Securing API Gateway with Okta, Serverless Framework and SSM
Overview
This brief article with accompanying GitHub repo, together cover how to secure an Amazon API Gateway endpoint with a Lambda authorizer function using Okta, Serverless Framework and AWS Systems Manager Parameter Store (SSM) for storing secrets.
Prerequisites
- Basic understanding of API Gateway Lambda Authorizers
- Basic understanding of Serverless Framework
- An app in Okta capable of minting JSON Web Tokens (JWT)
- Access to the Okta authorization server settings in your Okta domain
Code repo
https://github.com/davetownsend/serverless-okta-lambda-auth
Node.js based Lambdas are used in this project.
Authorizer Function
To grant secured access to API Gateway with an Okta JWT, a lambda authorizer function is needed that can perform the following tasks:
- Verify authenticity and validity of an Okta JWT
- Return an IAM policy granting access to API Gateway
In a Serverless Framework project, install the Okta JWT Verifier for Node.js package. This library will be used to verify the Okta JWT.
Create a function in the serverless project for the authorizer:
We’ll be assigning this function to API Gateway as an authorizer. Refer to the GitHub repo, to see the full authorizer function exampleAuth.js
.
Note the following line in exampleAuth.js
:
policy.allowMethod(AuthPolicy.HttpVerb.GET, “/example/read”)
This is where access to API Gateway resources, that will be written into the returned policy, are defined.
Policy Generator
The policy generator (used by the authorizer function) is responsible for creating a least privilege IAM policy to allow access into API Gateway.
Refer to the GitHub repo, to see the authPolicy.js
file.
Note: This code has been taken as is from here:
https://github.com/mcguinness/node-lambda-oauth2-jwt-authorizer/blob/master/auth-policy.js
Assign Authorizer to API Gateway
The authorizer function can now be assigned in serverless.yml
to the API Gateway.
Note the usage of authorizer:
The identitySource
specifies the request header where API Gateway should expect to find the JWT, and identityValidationExpression
specifies the format required of the Authorization
header value. If the header value does not meet this criterion, the request will not be sent on to the lambda authorizer and the caller will receive a 401 Unauthorized
response code. In addition, resultTtlInSeconds
specifies the cache timeout (in seconds) for the authorizer results (default 300, max 3600). For the example app, I’ve specified 0 to opt-out of caching.
Store Okta secrets in SSM
This example project uses SSM to store Okta secrets as SecuresString(s) and uses Middy to fetch and cache the params.
View the readme in the repo for steps to create the SSM parameters.
Middy makes working with SSM in Node.js extremely clean. Below is how Middy is configured to pull the SSM params, store them in the lambda’s context
object and cache them for five minutes.
Usage of the ${stage}
environment variable allows for account specific parameters.
Middy allows the retrieved SSM params to be set in either process.env
or into the lambda function’s context
object. Notice setContext: true
in the above config to opt-in to that setting. Refer to the Middy docs for more detail on SSM config options.
The SSM params can now be accessed from the context
object using the name assigned in the config, e.g.:
context.ISSUER;
Additional IAM permissions will be required on the authorizer function to both access SSM and to use KMS for decrypting the SecuredString(s).
Note: This service uses the serverless-iam-roles-per-function
and serverless-pseudo-parameters
serverless plugins to keep config clean and localized.
Refer to the GitHub repo readme for details on deploying and testing out the example application.
Additional Resources
Use API Gateway Lambda Authorizers
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html
The Complete Guide to Custom Authorizers w/ Lambda and API Gateway
https://www.alexdebrie.com/posts/lambda-custom-authorizers/
node-lambda-oauth2-jwt-authorizer
https://github.com/mcguinness/node-lambda-oauth2-jwt-authorizer
Okta JWT Verifier for Node.js
https://github.com/okta/okta-oidc-js/tree/master/packages/jwt-verifier
Integrating Okta with Amazon API Gateway
https://github.com/tom-smith-okta/okta-api-center/tree/master/gateways/aws