Integrate Microsoft OAuth with Web3Auth
This guide will cover the basics of how to integrate Web3Auth with OAuth 2.0, using Microsoft Github authentication. Trying to explain all the flow and covering all the problems that can happen during the integration. Web3Auth is employed to provide Ethereum private key access and public address.
Full example: https://github.com/Web3Auth/web3auth-core-kit-examples/tree/main/single-factor-auth-node/microsoft-oauth-connection
We use two web3auth libraries in this project: @web3auth/ethereum-provider
and
@web3auth/node-sdk
.
To install them, run: npm install @web3auth/ethereum-provider @web3auth/node-sdk
How it works?
When integrating Web3Auth with Microsoft Login the flow looks something like this:
-
When a user logs in with
Microsoft
, Microsoft sends a JWTid_token
to the app. This JWT token is sent to the Web3Auth SDK's login function. -
Finally, on successful validation of the JWT token, Web3Auth SDK will generate a private key for the user, in a self custodial way, resulting in easy onboarding for your user to the application.
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.- The
iss
field is the issuer of the JWT. In this case "https://login.microsoftonline.com/" - The
aud
field is the audience of the JWT. In this case "http://login.microsoftonline.com/{AZURE_TENANT_ID}/v2.0/token"
- The
Configure a new Application in Microsoft Entra.
After creating the app, you'll need the Application (client) ID and the Directory (tenant) ID into the .ENV file. Then you can add a redirect URI (in our example is http://localhost:5005/ms/callback)
Finally in "Certificates & secrets" -> Client Secret -> New client secret and copy the value to the
.ENV file as AZURE_CLIENT_SECRET
.
Create a Proof Key of Code Exchange (PKCE)
The Proof Key of Code Exchange (PKCE) is an extension of the standard authorization code grant OAuth
flow. It is designed to be a secure substitute for the implicit flow for single-page applications
(SPA) or native applications. SPAs and native applications are vulnerable to reverse engineering
practices. To create one you can go to this
PKCE generator. First click on "generate code
Verfier" and then into "Generate Code Challenge". Both values will be used in the .ENV file as
AZURE_CODE_VERIFIER
and AZURE_CODE_CHALLENGE
.
Running the example
Execute npm run dev
. To initiate the Microsoft OAuth flow, Open your browser to
http://localhost:5005/ms/login
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.
{
"userData": {
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [],
"displayName": "Display ... Name",
"givenName": "Name",
"jobTitle": null,
"mail": null,
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": "en",
"surname": "Raw",
"userPrincipalName": "data_gmail.com#EXT#@datagmail.onmicrosoft.com",
"id": "63af4d94-1ea4-4b0b-aaa9-0da5d044xxxx"
},
"jwtToken": "eyJhbGci ... z9HgEQOcYTg",
"ethData": {
"ethPrivateKey": "b070a6 ... 3536",
"ethPublicAddress": ["0xb31181bd22b57f994d ... d2ff72ad0631251fd"]
}
}
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 Microsoft OAuth flow.
app.get("/ms/login", async (req: any, res: any) => {
const oauthUrl = `${MICROSOFT_URL}/${azureTenantId}/oauth2/v2.0/authorize?
client_id=${azureClientId}
&response_type=code
&redirect_uri=${encodeURIComponent(azureRedirectUri)}
&response_mode=query
&scope=User.ReadBasic.All
&state=w3a_microsoft
&prompt=login
&code_challenge=${azurCodeChallenge}
&code_challenge_method=S256`;
res.redirect(oauthUrl);
});
- The Callback endpoint to receive the JWT token and exchange it for an access token.
app.get("/ms/callback", async (req: any, res: any) => {
const code = req.query.code;
try {
const accessToken = await exchangeCodeForAccessToken(code);
const userData = await fetchMicrosoftUserDetails(accessToken);
const jwtToken = generateJwtToken(userData);
const ethData = await getPrivateKey(jwtToken, userData.id.toString());
res.json({ userData, jwtToken, ethData });
} catch (error) {
res.status(500).send("Error during Microsoft authentication callback");
}
});
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
Conclusion
By following the steps outlined here, developers can seamlessly incorporate Web3Auth into their applications. This guide serves as a comprehensive resource for developers seeking to integrate Web3Auth and Microsoft Github users authenticate with OAuth 2.0 Flow. Also can be a starting point for developers who want to integrate Web3Auth with other OAuth providers.