#Always process jwt

31 messages · Page 1 of 1 (latest)

wraith horizon
#

Hey, I would like to know, if there is a correct way to always process the authorization token even if the routes isn't guarded.

The use case, is that in my graphql request there data restricted to authenticated user and also public data.

If you have an idea ?
Thank you by advance
LeGmask

reef venture
#

You can specify a provider in app.module.ts that looks like this:

{
  provide: APP_GUARD,
  useClass: AuthGuard // replace this with your own class
}

And you can import APP_GUARD constant from @nestjs/core

 import { APP_GUARD } from '@nestjs/core';
#

This will apply the guard globally

shrewd plank
wraith horizon
#

I've thinked a bit,
-> a modified jwt guard that doesn't throw error, and populate user context
-> a custom guard, that verify the user context, and throw error if the context is null

slow crypt
#

You need to come up with a system of access for your application, if the API should be mixed between public and confidential viewing. In other words, access controls are set deeper in the stack. Like possibly at resolver level.

#

And you need a way to decide. Is this a known or an unknown user and if unknown, what do I allow to be shown.

wraith horizon
#

if loggin for example loggin is required

slow crypt
#

Yeah, so you probably need something that will identify a resolver as "public" or not. Right?

#

That is a very simple solution.

wraith horizon
slow crypt
#

Then you need to go even deeper. Field level security is a hard and complex thing to accomplish.

wraith horizon
#

okay, thank you 😍

shrewd plank
#

perhaps casbin might be able as well

slow crypt
#

I just noticed Google took me to version 4 of CASL, yet version 6 is the latest version. I've updated the link above.

zealous bear
#

this (processing JWT's even on routes marked with @Public ) does not seem to be possible when using PassportJS's 'passport-jwt' strategy

burnt vale
#

Directly, no, but you can call super.canActivate(context) and return true regardless the outcome

#

Assuming your guard extended AuthGuard('jwt')

zealous bear
#

@burnt vale thanks.. but then where would i check for the IS_PUBLIC_KEY and use it?

burnt vale
#

Save the super.canActivate result to a variable.. After the call, check for the metadata, if it exists return true, if it doesn't what return the result

zealous bear
#

Thanks again, @burnt vale -- thx to you, i'm making progress! Now I've discovered that my async validate function in my JwtStrategy is being called after my resolver is called... could that be a problem with Passport?

burnt vale
#

Did you await the super call?

zealous bear
#

no because the canActivate function can't be async..

burnt vale
#

It can. It can return a Boolean, a Promise<Boolean> or an Observable<Boolean

zealous bear
#

hmm.. when i mark it as async, i get TS errors...

Property 'canActivate' in type 'JwtAuthGuard' is not assignable to the same property in base type 'IAuthGuard'.
  Type '(context: ExecutionContext) => Promise<boolean | Observable<boolean>>' is not assignable to type '(context: ExecutionContext) => boolean | Promise<boolean> | Observable<boolean>'.
burnt vale
#

Give it an as Promise<Boolean> because the types are too wide otherwise

burnt vale
zealous bear
#
override async canActivate(context: ExecutionContext) {
    const isValid = await super.canActivate(context);
    const contextType = context.getType<'http' | 'stripe_webhook'>();
    if (contextType === 'stripe_webhook' || contextType === 'http') {
      // will be handled by the stripe webhook handler...
      return true;
    }
    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);
    if (isPublic) {
      // we allow public access
      return true;
    }
    return isValid;
  }
burnt vale
#

Hmm, yeah I'd think Typescript should be okay with that.