Skip to content

Instantly share code, notes, and snippets.

@gbvanrenswoude
Last active August 30, 2021 17:13
Show Gist options
  • Save gbvanrenswoude/43c988bc695722860864b40e62087ba1 to your computer and use it in GitHub Desktop.
Save gbvanrenswoude/43c988bc695722860864b40e62087ba1 to your computer and use it in GitHub Desktop.
AWS API Gateway v2 Websocket API - Custom Lambda Authorizer for JWT Token
// Proxies https://github.com/ottokruse/aws-apigw-authorizer to function as a Custom Authorizer for AWS API Gatewayv2 Websocket Custom Authorizer when sending JWT tokens.
// Send your JWT token as a querystringparameter 't' in the connection url to your Websocket api
// or set your own querystringparameter name using process.env.webSocketQueryStringParameterName
import { ApiGatewayAuthorizer } from 'aws-apigw-authorizer';
import * as AWSLambda from 'aws-lambda';
const lambdaAuthorizer = new ApiGatewayAuthorizer({ policyBuilder: customPolicyBuilder });
// NOTE type checking seems off in the source, this does not return a AWSLambda.PolicyDocument, but we ignore it
function customPolicyBuilder(event: AWSLambda.CustomAuthorizerEvent, principalId: string, _decodedToken?): AWSLambda.PolicyDocument {
const tmp = event.methodArn.split(':');
const apiGatewayArnTmp = tmp[5].split('/');
const awsAccountId = tmp[4];
const apiOptions = {
region: tmp[3],
restApiId: apiGatewayArnTmp[0],
stage: apiGatewayArnTmp[1]
};
let region;
let restApiId;
let stage;
if (!apiOptions || !apiOptions.restApiId) {
restApiId = '*';
} else {
restApiId = apiOptions.restApiId;
}
if (!apiOptions || !apiOptions.region) {
region = '*';
} else {
region = apiOptions.region;
}
if (!apiOptions || !apiOptions.stage) {
stage = '*';
} else {
stage = apiOptions.stage;
}
return {
// @ts-ignore
principalId,
policyDocument: {
Version: '2012-10-17',
Statement: [ {
Action: ['execute-api:Invoke', 'execute-api:ManageConnections'],
Effect: 'Allow',
Resource: [
`arn:aws:execute-api:${region}:${awsAccountId}:${restApiId}/${stage}/*`,
`arn:aws:execute-api:${region}:${awsAccountId}:${restApiId}/${stage}/POST/@connections`
]
}
]
}};
}
export const handler = lambdaAuthorizer.handler.bind(lambdaAuthorizer);
export async function websocketProxy(event: AWSLambda.CustomAuthorizerEvent,
_context: AWSLambda.Context, callback: AWSLambda.Callback) {
const queryStringParameterName: string = process.env.webSocketQueryStringParameterName || 't';
const tokenArray = ['Bearer', event.queryStringParameters[queryStringParameterName]];
event.headers.authorization = tokenArray.join(' ');
return handler(event, _context, callback);
}
// Infra code
// const fnAuthEnv: { [key: string]: string } = {
// stage: branch.toLowerCase(),
// ALLOWED_IP_ADDRESSES: "0.0.0.0/0",
// AUDIENCE_URI: "zzzz",
// ISSUER_URI:
// "https://sts.zzzz.net/zzzzzz/",
// JWKS_URI:
// "https://login.microsoftonline.com/zzzzzz/discovery/v2.0/keys",
// };
// const fnAuthWebsocket = new lambdaNjs.NodejsFunction(this, "authorizerWebsocketJWT", {
// runtime: lambda.Runtime.NODEJS_12_X,
// entry: "thisgist.ts",
// handler: "websocketProxy",
// timeout: cdk.Duration.seconds(12),
// description: "Authorizer for JWT Token that also parses APIGW Websocket CA Request events into APIGW CA Request events",
// memorySize: 1024,
// functionName: `izzz-authorizerWebsocketJWT-${branch}-fn`,
// role: urRole,
// environment: { ...fnAuthEnv, ...{ webSocketQueryStringParameterName: 't'} },
// });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment