Skip to content

Commit

Permalink
feat(apigateway): lambda request authorizer (aws#5642)
Browse files Browse the repository at this point in the history
This creates a common LambdaAuthorizer base class so that the
token and request authorizers can share common functionality.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*

<!-- 
Please read the contribution guidelines and follow the pull-request checklist:
https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md
 -->
  • Loading branch information
CaerusKaru authored Feb 24, 2020
1 parent 9d11c4e commit 031932d
Show file tree
Hide file tree
Showing 18 changed files with 878 additions and 132 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pack/
.tools/
coverage/
.nyc_output
.nycrc
.LAST_BUILD
*.sw[a-z]
*~
Expand Down
48 changes: 44 additions & 4 deletions packages/@aws-cdk/aws-apigateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,8 @@ API Gateway interacts with the authorizer Lambda function handler by passing inp
The event object that the handler is called with contains the `authorizationToken` and the `methodArn` from the request to the
API Gateway endpoint. The handler is expected to return the `principalId` (i.e. the client identifier) and a `policyDocument` stating
what the client is authorizer to perform.
See https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html for a detailed specification on
inputs and outputs of the lambda handler.
See [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html) for a detailed specification on
inputs and outputs of the Lambda handler.

The following code attaches a token-based Lambda authorizer to the 'GET' Method of the Book resource:

Expand All @@ -382,7 +382,7 @@ const authFn = new lambda.Function(this, 'booksAuthorizerLambda', {
});

const auth = new apigateway.TokenAuthorizer(this, 'booksAuthorizer', {
function: authFn
handler: authFn
});

books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
Expand All @@ -397,6 +397,45 @@ Authorizers can also be passed via the `defaultMethodOptions` property within th
explicitly overridden, the specified defaults will be applied across all `Method`s across the `RestApi` or across all `Resource`s,
depending on where the defaults were specified.

#### Lambda-based request authorizer

This module provides support for request-based Lambda authorizers. When a client makes a request to an API's methods configured with such
an authorizer, API Gateway calls the Lambda authorizer, which takes specified parts of the request, known as identity sources,
as input and returns an IAM policy as output. A request-based Lambda authorizer (also called a request authorizer) receives
the identity sources in a series of values pulled from the request, from the headers, stage variables, query strings, and the context.

API Gateway interacts with the authorizer Lambda function handler by passing input and expecting the output in a specific format.
The event object that the handler is called with contains the body of the request and the `methodArn` from the request to the
API Gateway endpoint. The handler is expected to return the `principalId` (i.e. the client identifier) and a `policyDocument` stating
what the client is authorizer to perform.
See [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html) for a detailed specification on
inputs and outputs of the Lambda handler.

The following code attaches a request-based Lambda authorizer to the 'GET' Method of the Book resource:

```ts
const authFn = new lambda.Function(this, 'booksAuthorizerLambda', {
// ...
// ...
});

const auth = new apigateway.RequestAuthorizer(this, 'booksAuthorizer', {
handler: authFn,
identitySources: [IdentitySource.header('Authorization')]
});

books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
authorizer: auth
});
```

By default, the `RequestAuthorizer` does not pass any kind of information from the request. This can,
however, be modified by changing the `identitySource` property, and is required when specifying a value for caching.

Authorizers can also be passed via the `defaultMethodOptions` property within the `RestApi` construct or the `Method` construct. Unless
explicitly overridden, the specified defaults will be applied across all `Method`s across the `RestApi` or across all `Resource`s,
depending on where the defaults were specified.

### Deployments

By default, the `RestApi` construct will automatically create an API Gateway
Expand Down Expand Up @@ -539,7 +578,8 @@ running at one origin, access to selected resources from a different origin. A
web application executes a cross-origin HTTP request when it requests a resource
that has a different origin (domain, protocol, or port) from its own.

You can add the CORS [preflight](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests) OPTIONS HTTP method to any API resource via the `defaultCorsPreflightOptions` option or by calling the `addCorsPreflight` on a specific resource.
You can add the CORS [preflight](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests) OPTIONS
HTTP method to any API resource via the `defaultCorsPreflightOptions` option or by calling the `addCorsPreflight` on a specific resource.

The following example will enable CORS for all methods and all origins on all resources of the API:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Represents an identity source.
*
* The source can be specified either as a literal value (e.g: `Auth`) which
* cannot be blank, or as an unresolved string token.
*/
export class IdentitySource {
/**
* Provides a properly formatted header identity source.
* @param headerName the name of the header the `IdentitySource` will represent.
*
* @returns a header identity source.
*/
public static header(headerName: string): string {
return IdentitySource.toString(headerName, 'method.request.header');
}

/**
* Provides a properly formatted query string identity source.
* @param queryString the name of the query string the `IdentitySource` will represent.
*
* @returns a query string identity source.
*/
public static queryString(queryString: string): string {
return IdentitySource.toString(queryString, 'method.request.querystring');
}

/**
* Provides a properly formatted API Gateway stage variable identity source.
* @param stageVariable the name of the stage variable the `IdentitySource` will represent.
*
* @returns an API Gateway stage variable identity source.
*/
public static stageVariable(stageVariable: string): string {
return IdentitySource.toString(stageVariable, 'stageVariables');
}

/**
* Provides a properly formatted request context identity source.
* @param context the name of the context variable the `IdentitySource` will represent.
*
* @returns a request context identity source.
*/
public static context(context: string): string {
return IdentitySource.toString(context, 'context');
}

private static toString(source: string, type: string) {
if (!source.trim()) {
throw new Error(`IdentitySources must be a non-empty string.`);
}

return `${type}.${source}`;
}
}
3 changes: 2 additions & 1 deletion packages/@aws-cdk/aws-apigateway/lib/authorizers/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './lambda';
export * from './lambda';
export * from './identity-source';
Loading

0 comments on commit 031932d

Please sign in to comment.