in backend/Functions/WebSockets/auth/app.js [25:122]
exports.handler = function (event, context, callback) {
// Do not print the auth token unless absolutely necessary
console.log(JSON.stringify(event));
const token = event.queryStringParameters.access_token;
if (!pems) {
// Download the JWKs and save it as PEM
request({
url: `${iss}/.well-known/jwks.json`,
json: true,
}, (error, response, body) => {
if (!error && response.statusCode === 200) {
pems = {};
const { keys } = body;
for (let i = 0; i < keys.length; i++) {
// Convert each key to PEM
const key_id = keys[i].kid;
const modulus = keys[i].n;
const exponent = keys[i].e;
const key_type = keys[i].kty;
const jwk = { kty: key_type, n: modulus, e: exponent };
const pem = jwkToPem(jwk);
pems[key_id] = pem;
}
// Get AWS AccountId and API Options
const apiOptions = {};
const tmp = event.methodArn.split(':');
const apiGatewayArnTmp = tmp[5].split('/');
const awsAccountId = tmp[4];
apiOptions.region = tmp[3];
apiOptions.restApiId = apiGatewayArnTmp[0];
apiOptions.stage = apiGatewayArnTmp[1];
// validate the incoming token
// and produce the principal user identifier associated with the token
const splittoken = token.split('.');
const header = JSON.parse(Buffer.from(splittoken[0], 'base64').toString('utf-8'));
let policy;
jwt.verify(token, pems[header.kid], { algorithms: ['RS256'], issuer: iss }, (err, payload) => {
if (err) {
console.log('cannot verify');
policy = new AuthPolicy('', awsAccountId, apiOptions);
policy.denyAllMethods();
context.fail('Unauthorized');
}
// now have a valid decoded JWT
// give all rights if there is a valid JWT
const principalId = payload.sub;
policy = new AuthPolicy(principalId, awsAccountId, apiOptions);
policy.allowAllMethods();
// policy.allowMethod(AuthPolicy.HttpVerb.GET, "/users/username");
// finally, build the policy
const authResponse = policy.build();
console.log(JSON.stringify(authResponse));
callback(null, authResponse);
});
} else {
// Unable to download JWKs, fail the call
context.fail('error');
}
});
} else {
// Get AWS AccountId and API Options
const apiOptions = {};
const tmp = event.methodArn.split(':');
const apiGatewayArnTmp = tmp[5].split('/');
const awsAccountId = tmp[4];
apiOptions.region = tmp[3];
apiOptions.restApiId = apiGatewayArnTmp[0];
apiOptions.stage = apiGatewayArnTmp[1];
// validate the incoming token
// and produce the principal user identifier associated with the token
const splittoken = token.split('.');
const header = JSON.parse(Buffer.from(splittoken[0], 'base64').toString('utf-8'));
let policy;
jwt.verify(token, pems[header.kid], { algorithms: ['RS256'], issuer: iss }, (err, payload) => {
if (err) {
console.log('cannot verify');
policy = new AuthPolicy('', awsAccountId, apiOptions);
policy.denyAllMethods();
context.fail('Unauthorized');
console.log(JSON.stringify(err.stack));
}
// now have a valid decoded JWT
// give all rights if there is a valid JWT
const principalId = payload.sub;
policy = new AuthPolicy(principalId, awsAccountId, apiOptions);
policy.allowAllMethods();
// policy.allowMethod(AuthPolicy.HttpVerb.GET, "/users/username");
// finally, build the policy
const authResponse = policy.build();
console.log(JSON.stringify(authResponse));
callback(null, authResponse);
});
}
};