
Cloud
Learning Level
Advanced authentication patterns enable implementing OAuth 2.0, OpenID Connect, service-to-service authentication, and attribute-based access control (ABAC).
By the end of this lesson, you'll understand:
const express = require('express');
const {google} = require('googleapis');
const app = express();
const oauth2Client = new google.auth.OAuth2(
process.env.OAUTH_CLIENT_ID,
process.env.OAUTH_CLIENT_SECRET,
process.env.OAUTH_REDIRECT_URL
);
// Step 1: Generate authorization URL
app.get('/auth', (req, res) => {
const authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: ['openid', 'email', 'profile'],
state: generateRandomState()
});
res.redirect(authUrl);
});
// Step 2: Handle callback with authorization code
app.get('/oauth/callback', async (req, res) => {
const {code, state} = req.query;
if (!verifyState(state)) {
return res.status(400).send('State verification failed');
}
try {
const {tokens} = await oauth2Client.getToken(code);
oauth2Client.setCredentials(tokens);
// Store refresh token securely
saveRefreshToken(tokens.refresh_token);
res.cookie('idToken', tokens.id_token, {
httpOnly: true,
secure: true,
sameSite: 'strict'
});
res.redirect('/dashboard');
} catch (error) {
res.status(500).send('Authentication failed');
}
});
// Step 3: Refresh access token using refresh token
async function refreshAccessToken() {
const refreshToken = getRefreshToken();
const {credentials} = await oauth2Client.refreshAccessToken();
saveAccessToken(credentials.access_token);
return credentials.access_token;
}const {JwtRsaVerifier} = require('aws-jwt-verify');
const verifier = JwtRsaVerifier.create({
issuer: 'https://accounts.google.com',
audience: process.env.OAUTH_CLIENT_ID,
clientId: process.env.OAUTH_CLIENT_ID
});
async function verifyIdToken(token) {
try {
const payload = await verifier.verify(token);
return {
userId: payload.sub,
email: payload.email,
emailVerified: payload.email_verified,
name: payload.name,
picture: payload.picture
};
} catch (error) {
throw new Error('Token verification failed');
}
}
// Middleware to authenticate requests
const authMiddleware = async (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).send('No token provided');
}
try {
req.user = await verifyIdToken(token);
next();
} catch (error) {
res.status(403).send('Invalid token');
}
};// Microservice A calling Microservice B
async function makeAuthenticatedRequest(targetService) {
const auth = new google.auth.GoogleAuth({
scopes: ['https://www.googleapis.com/auth/cloud-platform']
});
const client = await auth.getClient();
const res = await client.request({
url: `https://${targetService}/api/data`,
method: 'GET'
});
return res.data;
}
// Microservice B verifying caller
const {IdTokenVerifier} = require('@google-cloud/service-account');
const verifier = new IdTokenVerifier();
const verifyCallerMiddleware = async (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).send('No authorization header');
}
const token = authHeader.split(' ')[1];
try {
const claims = await verifier.verify(token, {
audience: 'https://my-service'
});
req.caller = claims;
next();
} catch (error) {
res.status(403).send('Invalid token');
}
};class ABACPolicyEngine {
constructor() {
this.policies = [];
}
addPolicy(policy) {
this.policies.push(policy);
}
canAccess(subject, action, resource) {
for (const policy of this.policies) {
if (this.matchesPolicy(subject, action, resource, policy)) {
return true;
}
}
return false;
}
matchesPolicy(subject, action, resource, policy) {
return (
this.attributeMatches(subject.attributes, policy.subjectAttributes) &&
this.attributeMatches(action.attributes, policy.actionAttributes) &&
this.attributeMatches(resource.attributes, policy.resourceAttributes)
);
}
attributeMatches(actual, required) {
for (const [key, value] of Object.entries(required)) {
if (actual[key] !== value) return false;
}
return true;
}
}
// Usage
const abac = new ABACPolicyEngine();
abac.addPolicy({
name: 'read_draft_posts',
subjectAttributes: {role: 'author'},
actionAttributes: {action: 'read'},
resourceAttributes: {type: 'post', status: 'draft'}
});
abac.addPolicy({
name: 'publish_posts',
subjectAttributes: {role: 'editor'},
actionAttributes: {action: 'publish'},
resourceAttributes: {type: 'post'}
});
// Check access
const canAccess = abac.canAccess(
{attributes: {role: 'author', department: 'content'}},
{attributes: {action: 'read'}},
{attributes: {type: 'post', status: 'draft'}}
);Learn about federated identity and cross-organization access, or explore advanced IAM conditions.
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward