How to integrate Github OAuth with Web3Auth
This guide will cover the basics of how to integrate Web3Auth with GitHub OAuth for authentication. Web3Auth is employed to provide Ethereum private key access and public address and GitHub OAuth is used to authenticate users
Full example: https://github.com/Web3Auth/web3auth-core-kit-examples/tree/main/single-factor-auth-node/github-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?
As explain in the github OAuth Docs, The web integration would be like this steps:
-
Request a user's GitHub identity
GET https://github.com/login/oauth/authorize
-
Users are redirected back to your site by GitHub
- Exchange this code for an access token:
POST https://github.com/login/oauth/access_token
-
Accept: application/json
{
"access_token":"gho_16C7e42....e178B4a",
"scope":"repo,gist",
"token_type":"bearer"
}
-
The Token is sent to Web3auth (Instead of access the Github API.)
- Github sends a
id_token
to the app. This JWT token is sent to the Web3Auth SDK's login function. 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.
- Github sends a
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://github.com" - The
aud
field is the audience of the JWT. In this case "https://github.com/login/oauth/access_token"
- The
How to create a App in Github
- In the upper-right corner of any page on GitHub, click your profile photo.
- Navigate to your account settings.
- For an app owned by a personal account, click Settings.
- For an app owned by an organization: (Click Your organizations.)
- To the right of the organization, click Settings.
- In the left sidebar, click Developer settings.
- In the left sidebar, click GitHub Apps or OAuth apps.
You have to configure you Homepage URL: http://localhost:5005
and the callback URL
http://localhost:5005/github/callback
After creating the app, you'll need the Client Application ID into the .ENV file. Then click on "Generate a new client secret" and copy to use it also in the .ENV file.
Running the example
Execute npm run dev
. To initiate the Github OAuth flow, Open your browser to
http://localhost:5005/github/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":{
"login":"<alias>",
"id":<id>,
"node_id":"MSSSSS",
"gravatar_id":"",
"url":"https://api.github.com/users/<name>",
"type":"User",
"site_admin":false,
"name":"Name",
"company":"Web3Auth",
"location":"AR, CABA",
"email":null,
"hireable":null,
"bio":"<description>",
"twitter_username":null,
"public_repos":43,
"public_gists":0,
"followers":10,
"following":12,
"created_at":"2011-07-28T17:24:29Z",
"updated_at":"2024-02-29T15:54:30Z"
},
"jwtToken":"eyJhbGciOiJSUzI1NiIsInR5cC....oWw",
"ethData":{
"ethPrivateKey":"f8fe70c14868b709b0....1498a9db5",
"ethPublicAddress":[
"0x3d9c0cfff5c0a25....5a53fd6f4b678990f9"
]
}
}
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 Github OAuth flow.
app.get("/github/login", (req, res) => {
res.redirect(
`https://github.com/login/oauth/authorize?client_id=${githubClientId}&redirect_uri=${githubRedirectUri}`,
);
});
- The Callback endpoint to receive the JWT token and exchange it for an access token.
app.get("/github/callback", async (req, res) => {
const code = req.query.code;
try {
const accessToken = await exchangeCodeForAccessToken(code);
const userData = await fetchGitHubUserDetails(accessToken);
const jwtToken = generateJwtToken(userData);
const ethData = await getPrivateKey(jwtToken, userData.id.toString());
res.json({ userData, jwtToken, ethData });
} catch (error) {
console.error(error);
res.status(500).send("Error during GitHub authentication");
}
});
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