-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathauthorizer.ts
86 lines (71 loc) · 3.18 KB
/
authorizer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { APIGatewayTokenAuthorizerEvent, Context, Statement } from "aws-lambda";
import StatementBuilder from "../services/StatementBuilder";
import { APIGatewayAuthorizerResult } from "aws-lambda/trigger/api-gateway-authorizer";
import { generatePolicy as generateRolePolicy } from "./rolePolicyFactory";
import { generatePolicy as generateFunctionalPolicy } from "./functionalPolicyFactory";
import { getValidJwt } from "../services/tokens";
import { JWT_MESSAGE } from "../models/enums";
import { ILogEvent } from "../models/ILogEvent";
import { envLogger, LogLevel, writeLogMessage } from "../common/Logger";
import newPolicyDocument from "./newPolicyDocument";
import { Jwt, JwtPayload } from "jsonwebtoken";
/**
* Lambda custom authorizer function to verify whether a JWT has been provided
* and to verify its integrity and validity.
* @param event - AWS Lambda event object
* @param context - AWS Lambda Context object
* @returns - Promise<APIGatewayAuthorizerResult>
*/
export const authorizer = async (event: APIGatewayTokenAuthorizerEvent, context: Context): Promise<APIGatewayAuthorizerResult> => {
const logEvent: ILogEvent = {};
envLogger(LogLevel.DEBUG, "Invoked authoriser");
if (!process.env.AZURE_TENANT_ID || !process.env.AZURE_CLIENT_ID) {
writeLogMessage(event, logEvent, JWT_MESSAGE.INVALID_ID_SETUP);
return unauthorisedPolicy();
}
envLogger(LogLevel.DEBUG, "AZURE_TENANT_ID and AZURE_CLIENT_ID are set");
try {
initialiseLogEvent(event);
envLogger(LogLevel.INFO, "Getting valid JWT");
const jwt = await getValidJwt(event.authorizationToken, logEvent, process.env.AZURE_TENANT_ID, process.env.AZURE_CLIENT_ID);
envLogger(LogLevel.INFO, "Generating role policy");
const policy = generateRolePolicy(jwt, logEvent) ?? generateFunctionalPolicy(jwt, logEvent);
if (policy !== undefined) {
envLogger(LogLevel.INFO, "Role policy generated");
return policy;
}
reportNoValidRoles(jwt, event, context, logEvent);
writeLogMessage(event, logEvent, JWT_MESSAGE.INVALID_ROLES);
return unauthorisedPolicy();
} catch (error: any) {
envLogger(LogLevel.ERROR, "Catch - Error occurred", error);
writeLogMessage(event, logEvent, error);
return unauthorisedPolicy();
}
};
const unauthorisedPolicy = (): APIGatewayAuthorizerResult => {
const statements: Statement[] = [new StatementBuilder().setEffect("Deny").build()];
return {
principalId: "Unauthorised",
policyDocument: newPolicyDocument(statements),
};
};
const reportNoValidRoles = (jwt: Jwt, event: APIGatewayTokenAuthorizerEvent, context: Context, logEvent: ILogEvent): void => {
const roles = (jwt.payload as JwtPayload).roles;
if (roles && roles.length === 0) {
logEvent.message = JWT_MESSAGE.NO_ROLES;
} else {
logEvent.message = JWT_MESSAGE.INVALID_ROLES;
}
};
/**
* This method is being used in order to clear the ILogEvent, ILogError objects and populate the request url and the time of request
* @param event
*/
const initialiseLogEvent = (event: APIGatewayTokenAuthorizerEvent): ILogEvent => {
envLogger(LogLevel.DEBUG, "Init log event");
return {
requestUrl: event.methodArn,
timeOfRequest: new Date().toISOString(),
} as ILogEvent;
};