Skip to content

Instantly share code, notes, and snippets.

@System3-2
Created May 16, 2023 19:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save System3-2/aefdf449e51e7f8e9d30eb2cd3fda7c0 to your computer and use it in GitHub Desktop.
Save System3-2/aefdf449e51e7f8e9d30eb2cd3fda7c0 to your computer and use it in GitHub Desktop.
Nestjs authentication strategy public
npm install --save @nestjs/passport passport-jwt passport-google-oauth20 passport-github2
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { AuthService } from '../auth.service';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
constructor(private authService: AuthService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: 'secret',
});
}
async validate(payload: any) {
const user = await this.authService.validateUser(payload.username);
return user;
}
}
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-google-oauth20';
import { AuthService } from '../auth.service';
@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor(private authService: AuthService) {
super({
clientID: 'google_client_id',
clientSecret: 'google_client_secret',
callbackURL: 'http://localhost:3000/auth/google/callback',
scope: ['profile'],
});
}
async validate(accessToken: string, refreshToken: string, profile: any, done: any) {
const user = await this.authService.validateOAuthUser('google', profile.id);
done(null, user);
}
}
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-github2';
import { AuthService } from '../auth.service';
@Injectable()
export class GithubStrategy extends PassportStrategy(Strategy, 'github') {
constructor(private authService: AuthService) {
super({
clientID: 'github_client_id',
clientSecret: 'github_client_secret',
callbackURL: 'http://localhost:3000/auth/github/callback',
});
}
async validate(accessToken: string, refreshToken: string, profile: any, done: any) {
const user = await this.authService.validateOAuthUser('github', profile.id);
done(null, user);
}
}
import { ExecutionContext, Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class MultiAuthGuard extends AuthGuard(['jwt', 'google', 'github']) {
canActivate(context: ExecutionContext) {
return super.canActivate(context);
}
}
import { Controller, Get, UseGuards } from '@nestjs/common';
import { MultiAuthGuard } from './guards/multi-auth.guard';
@Controller()
export class AppController {
@Get('protected')
@UseGuards(MultiAuthGuard)
protectedRoute() {
return 'Protected route';
}
}
npm install --save @nestjs/passport passport-jwt
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { AuthService } from '../auth.service';
import { JwtBlacklistService } from './jwt-blacklist.service';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
constructor(private authService: AuthService, private jwtBlacklistService: JwtBlacklistService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: 'secret',
});
}
async validate(payload: any) {
const tokenIsBlacklisted = await this.jwtBlacklistService.tokenIsBlacklisted(payload.jti);
if (tokenIsBlacklisted) {
throw new Error('Invalid token');
}
const user = await this.authService.validateUser(payload.username);
return user;
}
}
import { Injectable } from '@nestjs/common';
@Injectable()
export class JwtBlacklistService {
private readonly blacklist: Set<string> = new Set();
addToBlacklist(tokenId: string, expiresIn: number) {
this.blacklist.add(tokenId);
setTimeout(() => {
this.blacklist.delete(tokenId);
}, expiresIn * 1000);
}
async tokenIsBlacklisted(tokenId: string) {
return this.blacklist.has(tokenId);
}
}
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
// ...
public readonly name = 'jwt';
// ...
}
@Injectable()
export class GoogleStrategy extends PassportStrategy(OAuth2Strategy, 'google') {
// ...
public readonly name = 'google';
// ...
}
@Injectable()
export class GithubStrategy extends PassportStrategy(OAuth2Strategy, 'github') {
// ...
public readonly name = 'github';
// ...
}
@Controller('auth')
export class AuthController {
constructor(private jwtBlacklistService: JwtBlacklistService) {}
@Post('logout')
@UseGuards(AuthGuard('jwt'), AuthGuard('google'), AuthGuard('github'))
async logout(@Request() req: any, @Query('strategy') strategy: string) {
switch (strategy) {
case 'jwt':
const tokenId = req.user.jti;
const expiresIn = req.user.exp - req.user.iat;
this.jwtBlacklistService.addToBlacklist(tokenId, expiresIn);
break;
case 'google':
// Add code to blacklist the Google token
break;
case 'github':
// Add code to blacklist the Github token
break;
default:
throw new BadRequestException('Invalid strategy');
}
return { message: 'Logout successful' };
}
}
npm install google-auth-library
import { OAuth2Client } from 'google-auth-library';
constructor(private readonly configService: ConfigService) {}
const googleConfig = this.configService.get('google');
const oAuth2Client = new OAuth2Client(
googleConfig.clientId,
googleConfig.clientSecret,
googleConfig.redirectUri,
);
async revokeGoogleToken(token: string) {
await oAuth2Client.revokeToken(token);
}
await this.revokeGoogleToken(req.user.accessToken);
req.logout();
return { message: 'Logout successful' };
import { Controller, Post, Req, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ConfigService } from '@nestjs/config';
import { OAuth2Client } from 'google-auth-library';
@Controller('auth')
export class AuthController {
constructor(private readonly configService: ConfigService) {}
@Post('logout')
@UseGuards(AuthGuard('jwt'), AuthGuard('google'), AuthGuard('github'))
async logout(@Req() req: any) {
if (req.user.provider === 'google') {
await this.revokeGoogleToken(req.user.accessToken);
}
req.logout();
return { message: 'Logout successful' };
}
private async revokeGoogleToken(token: string) {
const googleConfig = this.configService.get('google');
const oAuth2Client = new OAuth2Client(
googleConfig.clientId,
googleConfig.clientSecret,
googleConfig.redirectUri,
);
await oAuth2Client.revokeToken(token);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment