Serverless-offline: JWT with custom authorizers

Created on 29 Aug 2020  路  10Comments  路  Source: dherault/serverless-offline

Hi!

I'm trying to implement custom authorizers as described here:

This is my serverless.yml:

service: xxxx

frameworkVersion: ">=1.78.0 <2.0.0"

plugins:
  - serverless-dotenv-plugin
  - serverless-offline

provider:
  name: aws
  runtime: nodejs12.x
  region: ${env:AWS_LAMBDA_REGION}
  stage: ${ opt:stage, 'local' }
  cors:
    allowedOrigins:
      - "*"

custom:
  serverless-offline:
    httpPort: ${env:LOCAL_HTTP_PORT}
    host: 0.0.0.0
    # Enables hot reloading (https://github.com/dherault/serverless-offline/issues/864#issuecomment-627419266)
    useChildProcesses: true

functions:
  jwt-auth:
    handler: handler.jwt

  module-activation-sns:
    handler: handler.sns
    events:
      - sns: ${env:AWS_SNS_ARN_MODULE_ACTIVATION}

  module-activation-http:
    handler: handler.http
    events:
      - httpApi:
          method: POST
          path: /module
          authorizer: jwt-auth

But when I run serverless offline I'm getting this error:

Error: Serverless Offline only supports retrieving JWT from the headers (undefined)
      at createAuthScheme (/home/node/node_modules/serverless-offline/dist/events/http/createJWTAuthScheme.js:22:11)

Any idea of how can I get this working with Serverless Offline?

Thanks!

All 10 comments

Hey, in your serverless.yml add the following:

custom:
  serverless-offline:
    ignoreJWTSignature: true

The plugin skips the verification check which will allow your custom setup to work.

Hope that helps!

EDIT:
To confirm, I was using http and not httpApi- sorry!

Seeing the same issue here. I am passing --ignoreJWTSignature and have tried setting it in the config as well as suggested above but still get the Serverless Offline only supports retrieving JWT from the headers (undefined) error.

I notice this works for events of -http: but not -httpApi:.

Are we sure this is supported currently?

I can confirm that sls-offline doesn't work for me with httpApi. Passing --ignoreJWTSignature might get it to load but then if bombs on verification with:

offline: JWT could not be decoded
offline: TypeError: jwtOptions.audience.filter is not a function

Looking at createAuthScheme it's expecting jwtOptions.audience to be an array. I've changed my serverless.yaml to have an array but it always winds up as a string by the time the authJWTSettingsExtractor() function is run. I'll post a fix shortly and link it here.

I did notice this as well actually. Adding two identical array elements works around it but still obviously not ideal and didn't solve my overall issue anyway:

audience:
  - abcxxxxxxx
  - abcxxxxxxx

:) sneaky, i didn't try that, the fix is simple enough. See https://github.com/dherault/serverless-offline/pull/1133

I'm not really sure what that buildSuccessResult(null) code in authJWTSettingsExtractor.js is trying to achieve. The functionality I would guess would be useful is to bypass JWT validation in offline. But that's the opposite of what the switch is called - i.e. you have to use --ignoreJWTSignature to cause JWT validation to occur. Anyhow I left that part alone - just fixed the TypeError.

Yep, to confirm, I was using http and not httpApi- sorry if that caused any confusion. I've updated the original comment to include that note.

Ty @ilanc for the PR!

@vaunus I remember getting that too. Do you have identitySource: $request.header.Authorization in your authorizer? See minw below.

httpApi:
    authorizers:
      serviceAuthorizer:
        identitySource: $request.header.Authorization  # <= this line
        issuerUrl: https://app.spikedata.co.za/
        audience: spike-api-audience

Yes am setup exactly the same as you there @ilanc

To be clear though serverless-offline seems happy with that config. The issues I was facing were when trying to setup a custom authorizer as per OP. This is definitely supported within AWS HTTP APIs but it doesn't seem like offline supports it right now.

I think I found the problem, I was having the same problem and now it's fixed

I have this configuration in serverless.yml

httpApi:
    authorizers:
      firebaseJWTAuthorizer:
        identitySource: $request.header.Authorization
        issuerUrl: https://securetoken.google.com/project1
        audience:
          - 'aud1'

And when I ran the this command serverless offline --ignoreJWTSignature

I get this error
image
and a response like this

{
    "statusCode": 401,
    "error": "Unauthorized",
    "message": "Unauthorized"
}

After reading the error TypeError: jwtOptions.audience.filter is not a function I tried to add another audience target like this

httpApi:
    authorizers:
      firebaseJWTAuthorizer:
        identitySource: $request.header.Authorization
        issuerUrl: https://securetoken.google.com/project1
        audience:
          - 'aud1'
          - 'aud2'

And the problem is solved 馃槃 and the JWT authorization works offline 馃殌馃殌馃殌
I hope this trick helps 馃憤馃徎

And in the source code, I think that the problem is in this line: includes is executed against a non array type https://github.com/dherault/serverless-offline/blob/b74f49dfa8e5fc7c073f98b9b7979cefe3c38229/src/events/http/createJWTAuthScheme.js#L64

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JimLynchCodes picture JimLynchCodes  路  4Comments

davidroman0O picture davidroman0O  路  4Comments

ghost picture ghost  路  4Comments

FranzSkuffka picture FranzSkuffka  路  3Comments

Rafaelsk picture Rafaelsk  路  4Comments