Skip to main content

Integrating Telegram OAuth with Web3Auth for Authentication

telegramoauthauthenticationWeb3Auth Team | March 8, 2024

This guide will cover the basics of how to integrate Web3Auth with Telegram OAuth for authentication. Web3Auth is employed to provide Ethereum private key access and public address and Telegram OAuth is used to authenticate users

Full example: https://github.com/Web3Auth/web3auth-core-kit-examples/tree/main/web3auth-byoa/telegram-oauth-connection

We use two web3auth libraries in this project: @web3auth/ethereum-provider and @web3auth/node-sdk. Also we are usign a telegram libray @telegram-auth/server.

To install them, run: npm install @web3auth/ethereum-provider @web3auth/node-sdk @telegram-auth/server

How it works?

Telegram is usign a particular Oauth flow. To start it, we need to call the Telegram Login Widget. This widget will open a new window to the user to login into Telegram. After the user logs in, Telegram will send a the user information to callback url, that we have to validate. After that we will send the user information to Web3Auth to get the Ethereum private key and public address.

Create a JWKS file

A JWKS stands for JSON Web Key Set. It is a set of keys containing the public keys that should be used to verify any JSON Web Token (JWT) issued by the authorization server and signed using the RS256 signing algorithm.

If you don't know how to create a JWKS, you can follow this web3auth tutorial. This file must be located on a public endpoint. To test the example, you will need to modify the file located in the root directory of the project.

Both the private and the public keys, that you used to create the JWKS, must be in the server directory. In our project, they are called private.pem and public.pem.

Set up Custom JWT Verifier

Custom JWT Provider on Web3Auth Dashboard

To create a custom verifier for your JWT Provider, you'll need the follow this steps:

  1. The verifier Identifier, which would be the name. This name should be used in your .ENV file as WEB3AUTH_VERIFIER.

  2. JWT Verifier ID: JWT Verifier ID is the unique identifier to publicly represent a user on a verifier. e.g: sub, email, or even a custom field of your JWT payload that is unique in your system for each user. In this case, we are using the sub field.

  3. JWK Endpoint: An endpoint containing the JWKS used to sign the JWT. In my example I'm using a static github url file.

  4. In the Select JWT Validation. You will add iss and aud fields (eplace both with your real Github Client ID.).

How to create a Bot in telegram

create a bot

  • In the search box from the Telegram App, search for @BotFather.
  • Click on the BotFather and then click on the start button.
  • Click on the /newbot command.
  • Choose a name for your bot, description and an image.
  • Also you will need to add a Domain. This domain will be used to validate the callback url. As Telegram don't allow a callback to localhost, we are going to use ngrok to get a https address of our localhost app. (you can change this domain later with /setDomain command)
  • After creating the bot, you can use the command /token to get the token of your bot. You will need the name of the bot and the token in the .ENV file.

Set the domain in the bot

Running the example

Run the application in 2 consoles:

ngrok http 5005
npm start
  1. Add the URL from ngrok to the .env file as SERVER_HOST_URL and go to the Telegram Father Bot and send /setdomain and set the URL from ngrok from the your bot.

  2. Open your browser and navigate to http://<URL>/telegram/login to initiate the Telegram OAuth flow.

  3. Finally, after loginning in as a result, you will receive in the callback url a JSON with the user data, the JWT token, the Ethereum address and private key.

{
"user": {
"id": "<id>",
"first_name": "<name>",
"username": "<user>",
"photo_url": "https://t.me/i/userpic/320/...lkx13ek4.jpg",
"auth_date": "1710254881"
},
"JWTtoken": "eyJhbGciO...7FhzkQOw",
"ethData": {
"ethPrivateKey": "a310362754543e....2d726ed6",
"ethPublicAddress": ["0xaad13359bb....2930e962278c19"]
}
}

Code guide

In the example, we are using express for the server. This are the Endpoint that we are using:

  • The initial endpoint to start the Telegram OAuth flow. Before we need to create the login.html file with the Telegram Login Widget.

Telegram login widget

app.get("/telegram/login", async (req, res) => {
// load file, replace string and send it
const file = path.join(__dirname, "login.html");
fs.readFile(file, "utf8", (err, data) => {
if (err) {
return console.log(err);
}
const result = data
.replace(/{{TELEGRAM_BOT_NAME}}/g, TELEGRAM_BOT_NAME)
.replace(/{{TELEGRAM_BOT_CALLBACK}}/g, TELEGRAM_REDIRECT_URI);

res.send(result);
});
});
  • The Callback endpoint validate de information and generate the private key with the JWT token.
app.get("/telegram/callback", async (req, res) => {
const token = TELEGRAM_BOT_TOKEN;
const validator = new AuthDataValidator({ botToken: token });
const data = objectToAuthDataMap(req.query || {});
try {
// validate the data
const user = await validator.validate(data);
const JWTtoken = generateJwtToken(user);
// get the private key and address
const ethData = await getPrivateKey(JWTtoken, user.id.toString());
res.json({ user, JWTtoken, ethData });
} catch (error) {
console.error(error);
}
});

In the getPrivateKey function, we use Web3auth to establish a connection with the provider and get both the address and the private key.

const getPrivateKey = async (idToken: string, verifierId: string) => {
const web3authNodeprovider = await web3auth.connect({
verifier: process.env.WEB3AUTH_VERIFIER,
verifierId,
idToken,
});
// The private key returned here is the CoreKit Key
const ethPrivateKey = await web3authNodeprovider.request({ method: "eth_private_key" });
const ethPublicAddress = await web3authNodeprovider.request({ method: "eth_accounts" });
const ethData = {
ethPrivateKey,
ethPublicAddress,
};
return ethData;
};

References