|
// 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'} }, |
|
// }); |