Integrating Auth0 with NestJS - am unable to verify the access token within my API

Greetings, all.

In brief, I’m attempting to develop a GraphQL API that is guarded by an access token generated upon successful login. I’m copying and pasting the token into Postman and sending it with requests to a guarded resolver endpoint as an authorization header. I’ve verified that the token is indeed reaching the server as expected. The problem is that I seem to be unable to actually verify the token. Note that interpolation of things like environment variables, etc., is working and the application is compiling successfully. It’s just that I’m not sure how to validate the access token provided by Auth0. I could really use some help with this and would even be willing to offer a reward to anyone who could help me solve this matter. Thanks!

My setup looks like this:

app.module.ts
src/authorization
  - auth.guard.ts
  - authorization.module.ts
  - jwt.strategy.ts
src/products
  - products.resolver.ts

That’s it. Pretty simple. As to the files’ contents:

// src/app.module.ts

/* istanbul ignore file */
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ConfigModule } from '@nestjs/config';
import { ProductsModule, ProductsService, ProductsResolver } from './products';
import { PrismaService } from './prisma.service';
import { AuthorizationModule } from './authorization/authorization.module';

@Module({
  imports: [
    GraphQLModule.forRoot({
      debug: false,
      playground: true,
      typePaths: ['./**/*.graphql'],
      definitions: { path: [process.cwd(), 'src/graphql.ts'].join() },
    }),
    PrismaService,
    ConfigModule.forRoot({
      isGlobal: false,
      envFilePath: ['.env.development.local', '.env.test'],
    }),
    AuthorizationModule,
  ],
  providers: [ProductsModule, ProductsResolver, ProductsService, PrismaService],
})
export class AppModule {}
// src/authorization/auth.guard.ts

import { ExecutionContext, UnauthorizedException } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AuthGuard } from '@nestjs/passport';

// I'm not sure what to do here!
export class Auth0Guard extends AuthGuard('jwt') {
  canActivate(context: ExecutionContext) {
    try {
      const graphqlContext = GqlExecutionContext.create(context);
      console.log(graphqlContext.getContext().req);
      const [_, token] = graphqlContext
        .getContext()
        .req.headers.authorization.split(' ');
      if (token) return true;
    } catch (error) {
      throw new UnauthorizedException();
    }
  }
}
// src/authorization/authorization.module.ts

import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { ConfigModule } from '@nestjs/config';
import { Auth0Guard } from './auth.guard';
import { JwtStrategy } from './jwt.strategy';

@Module({
  imports: [
    PassportModule.register({
      defaultStrategy: 'jwt'
    }),
    ConfigModule.forRoot({
      envFilePath: ['.env.development.local', '.env.test'],
    }),
  ],
  providers: [JwtStrategy, Auth0Guard],
  exports: [PassportModule, Auth0Guard],
})
export class AuthorizationModule {}
// src/authorization/jwt.strategy.ts

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { ConfigService } from '@nestjs/config';
import { passportJwtSecret } from 'jwks-rsa';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(configService: ConfigService) {
    super({
      secretOrKeyProvider: passportJwtSecret({
        cache: false,
        rateLimit: true,
        jwksRequestsPerMinute: 100,
        jwksUri: configService.get('AUTH0_JWKS'),
      }),
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      audience: configService.get('AUTH0_AUDIENCE'),
      issuer: configService.get('AUTH0_ISSUER'),
      passReqToCallback: false,
      algorithms: ['RS256'],
    });
  }

  // This is never envoked!
  async validate(req: any, payload: any) {
    console.log('Inside validate method', req, payload);
    return payload;
  }
}
// src/products/products.resolver.ts

import {
  Query,
  Mutation,
  Resolver,
  Args,
  ArgsType,
  Field,
} from '@nestjs/graphql';
import { UseGuards } from '@nestjs/common';
import { Auth0Guard } from '../authorization/auth.guard';
import { ProductsService } from './products.service';
@ArgsType()

@Resolver('Product')
export class ProductsResolver {
  constructor(private productsService: ProductsService) {}

  @Query('products')
  // I use the guard I've created instead of the AuthGuard('jwt') because mine
  // extends AuthGuard('jwt'); the problem is: how do I now *verify/validate*
  // the JWT itself? That's been the missing piece of the puzzle for some time.
  @UseGuards(Auth0Guard)
  async getProducts() {
    return await this.productsService.getAllProducts();
  }
}

I am having the same issue. I have the access_token taken from the frontend using auth0client, but don’t know how to validate the access_token in the auth guard.

1 Like

Reward :laughing: @exnihil

I am reviewing this after two years ad I hope it will be helpful for someone

I’m not highly technical in programming, but I can help you from a logical perspective and share options related to Auth0."

I’m copying and pasting the token into Postman and sending it with requests to a guarded resolver endpoint as an authorization header. I’ve verified that the token is indeed reaching the server as expected.

I understand that you can view the access token in your API code, which is sent from Postman. If that’s the case, it’s straightforward. You can simply decode the access token and validate key attributes like the issuer (iss) and audience (aud, which will be the API name). For additional protection of your API, you can implement Role-Based Access Control (RBAC). This allows you to assign specific permissions, such as ‘Admin’ or ‘Read-Only,’ to specific users. This information will also be included in the access token under the permissions dictionary

CC: @ahmed.jeddah19

Any updates on this?

Hi @exnihil,

You can verify your access token by checking the signature with the public key available at https://{yourdomain}/.well-known/jwks.json.

Additionally, you can validate your access token using any of the libraries listed here: JSON Web Token Libraries - jwt.io.

For more details, I suggest checking out our documentation on validating access tokens: Validate Access Tokens.

(Reference: How to validate Access_Token)

Thanks,
Rueben

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.