DEV Community

Cover image for How to make OAuth integrated login/registration form in Node.js
Jahongir Sobirov
Jahongir Sobirov

Posted on

How to make OAuth integrated login/registration form in Node.js

Let's make OAuth (like "Login with Google / Facebook / Github") integrated login/registration form in Node.js.
Firstly we'll make our project folder:

mkdir oauth-login && cd oauth-login
Enter fullscreen mode Exit fullscreen mode

And then we should install necessary libraries:

npm install express auth-verify ejs
Enter fullscreen mode Exit fullscreen mode

And our file structure will be like this:

|-- index.js
|-- package.json
|-- package-lock.json
|-- views/
|--   index.ejs
|--   profile.ejs
|-- node_modules/
Enter fullscreen mode Exit fullscreen mode

Let's make our index.js file by preparing ejs and our web server

const express = require('express');
const path = require('path');
const app = express();
app.set("view engine", "ejs"); // using ejs
app.set("views", path.join(__dirname, "views"));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

const PORT = 3000;
app.listen(PORT, ()=>{
   console.log(`Server running on ${PORT}...`);
});
Enter fullscreen mode Exit fullscreen mode

And now we should make our index.ejs file and insert it to our web server as response to users/clients:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Login with Google</title>

  <!-- Bootstrap 5 CDN -->
  <link
    href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
    rel="stylesheet"
  >

  <style>
    body {
      background: #f8f9fa;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .card {
      padding: 2rem;
      border-radius: 1rem;
      box-shadow: 0 4px 12px rgba(0,0,0,0.1);
      text-align: center;
    }

    .google-btn {
      background-color: white;
      border: 1px solid #ddd;
      border-radius: 5px;
      padding: 10px 20px;
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 10px;
      transition: all 0.2s;
    }

    .google-btn:hover {
      background-color: #f1f1f1;
    }

    .google-btn img {
      width: 20px;
      height: 20px;
    }
  </style>
</head>
<body>
  <div class="card">
    <h3 class="mb-3">Welcome Back 👋</h3>
    <p class="text-muted">Sign in with your Google account</p>

    <a href="/auth/google" class="google-btn mt-3 nav-link">
      <img src="https://www.svgrepo.com/show/355037/google.svg" alt="Google logo" />
      <span>Continue with Google</span>
    </a>
  </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

And index.js we'll add index page:

app.get('/', (req, res)=>{
   res.render('index');
});
Enter fullscreen mode Exit fullscreen mode

And our web looks like this:

Web app looks like

OAuth integration

Now we'll make real OAuth integrated login for getting user data from Google. Firstly we make connection to our google cloud for using Oauth.
You need make project in Google Cloud for this. So after getting client id and secret id we'll use auth-verify for connection:

const AuthVerify = require('auth-verify');
const auth = new AuthVerify({storeTokens: 'memory'});

// making connection with Google
const google = auth.oauth.google({
   clientId: 'YOUR_CLIENT_ID', 
   clientSecret: 'YOUR_CLIENT_SECRET', 
   redirectUri: 'http://localhost:3000/auth/google/callback' // we'll get user data at this page
});
Enter fullscreen mode Exit fullscreen mode

After making connection we'll send response to Google OAuth for getting user data for logging in system:

app.get('/auth/google', (req, res) => google.redirect(res));
Enter fullscreen mode Exit fullscreen mode

And then we'll get user data by code which sent by Google to our web server:
app.get('/auth/google/callback', async (req, res)=>{
const code = req.query.code;
try {
const user = await google.callback(code); // code sent by Google
res.render('profile', {user});
} catch(err){
res.status(500).send("Error: " + err.message);
}
});
And our profile.ejs:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>User Profile</title>
    <!-- Bootstrap 5 CSS CDN -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container py-5">
        <div class="row justify-content-center">
            <div class="col-md-6">
                <!-- Profile Card -->
                <div class="card shadow-sm">
                    <div class="card-body text-center">
                        <!-- Profile Picture -->
                        <img src="<%= user.picture %>" 
                             class="mb-3" 
                             width="100" style="border-radius:50%"
                             alt="Profile Picture" >

                        <!-- User Info -->
                        <h4 class="card-title"><%= user.name %></h4>
                        <p class="text-muted mb-1"><%= user.email %></p>

                        <!-- Action Buttons -->
                        <a href="/edit-profile" class="btn btn-primary btn-sm me-2">Edit Profile</a>
                        <a href="/logout" class="btn btn-outline-danger btn-sm">Logout</a>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Bootstrap 5 JS CDN -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

And the result:

Result

Full codes of index.js:

const express = require('express');
const path = require('path');
const app = express();
const AuthVerify = require('auth-verify');

app.set("view engine", "ejs"); // using ejs
app.set("views", path.join(__dirname, "views"));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

const auth = new AuthVerify({storeTokens: 'memory'});

// making connection with Google
const google = auth.oauth.google({
   clientId: 'YOUR_CLIENT_ID', 
   clientSecret: 'YOUR_SECRET_ID', 
   redirectUri: 'http://localhost:3000/auth/google/callback' // we'll get user data at this page
});

app.get('/auth/google', (req, res) => google.redirect(res));

app.get('/auth/google/callback', async (req, res)=>{
    const code = req.query.code;
    try {
        const user = await google.callback(code);
        // res.send(`
        //     <h2>Welcome, ${user.name}!</h2>
        //     <img src="${user.picture}" width="100" style="border-radius:50%">
        //     <p>Email: ${user.email}</p>
        //     <p>Access Token: ${user.access_token.slice(0, 20)}...</p>
        // `);
        res.render('profile', {user});
    } catch(err){
        res.status(500).send("Error: " + err.message);
    }
});

app.get('/', (req, res)=>{
    res.render('index');
});

const PORT = 3000;
app.listen(PORT, ()=>{
   console.log(`Server running on ${PORT}...`);
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)