Telegram authorization without default button
Asked Answered
G

4

20

The only documented way to use Telegram 3-rd party authorization is to use their script that is being provided at https://core.telegram.org/widgets/login

This script (as I digged) works in pretty strange way

  1. It renders "Log in with Telegram" button inside the iframe with another extra script that loads some Telegram entities to work with (like TWidgetLogin, TSticker (?), TVideo (??), TAudio (???) and some others).
  2. By clicking on button, this iframe opens new window that is performing authorization.
  3. After authorization is being completed, this window is being closed, and since it's done, the iframe checks the authorization again. If it's done in right way, the iframe retrieves all shared user info and dependent on type of authorization end calls data-onauth or sends request to data-auth-url.

This behaviour is really unusable for me, because we are also using Google , Github and Facebook OAuths nearby, and all of them are providing the normal usable API to open authorization windows manually and do redirects to specified url.

I mean, that's how our, for example, Google authorization works:

  1. User clicks on button that is created on our own, customized to match our application style.
  2. On click, our application creates new window with url https://hostname/some/path/to/auth?and_some_params=here
  3. Our server catches this and redirects to Google OAuth consent screen.
  4. After Google authorization is being completed, it redirects user to another /some/path/to/completed_authorization
  5. Server retrieves all necessary information, and redirects window to /some/path/to/success_authorization that has script with window.postMessage to parent window with authorization info.
  6. Parent window (application window) catches this message, closes window and fills storage with given user data.

And thats done. Since opened window is being opened by application, it can be controlled and closed when it's not in use (e.g. when another auth window is being opened, or when the application tab is being closed).

What is unsuitable in telegram "Log in with telegram" button is:

  1. No possibility to stylize button to match application style
  2. No possibility to change content of the button (in our case it is necessary, because our application is multilanguage).
  3. No possibility to control opened window (it is being opened even if the main window is closed)

For now I can open a window with Telegram OAuth screen using

// some code above
this.popup = window.open("https://oauth.telegram.org/auth?bot_id=<my_bot_id>&origin=http%3A%2F%2F<mydevorigin>&request_access=write, "authWindow", <some window params>)
// some code below

But since authorization is being completed, I cannot set anything to let server know that it should retrieve user data and redirect to my page with window.postMessage

Is there any way to achieve Telegram authorization without their "Login with Telegram" button? Any help is highly appreciated.

Gorgonzola answered 28/5, 2019 at 18:11 Comment(6)
Telegram has introduced telegram.org/blog/… recently. Maybe you can use it as an alternative.Reverberatory
Would it be possible to visually hide the iframe and trigger a click on it when the user clicks on your styled button? I know this is a bit hacky and won't fix the issue of it opening a new tab/ window but it might be better than nothing.Spires
@Spires nope, because the iframe loads content from https://core.telegram.org/auth/embed and I have no access via JS to this button :(Gorgonzola
@AliHashemi Thank you a lot, I will check it deeper. But as far as I understood, this is a kind of server-less authorization. Or it requires implemetation of some bot logic, which is not suitable for our backend developer for obvious reasons :(Gorgonzola
I had the same issue (with wanting to have the same style as google oauth) and I've used the hacky way @Spires suggested. it works pretty good. about the issue you mentioned of not having access to the JS button, the iframe provides the data as a "push" event to the parent element of the iframe. (being your JS). If you're interested, I can provide my workaround as an answer.Gowrie
@Gorgonzola Hello! I'm a backend developer with the same problem. I've get iframe code, but coudn't move afterwards. Could you please provide found solution step-by-step for backend devs:) Thanks a lot in advance..Dowd
M
24

So there is an even easier way to do it, without directly listening to postMessages.

Telegram widget script https://telegram.org/js/telegram-widget.js adds Telegram object to the window, this object has Login property, which has auth function.

auth function accepts options and callback, like so:

declare const auth: (options: Options, callback: Callback) => void;

interface Options {
  bot_id: string;
  request_access?: boolean;
  lang?: string;
}

interface Data {
  auth_date: number;
  first_name: string;
  hash: string;
  id: number;
  last_name: string;
  username: string;
  // I think there could be other properties too
}

type Callback = (dataOrFalse: Data | false) => void;

Pay attention that callback will be called with false boolean if authorization is not successful.

So all you need to do is load widget script (without data attributes, because otherwise it will initialise iframe with button), then call this function whenever you need:

window.Telegram.Login.auth(
  { bot_id: 'YOUR_BOT_ID', request_access: true },
  (data) => {
    if (!data) {
      // authorization failed
    }

    // Here you would want to validate data like described there https://core.telegram.org/widgets/login#checking-authorization
    doWhateverYouWantWithData(data);
  }
);

auth will open another window with Telegram authorization interface and will listen to this window post messages by itself. When window closes your callback will be called.

Maryleemarylin answered 26/8, 2020 at 8:14 Comment(5)
So this above works perfectly. Now how do I access the userpic? I can see the API response from oauth.telegram.org/auth/get has html, origin and user. The user key appears in the data in the above code. The html key has the image link sitting inside, but I dont see how I can access it.Polyploid
This does not work — bot_id should be either domain or actual numeric id and neither of them works. When I pass username the script requires "bot id" (as it parses int inside js), and when I pass numeric ID I get "Bot domain invalid" errorFireguard
@Fireguard bot_id is a string type consisting of numbers, it looks like this "123456789". Don't try to pass domain name or bot nickname there, just use bot id. Do not to use bot_token here either, although it will work, you should not expose it on the client side. If you are getting domain error then you have misconfigured domain name, double check it.Maryleemarylin
How do you get the bot_id? I only have the usernameKhaki
@FezVrasta i got it working with the first part of the bot API token. As it was mentioned, dont use the whole bot token. only the part before the semicolon. ie for bot token 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw, you would only use 110201543Servant
G
7

@Limbo as I can see - the generated widget and code just create an iframe with the content based on our bot name and other params. It each time the same. For example for (https://oauth.telegram.org/embed/samplebot?origin=https%3A%2F%2Fcore.telegram.org&size=medium&userpic=false), the interested part in response is here:

<div class="tgme_widget_login medium nouserpic" id="widget_login"><button class="btn tgme_widget_login_button" onclick="return TWidgetLogin.auth();"><i class="tgme_widget_login_button_icon"></i>Log in with Telegram</button></div>

<script src="//telegram.org/js/widget-frame.js?27"></script>
<script>TWidgetLogin.init('widget_login', 547043436, {"origin":"https:\/\/core.telegram.org"}, false, "en");

And it will be the same each time. So, you just add this code to your page whre you can customize the button styles, and put in any place of the page as you want. Just take care of id param and not forget to add an event listener for onClick which will call the TWidgetLogin.auth() when you want to show the login popup.

The TWidgetLogin.init function accepts couple of the params (target_login_btn_id, bot_id, params, init_auth, lang). All of them is self-described.

The interesting part - is about the getting auth info. If you check that widget-frame.js you will find that after successful auth it calls window.parent.postMessage(JSON.stringify(data), origin || '*'); with user data in data param. In our case (we operate without iframe) the postMessage will be delivered to the current window and you will be able to catch it with simple code

window.addEventListener("message", function(event) {console.log('get message, evetn)}, false);

And its where you can get all user data that you need.

The only thing - the origin of that message. But this param scripts gets with user data from telegram servers, so I suspect that it will contain the linked site origin and we will not have any problems with that.

Good luck with further investigation.

Gipps answered 4/6, 2019 at 14:43 Comment(4)
Thank you for your answer. This is a kind of things that I've tried, but not in this way. As far as I undestand, this will cause Telegram OAuth window to post message to my application, but our backend won't catch the authorization fact in this case, so frontend should do this manually. There are some pros, but the main cons is that we can control the style and content of the button and this solves problem partially :)Gorgonzola
Yes, you will be forced to send that auth data to backend by your code, but that code is very simple and as you can see Telegram not provide oAuth in the "classic" way.Gipps
@MykolaPrymak Hello! I'm a backend developer with the same problem. I've get iframe code, but coudn't move afterwards. Could you please provide solution step-by-step for backend devs:) Thanks a lot in advance...Dowd
I have same code but I'm opening a tab with this url - file:///auth?bot_id=547043436&origin=https%3A%2F%2Fcore.telegram.org&embed=1&request_access=writeAbseil
G
0

Worth mentioning if you have "Prevent Cross-Site Tracking" enabled in Safari or "Allow Cross-Website Tracking" disabled in Chrome you won't be able to authorize since widget will not send any data

Gonyea answered 28/8, 2023 at 22:6 Comment(0)
C
-1

code This is my code. I use the custom element in TG Mini Apps to enter the authorization popup by clicking on the event. After completion, I can get the data in my Mini Apps. hope that may help you preview

Cimino answered 2/4 at 3:54 Comment(2)
Please read Why should I not upload images of code/data/errors?Braud
DO NOT post images of code, data, error messages, etc. - copy or type the text into the question. Please reserve the use of images for diagrams or demonstrating rendering bugs, things that are impossible to describe accurately via text.Pineal

© 2022 - 2024 — McMap. All rights reserved.