Skip to main content

Integrating Microsoft OAuth with Web3Auth for Decentralized Authentication

microsoftOAuthauthenticationgithubWeb3Auth Team | February 28, 2024

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-byoa/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:

Microsoft flow

  • When a user logs in with Microsoft, Microsoft sends a JWT id_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

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.

Custom JWT Provider in Web3Auth Dashboard

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)

Custom JWT Provider on Web3Auth Dashboard

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.