Developing a Secure API with NestJS

You are welcome! The guide should be coming up next week.

1 Like

Thanks for the headsup Dan!

1 Like

Trying to retrieve an id_token and test it against my NestJS application
(Full-Stack TypeScript Apps: Developing a Secure API with NestJS)

Summary: Bearer-Token auth only works if I use the ā€˜audience’ string returned from the Login response using the Authentication API Debugger

What I did:
NestJS => JwtStrategy => audience: https://sandbox.au.auth0.com/api/v2/

audience: configService.getOrThrow('AUTH0_AUDIENCE'),

Auth0 Website => Authentication API Debugger => Login => OAuth2/OICD

set audience to: https://sandbox.au.auth0.com/api/v2/
set Response Type to ā€˜id_token’

Click User Flows => [OAUTH2 / OICD LOGIN]

Request details:

Hash Fragment:
{
ā€œid_tokenā€: jwt_token__no_need_to_paste_here",
ā€œstateā€: ā€œmy-custom-stateā€
}

ID Token:

{
  "header": {
    "alg": "RS256",
    "typ": "JWT",
    "kid": "RfvRO_OkON3ojXPtgeaOb"
  },
  "payload": {
    "email": "thorsten.maus@scvhuma.onmicrosoft.com",
    "email_verified": true,
    "iss": "https://huma-sandbox.au.auth0.com/",
    **
"aud": "S4I6ILkcHp2te2BygTELeEZqipvUB0NJ",
**
    "iat": 1678430041,
    "exp": 1678466041,
    "sub": "auth0|64015a68d7ea5c12c38c7662",
    "sid": "tCHI6xk7832t-2SKgT2SJIwPVC9I8HNb",
    "nonce": "1024"
  },
  "signature": "xU2oH7AEO0cd1Tqqh2XYDnanFswgdZyMtgCDxMV6eqYkmhJaOb4QA3dtbFyrkYPtzFOaPGj3_zE-HWc8nePOjCIrIOz-pLA1Nra-pqY79ZrZgCorO8MwbjKnCXloS_XY6OAGQ_bWsMgn8RU1alSt66QROTc0DSCfM6SP_YV28GTe-6kSdHjqDYq9-Oq8Qsp-w6cpnWDzW3FTdTgBsWqUG6o-tte44DLjvH-Yd72rA_K41nUuyyU2xpiiOqesPr25VPg63VnK1FK84o8htKo3gLLP8u1wOXuRgXUjFTxuixSGXyJeugaCmyjd2ubND_wnLJbnIaoyTLVd1dKGMl_uog"
}

I copy the id_token into my Swagger and fire the request against my AuthBearer protected endpoint. (NestJS using same audience as mentioned above)

I get a 401 response (not expected)

I change the audience in my NestJS application to the output of the Authentication API Debugger => Request => ID Token => payload => aud (S4I6ILkcHp2te2BygTELeEZqipvUB0NJ")

Fire the request (same token) and pass the JWT validation within NestJS (not expected)

Questions:

  • Do I have to encode the audience string in my NestJS application (not found any documentation about it)?
  • Is there anything I do wrong ?
  • So what’s the thing I do not get here

:slight_smile:

thx for your help

Hi

using the code from the BASIC API Auth example
I am not clear on how to get the sub and role from auth

import { auth, InvalidTokenError, UnauthorizedError } from 'express-oauth2-jwt-bearer';
const validateAccessToken = promisify(auth())

Thanks

Chris

1 Like

Hello, is this question related to the code sample from the Developer Center or the code sample that you can build following the blog post referenced in this forum?

The code from the blog is great at restricting access to an API route.
Is there a doc / blog on the recommended way to get the user name, role and any other information held in Auth0 for the deciding on the authorisation of actions on the API?

The use case is authorised general users should not have rights of admin users.

Many thanks

1 Like

Hello @rationem, if what you are trying to achieve is to serve resources that require different access levels from a secure API server based on roles, I recommend you visit the following code sample page that demonstrates how to implement Role-Based Access Control (RBAC) in a NestJS API server using Auth0. In this case, it implements a guard that checks the permissions claim on the access token.

However, if this differs from what you’re trying to accomplish, could you provide us with more detail on your use case on a new topic so we can answer your needs?

Thanks

3 Likes

Many thanks for this.

2 Likes

You are welcome. Please let us know if you have any other questions.

Hi @dan-auth0 Somehow my Auth0Strategy doesn’t do anything. Nothing return in validate callback function. According to your documentation I suppose to see payload.


@Module({
  imports: [
    DatabaseModule.forFeature([UserEntity, UserTeam]),
    PassportModule.register({
      defaultStrategy: 'jwt',
    }),
    JwtModule,
  ],
  providers: [ConfigService, Auth0Strategy, AppResolver, AppService],
  exports: [AppService, PassportModule],
})

@Injectable()
export class Auth0Strategy extends PassportStrategy(Strategy, 'jwt') {
  constructor(
    private configService: ConfigService,
    private appService: AppService
  ) {
    super({
      secretOrKeyProvider: passportJwtSecret({
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: `https://${configService.get(
          'NX_AUTH0_DOMAIN'
        )}/.well-known/jwks.json`,
      }),
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      audience: configService.get('NX_AUTH0_AUDIENCE'),
      issuer: configService.get('NX_AUTH0_ISSUER_URL'),
      algorithms: ['RS256'],
    });
  }

  validate(payload: any) {
 // Nothing return here.
    return this.appService.findOneByOrFail({ email: payload.email });
  }
}

1 Like

Hello. Welcome to the Auth0 Community :slight_smile:
The integration of Passport is complex. There are easier ways to secure a NestJS API now. At the time of writing that is what we best had to secure NestJS API. I am currently working on release the guide that will support this code sample:

I recommend you check it out as that uses an simpler library :muscle:

I’ll ping you when the new guide is ready. To be honest, I have not used Passport in years and I am looking to deprecate this guide as it will be difficult to support now :pray:

I’ve been following this page to create an api but it has been giving me a 400 for the last hour or so.

Google search ā€œauth0 nestjsā€ leads to this, and I was looking at it earlier this morning.

Actually, the entire blog is down Auth0 Blog

edit: blog is back up now…

edit: and it’s down again

edit: cleared my auth0 cookies and now it’s working consistently. i guess local development mucked with something.

Hey @dan-auth0, the RBAC system you implemented is being deprecated (rules) in favor of actions. You might want to update the content. Other than that its really an excellent article!

1 Like

Following up on @fynn.merlevede comment - The rule code example should be changed to:

exports.onExecutePostLogin = async (event, api) => {
  const namespace = 'https://menu-api.demo.com';
  if (event.authorization) {
    api.idToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
    api.accessToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
  }
}