The API Gateway endpoints we are using shall be restricted via permissions to a specific audience.
The idea is to use the lambda authorizer to fetch the permissions from an external service and then create the policy to allow or deny access to the endpoint.
For the matching of the permissions to the API endpoint the endpoint would need to provide the permissions it needs to the authorizer.
My question is now how can I enrich the endpoint data with its own required permissions and use them in the authorizer lambda(probably via the event) for further validation.
Example:
- User1 is forwarded to the first endpoint GET/petstore/pets(this endpoint needs the permission -> View:Pets)
- Lambda authorizer requests the user permissions from the external service
- The service returns: [View:Pets , View:Somethingelse, etc.]
- The lambda authorizer matches the user permissions against the required endpoint permission and creates the Allow policy on a match
- User2 does the same but does not have the permission for viewing pets, no match -> Deny
Here is my code for the lambda:
import {Callback, Context} from 'aws-lambda';
import {Authorizer} from './authorizer';
export class App {
constructor(private authorizer: Authorizer = new Authorizer()) {
}
public handleEvent(event, callback: Callback): Promise<void> {
return this.authorizer.checkAuthorization(event, callback)
.then((policy) => callback(null, policy))
.catch((error) => callback(error, null));
}
}
const app: App = new App();
module.exports.lambda_handler = async (event) => {
return await app.handleEvent(event);
};
Code for the checkAuthorization method:
export class Authorizer {
public resourceAuthorizer: ResourceAuthorizer = new ResourceAuthorizer();
public authenticationChecker: AuthenticationChecker = new AuthenticationChecker();
public checkAuthorization(event, callback): Promise<object> {
const endpointPermissions = event.endpointPermissions; // <== this is what I need, a custom field in the event which
// is provided from the api endpoint in some way
// in my example this whould contain a string or json
// with 'View:Pets' and 'View:Somethingelse'
return this.authenticationChecker.check(event)
.then((decodedJwt) => {
const principalId: string = decodedJwt.payload.sub;
return Promise.resolve(decodedJwt)
.then((jwt) => this.resourceAuthorizer.check(jwt, event.endpointPermissions))
.then((payload) => callback(null,
getAuthorizationPolicy(principalId, 'Allow', event.endpointPermissions, payload)))
.catch((payload) => callback(null,
getAuthorizationPolicy(principalId, 'Deny', event.endpointPermissions, payload)));
}).catch((error) => {
console.log(error);
callback('Unauthorized');
});
}
}
The event.endpointPermissions is basically what I am looking for. Depending on the API endpoint this should be filled with the permissions neccessary for that endpoint. The resourceAuthorizer then fetches the users Permissions from the external service and compares them to the endpointPermissions and then creates the Allow or Deny policies.
So where can I enter the endpointPermissions in my API Endpoint to provide them to the Authorizer?