Welcome folks today in this blog post we will be building the github
login in node.js and express using oauth2
and then getting the accessToken
inside the sessions
in browser using javascript. All the full source code of the application is shown below.
Get Started
In order to get started you need to make a new node.js
project using the below command as shown below
npm init -y
npm i express
npm i axios
npm i dotenv
And after that you need to make the index.js
file and copy paste the following code
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
require('dotenv').config(); const axios = require('axios'); const express = require('express'); const path = require('path'); const app = express(); app.use(express.static('static')); app.get('/', (req, res) => { res.sendFile(path.join(__dirname, '/static/index.html')); }); app.listen(3000); // eslint-disable-next-line no-console console.log('App listening on port 3000'); |
As you can see we are rendering the index.html
file when the user goes to the /
route and then we are starting the express server at port 3000. And now we need to make the static
folder and inside it we need to make the index.html
file and copy paste the following code
static/index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <title>Github OAuth</title> <link href="https://fonts.googleapis.com/css2?family=Arvo&family=Kumbh+Sans&display=swap" rel="stylesheet" /> <style> body { height: 100vh; margin: 0; color: #222; font-family: 'Kumbh Sans', sans-serif; display: flex; justify-content: center; align-items: center; background: rgb(43, 186, 131); } .content { background: white; width: 380px; height: 480px; border-radius: 40px; text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: space-between; box-shadow: 0 3px 16px #222; } .content-bottom { margin: 10px 0; } h1 { font-family: 'Arvo', serif; font-size: 26px; margin: 32px auto 24px; line-height: 40px; } .img-github { margin-top: 32px; width: 160px; height: 160px; } .btn { text-decoration: none; display: block; width: 220px; line-height: 38px; padding-top: 2px; border-radius: 20px; color: white; background: rgba(71, 43, 186, 1); margin: 0 auto; border: none; font-size: 14px; } input[type='text'] { width: 180px; line-height: 32px; margin-bottom: 12px; padding-left: 12px; } .sign-in-text { font-size: 14px; line-height: 22px; } .party-popper { display: inline-block; font-size: 52px; margin-bottom: 24px; } </style> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> </head> <body> <div class="content unauthorized"> <div class="top"> <img class="img-github" src="github.png" /> <h1>Happy to see you<br />newcomer 👋</h1> </div> <div class="content-bottom"> <a class="btn" href="/auth">SIGN IN WITH GITHUB</a> <p class="sign-in-text">in order to get started</p> </div> </div> <div class="content authorized" style="display: none"> <div class="top"> <img class="img-github" src="github.png" /> <h1><span class="party-popper">🎉</span><br />Awesome!<br />You're authorized 🔒</h1> </div> </div> <script type="text/javascript" src="main.js"></script> </body> </html> |
As you can see we have a simple login with github
button shown on the webpage when the user hits this button we will be redirected to the consent screen
where user can grant the access and select the account. And now we need to create the .env
file where we need to insert the clientId
and secret
as shown below
.env
1 2 |
GITHUB_CLIENT_ID=##clientid## GITHUB_SECRET=##clientsecret## |
And now you need to copy the above clientid
and secret
and store it inside the .env
file. And now we need to add the below code inside the index.js
file as shown below
index.js
1 2 3 4 5 |
app.get('/auth', (req, res) => { res.redirect( `https://github.com/login/oauth/authorize?client_id=${process.env.GITHUB_CLIENT_ID}`, ); }); |
As you can see we are redirecting the user
to the github oauth2 consent screen where we provide the clientId
and then we will be getting the authorization code as shown below. Now we need to add the javascript
code inside the index.html
file as shown below
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<script> const URL_PARAMS = new URLSearchParams(window.location.search); const TOKEN = URL_PARAMS.get('token'); // Show an element const show = (selector) => { document.querySelector(selector).style.display = 'block'; }; // Hide an element const hide = (selector) => { document.querySelector(selector).style.display = 'none'; }; if (TOKEN) { hide('.content.unauthorized'); show('.content.authorized'); } </script> |
As you can see we are showing and hiding the panel
according to the token
that we have inside the urlsearchparams
as shown below
And now we need to write the /oauth2-callback
route inside the index.js file
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
app.get('/oauth-callback', ({ query: { code } }, res) => { const body = { client_id: process.env.GITHUB_CLIENT_ID, client_secret: process.env.GITHUB_SECRET, code, }; const opts = { headers: { accept: 'application/json' } }; axios .post('https://github.com/login/oauth/access_token', body, opts) .then((_res) => _res.data.access_token) .then((token) => { // eslint-disable-next-line no-console console.log('My token:', token); res.redirect(`/?token=${token}`); }) .catch((err) => res.status(500).json({ err: err.message })); }); |
As you can see we are providing the clientId
and secret
and also providing the code as well. And then we are using the axios
library to make the post request to get the accessToken
and then we are redirecting the user to /
route where we are providing the token in the urlparams.