Integrating Telegram OAuth with Web3Auth for Authentication
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
To create a custom verifier for your JWT Provider, you'll need the follow this steps:
-
The verifier Identifier, which would be the name. This name should be used in your .ENV file as
WEB3AUTH_VERIFIER
. -
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 thesub
field. -
JWK Endpoint: An endpoint containing the JWKS used to sign the JWT. In my example I'm using a static github url file.
-
In the Select JWT Validation. You will add
iss
andaud
fields (eplace both with your real Github Client ID.).- The
iss
field is the issuer of the JWT. In this case "https://telegram.com"
- The
How to create a Bot in telegram
- 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.
Running the example
Run the application in 2 consoles:
ngrok http 5005
npm start
-
Add the URL from ngrok to the
.env
file asSERVER_HOST_URL
and go to the Telegram Father Bot and send/setdomain
and set the URL from ngrok from the your bot. -
Open your browser and navigate to
http://<URL>/telegram/login
to initiate the Telegram OAuth flow. -
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.
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