寻求基于NestJS实现Auth0 Authorization Code Grant流程的示例
Got it, let's walk through a complete, working example of implementing Auth0's Authorization Code Grant flow with NestJS. I'll break this down into simple, actionable steps so you can replicate it easily.
1. Initialize NestJS Project & Install Dependencies
First, create a new NestJS project if you don't have one already:
nest new nest-auth0-acg cd nest-auth0-acg
Next, install all the packages we'll need for Auth0 integration, configuration, and authentication:
npm install @nestjs/config passport passport-jwt express-openid-connect npm install --save-dev @types/passport-jwt
2. Configure Auth0 Environment Variables
Create a .env file in your project root and add these Auth0-specific values (replace with your actual Auth0 tenant details):
AUTH0_DOMAIN=your-auth0-domain.us.auth0.com AUTH0_CLIENT_ID=your-auth0-client-id AUTH0_CLIENT_SECRET=your-auth0-client-secret AUTH0_CALLBACK_URL=http://localhost:3000/auth/callback AUTH0_AUDIENCE=https://your-auth0-api-audience.com
Then, enable environment variable loading in your app.module.ts by importing the ConfigModule:
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { AuthModule } from './auth/auth.module'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), // Makes env vars available globally AuthModule, ], }) export class AppModule {}
3. Set Up Auth0 Authentication Middleware
We'll use express-openid-connect to handle the heavy lifting of the Authorization Code flow (redirecting to Auth0, handling the callback, exchanging the code for tokens).
Create a src/auth/auth0.middleware.ts file:
import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; import { auth } from 'express-openid-connect'; import { ConfigService } from '@nestjs/config'; @Injectable() export class Auth0Middleware implements NestMiddleware { constructor(private configService: ConfigService) {} use(req: Request, res: Response, next: NextFunction) { auth({ issuerBaseURL: `https://${this.configService.get('AUTH0_DOMAIN')}`, baseURL: 'http://localhost:3000', clientID: this.configService.get('AUTH0_CLIENT_ID'), clientSecret: this.configService.get('AUTH0_CLIENT_SECRET'), authorizationParams: { response_type: 'code', audience: this.configService.get('AUTH0_AUDIENCE'), scope: 'openid profile email', }, redirectUri: this.configService.get('AUTH0_CALLBACK_URL'), session: { secret: 'your-session-secret-here', // Use a secure secret in production }, })(req, res, next); } }
Register this middleware in app.module.ts:
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { AuthModule } from './auth/auth.module'; import { Auth0Middleware } from './auth/auth0.middleware'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), AuthModule, ], }) export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer) { consumer.apply(Auth0Middleware).forRoutes('auth'); } }
4. Create Auth Controller & Routes
Now let's build the endpoints to handle login, callback, and fetching user profile data.
Create src/auth/auth.controller.ts:
import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common'; import { Request, Response } from 'express'; import { AuthGuard } from './auth.guard'; @Controller('auth') export class AuthController { // Redirect user to Auth0 login page @Get('login') login(@Req() req: Request) { req.oidc.login({ returnTo: '/auth/profile' }); } // Handle Auth0 callback (tokens are automatically stored in session) @Get('callback') callback(@Res() res: Response) { res.redirect('/auth/profile'); } // Protected route: Get authenticated user profile @Get('profile') @UseGuards(AuthGuard) getProfile(@Req() req: Request) { return { user: req.oidc.user, accessToken: req.oidc.accessToken, }; } // Logout user and clear session @Get('logout') logout(@Req() req: Request, @Res() res: Response) { req.oidc.logout({ returnTo: 'http://localhost:3000' }); } }
5. Create an Auth Guard for Protected Routes
To protect routes and ensure only authenticated users can access them, create src/auth/auth.guard.ts:
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Request } from 'express'; @Injectable() export class AuthGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest<Request>(); return request.oidc.isAuthenticated(); } }
6. Set Up Auth Module
Wrap everything up in an AuthModule (src/auth/auth.module.ts):
import { Module } from '@nestjs/common'; import { AuthController } from './auth.controller'; import { AuthGuard } from './auth.guard'; @Module({ controllers: [AuthController], providers: [AuthGuard], exports: [AuthGuard], }) export class AuthModule {}
Key Notes to Remember
- Auth0 Console Configuration: Make sure your
AUTH0_CALLBACK_URLis added to the "Allowed Callback URLs" in your Auth0 application settings. Also, verify "Allowed Logout URLs" if you're using the logout endpoint. - Production Considerations: In production, use a secure session secret, HTTPS for all URLs, and store sensitive env vars in a secure vault (not
.envfiles). - Token Validation: If you need to validate access tokens for API routes (instead of using session-based auth), you can use
passport-jwtto create a JWT strategy that verifies tokens against Auth0's JWKS endpoint.
内容的提问来源于stack exchange,提问作者Francesco Borzi

