UNPKG

universal_authentication

Version:

Seamless and Secure Authentication for Modern Web Applications: Easily integrate OTP-based email verification, Google OAuth, GitHub, Microsoft, and Okta login into your Node.js app. Modular, flexible, and database-agnostic, this package simplifies user au

149 lines (138 loc) 5.04 kB
import axios from "axios"; import { IOAuthConfig } from "../interface/OAuth.interface"; // function to genrate OAuth url export const initiateLogin = ( provider: "google" | "github" | "microsoft" | "okta", clientId: string, redirectUri: string ): string => { const providerUrls = { google: `https://accounts.google.com/o/oauth2/v2/auth?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=profile email`, github: `https://github.com/login/oauth/authorize?client_id=${clientId}`, microsoft: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=${clientId}&response_type=code&redirect_uri=${redirectUri}&response_mode=query&scope=https://graph.microsoft.com/.default`, okta: `${process.env.OKTA_DOMAIN}/v1/authorize?client_id=${clientId}&response_type=code&scope=openid profile email&redirect_uri=${redirectUri}`, }; return providerUrls[provider]; }; //function to handle OAuth callback export const handleOAuthCallback = async ( code: string, provider: "google" | "github" | "microsoft" | "okta", config: IOAuthConfig ): Promise<any> => { try { if (!code) { return { status: 400, message: "Authorization code is missing" }; } // token urls of particular provider and their payloads const tokenUrls = { google: "https://oauth2.googleapis.com/token", github: "https://github.com/login/oauth/access_token", microsoft: "https://login.microsoftonline.com/common/oauth2/v2.0/token", okta: `${process.env.OKTA_DOMAIN}/oauth/token`, }; const tokenPayloads = provider === "google" ? { code, client_id: config.clientId, client_secret: config.clientSecret, redirect_uri: config.redirectUri, grant_type: "authorization_code", } : provider === "github" ? { client_id: config.clientId, client_secret: config.clientSecret, code, } : provider === "microsoft" ? { client_id: config.clientId, client_secret: config.clientSecret, code, redirect_uri: config.redirectUri, grant_type: "authorization_code", } : { grant_type: "authorization_code", code, redirect_uri: config.redirectUri, client_id: config.clientId, client_secret: config.clientSecret, }; // Microsoft-specific header for token exchange const tokenHeaders = provider === "microsoft" ? { "Content-Type": "application/x-www-form-urlencoded" } : { Accept: "application/json" }; //Exchange authorization code for access token const { data: tokenData } = await axios.post( tokenUrls[provider], tokenPayloads, { headers: tokenHeaders, } ); const accessToken = tokenData.access_token; if (!accessToken) { return { status: 400, message: "Failed to get access token" }; } //user profile url to fetch the particular user const userinfoUrls = { google: "https://www.googleapis.com/oauth2/v1/userinfo", github: "https://api.github.com/user", microsoft: "https://graph.microsoft.com/v1.0/me", okta: `${process.env.OKTA_DOMAIN}/v1/userinfo`, }; //fetch user profile from OAuth provider const { data: profileData } = await axios.get(userinfoUrls[provider], { headers: { Authorization: `Bearer ${accessToken}`, }, }); // extract relevant user details const userData = provider === "google" ? { providerId: profileData.id, name: profileData.name, email: profileData.email, provider, } : provider === "github" ? { providerId: profileData.id, username: profileData.login, name: profileData.name, provider, } : provider === "microsoft" ? { providerId: profileData.id, name: profileData.displayName, email: profileData.mail || profileData.userPrincipalName, provider, } : { providerId: profileData.sub, name: profileData.name, email: profileData.email, provider, }; //check if the user exist const existingUser = await config.findUserById(userData.providerId); if (!existingUser) { const newUser = await config.createUser(userData); return { status: 200, message: "User created successfully", user: newUser, }; } else { return { status: 200, message: "User already exist", user: existingUser }; } } catch (err) { return { status: 500, message: `Failed to get loged in to ${provider}` }; } };