Alex Awesome
Posted on March 24, 2023
You can make authorization via Telegram another way. It works. But today we want to do the classic OAuth Authorization.
Before you begin, you need to create a Telegram bot and obtain your bot token. You can do this in @BotFather
in Telegram. For more information on initiating a bot, read the Telegram Bot API documentation: https://core.telegram.org/bots
Redirect Users to Telegram's OAuth URL
To initiate the OAuth process, you'll need to redirect users to the following URL:
https://oauth.telegram.org/auth?bot_id=YOUR_BOT_ID&scope=YOUR_SCOPE&public_key=YOUR_PUBLIC_KEY&nonce=YOUR_NONCE
You have to replace YOUR_BOT_ID
, YOUR_SCOPE
, YOUR_PUBLIC_KEY
, and YOUR_NONCE
with your bot's specific information. The nonce
is a unique, randomly generated string that you'll need to store for later validation.
Handle Telegram's OAuth Callback
After the user authorizes your application, Telegram will redirect them back to your site with a URL that contains a hash and a payload. You'll need to verify the hash, parse the payload, and store the user's information.
That's it! I could wrap up this article. But ok, I am going to add the examples in languages that I use: PHP, Node.js, and Golang.
PHP Example:
<?php
$botToken = 'YOUR_BOT_TOKEN';
// Extracting the hash and payload from the request
$hash = $_GET['hash'];
$payload = json_decode(base64_decode($_GET['payload']), true);
// Verifying the hash
$secretKey = hash('sha256', $botToken, true);
$checkHash = hash_hmac('sha256', $payload, $secretKey);
if ($hash !== $checkHash) {
die('Invalid hash.');
}
// Extracting user information from the payload
$user = $payload['user'];
$userId = $user['id'];
$firstName = $user['first_name'];
$lastName = $user['last_name'];
$username = $user['username'];
// Store user information in your database
// ...
?>
Node.js Example:
const crypto = require('crypto');
const url = require('url');
const querystring = require('querystring');
const botToken = 'YOUR_BOT_TOKEN';
const handleTelegramOAuthCallback = (req, res) => {
const parsedUrl = url.parse(req.url);
const queryParams = querystring.parse(parsedUrl.query);
const hash = queryParams.hash;
const payload = JSON.parse(Buffer.from(queryParams.payload, 'base64').toString());
const secretKey = crypto.createHash('sha256').update(botToken).digest();
const checkHash = crypto.createHmac('sha256', secretKey).update(queryParams.payload).digest('hex');
if (hash !== checkHash) {
res.status(400).send('Invalid hash');
return;
}
const user = payload.user;
const userId = user.id;
const firstName = user.first_name;
const lastName = user.last_name;
const username = user.username;
// Store user information in your database
// ...
};
// Use the handleTelegramOAuthCallback function as a request handler in your web server
Golang Example:
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"log"
"net/http"
)
const (
botToken = "YOUR_BOT_TOKEN"
)
type User struct {
Id int64 `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Username string `json:"username"`
}
type Payload struct {
User User `json:"user"`
}
func handleTelegramOAuthCallback(w http.ResponseWriter, r *http.Request) {
hash := r.URL.Query().Get("hash")
payloadB64 := r .URL.Query().Get("payload")
payloadBytes, err := base64.StdEncoding.DecodeString(payloadB64)
if err != nil {
http.Error(w, "Invalid payload", http.StatusBadRequest)
return
}
var payload Payload
err = json.Unmarshal(payloadBytes, &payload)
if err != nil {
http.Error(w, "Invalid payload", http.StatusBadRequest)
return
}
h := hmac.New(sha256.New, []byte(botToken))
h.Write([]byte(payloadB64))
checkHash := hex.EncodeToString(h.Sum(nil))
if hash != checkHash {
http.Error(w, "Invalid hash", http.StatusBadRequest)
return
}
user := payload.User
userId := user.Id
firstName := user.FirstName
lastName := user.LastName
username := user.Username
// Store user information in your database
// ...
}
func main() {
http.HandleFunc("/telegram-oauth-callback", handleTelegramOAuthCallback)
log.Fatal(http.ListenAndServe(":8080", nil))
}
It's very easy, isn't it?
Of course, these are not the best blocks of code ever, but they help to understand how to work with it.
Posted on March 24, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.