diff --git a/README.md b/README.md
index 0aba3857b..6b08a77c4 100644
--- a/README.md
+++ b/README.md
@@ -364,10 +364,11 @@ only enabled with the `--ignoreJWTSignature` flag. Make sure to only set this fl
You are able to use some custom headers in your request to gain more control over the requestContext object.
-| Header | Event key |
-| ------------------------------- | ----------------------------------------------------------- |
-| cognito-identity-id | event.requestContext.identity.cognitoIdentityId |
-| cognito-authentication-provider | event.requestContext.identity.cognitoAuthenticationProvider |
+| Header | Event key | Example |
+| ------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------- |
+| cognito-identity-id | event.requestContext.identity.cognitoIdentityId | |
+| cognito-authentication-provider | event.requestContext.identity.cognitoAuthenticationProvider | |
+| sls-offline-authorizer-override | event.requestContext.authorizer | { "iam": {"cognitoUser": { "amr": ["unauthenticated"], "identityId": "abc123" }}} |
By doing this you are now able to change those values using a custom header. This can help you with easier authentication or retrieving the userId from a `cognitoAuthenticationProvider` value.
@@ -744,6 +745,10 @@ We try to follow [Airbnb's JavaScript Style Guide](https://github.com/airbnb/jav
| :------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------: |
| [lteacher](https://github.com/lteacher) | [martinmicunda](https://github.com/martinmicunda) | [nori3tsu](https://github.com/nori3tsu) | [ppasmanik](https://github.com/ppasmanik) | [ryanzyy](https://github.com/ryanzyy) |
-| [](https://github.com/m0ppers) | [](https://github.com/footballencarta) | [](https://github.com/bryanvaz) | [](https://github.com/njyjn) |
+| [](https://github.com/m0ppers) | [](https://github.com/footballencarta) | [](https://github.com/bryanvaz) | [](https://github.com/njyjn) | |
| :---------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------: | ------------------------------------- |
| [m0ppers](https://github.com/m0ppers) | [footballencarta](https://github.com/footballencarta) | [bryanvaz](https://github.com/bryanvaz) | [njyjn](https://github.com/njyjn) | [kdybicz](https://github.com/kdybicz) |
+
+| [](https://github.com/ericctsf) | | | | |
+| :------------------------------------------------------------------------------------------------------------------------------: | :-: | :-: | :-: | :-: |
+| [ericctsf](https://github.com/erictsf) | | | | |
diff --git a/package.json b/package.json
index 5d9bda79d..fa8cc25c4 100644
--- a/package.json
+++ b/package.json
@@ -156,7 +156,8 @@
"Dima Krutolianov (https://github.com/dimadk24)",
"Bryan Vaz (https://github.com/bryanvaz)",
"Justin Ng (https://github.com/njyjn)",
- "Fernando Alvarez (https://github.com/jefer590)"
+ "Fernando Alvarez (https://github.com/jefer590)",
+ "Eric Carter (https://github.com/ericctsf)"
],
"husky": {
"hooks": {
diff --git a/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js b/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js
index b798b9e39..30bb7c904 100644
--- a/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js
+++ b/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js
@@ -75,6 +75,22 @@ export default class LambdaProxyIntegrationEvent {
// NOTE FIXME request.raw.req.rawHeaders can only be null for testing (hapi shot inject())
const headers = parseHeaders(rawHeaders || []) || {}
+ if (headers['sls-offline-authorizer-override']) {
+ try {
+ authAuthorizer = parse(headers['sls-offline-authorizer-override'])
+ } catch (error) {
+ if (this.log) {
+ this.log.error(
+ 'Could not parse header sls-offline-authorizer-override, make sure it is correct JSON',
+ )
+ } else {
+ console.error(
+ 'Serverless-offline: Could not parse header sls-offline-authorizer-override make sure it is correct JSON.',
+ )
+ }
+ }
+ }
+
if (body) {
if (typeof body !== 'string') {
// this.#request.payload is NOT the same as the rawPayload
diff --git a/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js b/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js
index 2801866a6..fba0821fe 100644
--- a/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js
+++ b/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js
@@ -63,6 +63,22 @@ export default class LambdaProxyIntegrationEventV2 {
// NOTE FIXME request.raw.req.rawHeaders can only be null for testing (hapi shot inject())
const headers = parseHeaders(rawHeaders || []) || {}
+ if (headers['sls-offline-authorizer-override']) {
+ try {
+ authAuthorizer = parse(headers['sls-offline-authorizer-override'])
+ } catch (error) {
+ if (this.log) {
+ this.log.error(
+ 'Could not parse header sls-offline-authorizer-override, make sure it is correct JSON',
+ )
+ } else {
+ console.error(
+ 'Serverless-offline: Could not parse header sls-offline-authorizer-override make sure it is correct JSON.',
+ )
+ }
+ }
+ }
+
if (body) {
if (typeof body !== 'string') {
// this.#request.payload is NOT the same as the rawPayload
diff --git a/tests/integration/override-authorizer/handler.js b/tests/integration/override-authorizer/handler.js
new file mode 100644
index 000000000..223b597f5
--- /dev/null
+++ b/tests/integration/override-authorizer/handler.js
@@ -0,0 +1,8 @@
+'use strict'
+
+exports.echo_authorizer = async function get(context) {
+ return {
+ body: JSON.stringify(context.requestContext.authorizer),
+ statusCode: 200,
+ }
+}
diff --git a/tests/integration/override-authorizer/override-authorizer.test.js b/tests/integration/override-authorizer/override-authorizer.test.js
new file mode 100644
index 000000000..ec749ab63
--- /dev/null
+++ b/tests/integration/override-authorizer/override-authorizer.test.js
@@ -0,0 +1,104 @@
+import { resolve } from 'path'
+import fetch from 'node-fetch'
+import { joinUrl, setup, teardown } from '../_testHelpers/index.js'
+
+jest.setTimeout(30000)
+
+const envAuthorizer = {
+ iam: {
+ cognitoUser: {
+ amr: ['unauthenticated'],
+ identityId: 'env_identity_id',
+ },
+ },
+}
+
+const headerAuthorizer = {
+ iam: {
+ cognitoUser: {
+ amr: ['unauthenticated'],
+ identityId: 'header_identity_id',
+ },
+ },
+}
+
+describe('override authorizer tests', () => {
+ // init
+ beforeAll(async () => {
+ process.env.AUTHORIZER = JSON.stringify(envAuthorizer)
+ await setup({
+ servicePath: resolve(__dirname),
+ })
+ })
+
+ // cleanup
+ afterAll(async () => {
+ process.env.AUTHORIZER = undefined
+ await teardown()
+ })
+
+ //
+ ;[
+ {
+ description: 'HTTP API Falls back on env variable',
+ req: {
+ path: '/gateway_v2_http_api',
+ headers: {},
+ },
+ res: {
+ status: 200,
+ body: envAuthorizer,
+ },
+ },
+ {
+ description: 'REST API Falls back on env variable',
+ req: {
+ path: '/dev/gateway_v1_rest_api',
+ headers: {},
+ },
+ res: {
+ status: 200,
+ body: envAuthorizer,
+ },
+ },
+ {
+ description: 'HTTP API uses override header',
+ req: {
+ path: '/gateway_v2_http_api',
+ headers: {
+ 'sls-offline-authorizer-override': JSON.stringify(headerAuthorizer),
+ },
+ },
+ res: {
+ status: 200,
+ body: headerAuthorizer,
+ },
+ },
+ {
+ description: 'HTTP API uses override header',
+ req: {
+ path: '/dev/gateway_v1_rest_api',
+ headers: {
+ 'sls-offline-authorizer-override': JSON.stringify(headerAuthorizer),
+ },
+ },
+ res: {
+ status: 200,
+ body: headerAuthorizer,
+ },
+ },
+ ].forEach(({ description, req, res }) => {
+ test(description, async () => {
+ const url = joinUrl(TEST_BASE_URL, req.path)
+ const options = {
+ headers: req.headers,
+ }
+
+ const response = await fetch(url, options)
+ expect(response.status).toEqual(res.status)
+
+ const json = await response.json()
+ expect(json).toEqual(res.body)
+ })
+ })
+})
diff --git a/tests/integration/override-authorizer/serverless.yml b/tests/integration/override-authorizer/serverless.yml
new file mode 100644
index 000000000..3f4495ad8
--- /dev/null
+++ b/tests/integration/override-authorizer/serverless.yml
@@ -0,0 +1,33 @@
+service: jwt-authorizer
+
+plugins:
+ - ../../../
+
+custom:
+ serverless-offline:
+ noAuth: true
+
+provider:
+ memorySize: 128
+ name: aws
+ region: us-east-1 # default
+ runtime: nodejs12.x
+ stage: dev
+ versionFunctions: false
+ httpApi:
+ payload: '2.0'
+
+functions:
+ user:
+ events:
+ - http:
+ authorizer:
+ type: 'AWS_IAM'
+ method: get
+ path: gateway_v1_rest_api
+ - httpApi:
+ authorizer:
+ type: AWS_IAM
+ method: get
+ path: gateway_v2_http_api
+ handler: handler.echo_authorizer