Expose the cognito user pool claims

This commit is contained in:
John Ferlito 2016-11-06 14:33:17 +11:00
parent 64fa7c64b3
commit 577ebfd350
No known key found for this signature in database
GPG Key ID: 4FFB060C9EC70B95
6 changed files with 112 additions and 10 deletions

View File

@ -206,6 +206,26 @@ functions:
arn: arn:aws:cognito-idp:us-east-1:xxx:userpool/us-east-1_ZZZ
```
By default the `sub` claim will be exposed in `events.cognitoPoolClaims`, you can add extra claims like so:
```yml
functions:
create:
handler: posts.create
events:
- http:
path: posts/create
method: post
integration: lambda
authorizer:
arn: arn:aws:cognito-idp:us-east-1:xxx:userpool/us-east-1_ZZZ
claims:
- email
- nickname
```
You must use `integration: lambda` to have any claims exposed.
### Catching Exceptions In Your Lambda Function
In case an exception is thrown in your lambda function AWS will send an error message with `Process exited before completing request`. This will be caught by the regular expression for the 500 HTTP status and the 500 status will be returned.

View File

@ -28,15 +28,15 @@ module.exports = {
authorizerProperties.ProviderARNs = [authorizer.arn];
} else {
authorizerProperties.AuthorizerUri =
{ 'Fn::Join': ['',
[
'arn:aws:apigateway:',
{ Ref: 'AWS::Region' },
':lambda:path/2015-03-31/functions/',
authorizer.arn,
'/invocations',
],
] };
{ 'Fn::Join': ['',
[
'arn:aws:apigateway:',
{ Ref: 'AWS::Region' },
':lambda:path/2015-03-31/functions/',
authorizer.arn,
'/invocations',
],
] };
authorizerProperties.Type = 'TOKEN';
}

View File

@ -28,7 +28,6 @@ module.exports = {
template.Properties.ApiKeyRequired = true;
}
const methodLogicalId = this.provider.naming
.getMethodLogicalId(resourceName, event.http.method);
const lambdaLogicalId = this.provider.naming
@ -43,6 +42,19 @@ module.exports = {
this.getMethodResponses(event.http)
);
let extraCognitoPoolClaims;
if (event.http.authorizer) {
const claims = event.http.authorizer.claims || [];
extraCognitoPoolClaims = _.map(claims, claim =>
`"${claim}": "$context.authorizer.claims.${claim}",`
);
}
const requestTemplates = template.Properties.Integration.RequestTemplates;
_.forEach(requestTemplates, (value, key) => {
requestTemplates[key] =
value.replace('extraCognitoPoolClaims', extraCognitoPoolClaims || '');
});
this.apiGatewayMethodLogicalIds.push(methodLogicalId);
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {

View File

@ -192,6 +192,63 @@ describe('#compileMethods()', () => {
awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.ApiGatewayMethodUsersCreatePost.Properties.AuthorizerId.Ref
).to.equal('AuthorizerApiGatewayAuthorizer');
expect(
awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.ApiGatewayMethodUsersCreatePost.Properties
.Integration.RequestTemplates['application/json']
).to.not.match(/undefined/);
});
});
it('should set claims for a cognito user pool', () => {
awsCompileApigEvents.validated.events = [
{
functionName: 'First',
http: {
authorizer: {
name: 'authorizer',
arn: 'arn:aws:cognito-idp:us-east-1:xxx:userpool/us-east-1_ZZZ',
claims: ['email'],
},
integration: 'AWS',
path: 'users/create',
method: 'post',
},
},
];
return awsCompileApigEvents.compileMethods().then(() => {
expect(
awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.ApiGatewayMethodUsersCreatePost.Properties
.Integration.RequestTemplates['application/json']
).to.match(/email/);
});
});
it('should replace the extra claims in the template if there are none', () => {
awsCompileApigEvents.validated.events = [
{
functionName: 'First',
http: {
authorizer: {
name: 'authorizer',
arn: 'arn:aws:cognito-idp:us-east-1:xxx:userpool/us-east-1_ZZZ',
},
integration: 'AWS',
path: 'users/create',
method: 'post',
},
},
];
return awsCompileApigEvents.compileMethods().then(() => {
expect(
awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources.ApiGatewayMethodUsersCreatePost.Properties
.Integration.RequestTemplates['application/json']
).to.not.match(/extraCognitoPoolClaims/);
});
});

View File

@ -120,6 +120,11 @@ module.exports = {
"principalId": "$context.authorizer.principalId",
"stage": "$context.stage",
"cognitoPoolClaims" : {
extraCognitoPoolClaims
"sub": "$context.authorizer.claims.sub"
},
#set( $map = $input.params().header )
"headers": $loop,
@ -172,6 +177,11 @@ module.exports = {
"principalId": "$context.authorizer.principalId",
"stage": "$context.stage",
"cognitoPoolClaims" : {
extraCognitoPoolClaims
"sub": "$context.authorizer.claims.sub"
},
#set( $map = $input.params().header )
"headers": $loop,

View File

@ -188,6 +188,7 @@ module.exports = {
let identitySource;
let resultTtlInSeconds;
let identityValidationExpression;
let claims;
if (typeof authorizer === 'string') {
if (authorizer.indexOf(':') === -1) {
@ -210,6 +211,7 @@ module.exports = {
resultTtlInSeconds = Number.parseInt(authorizer.resultTtlInSeconds, 10);
resultTtlInSeconds = Number.isNaN(resultTtlInSeconds) ? 300 : resultTtlInSeconds;
claims = authorizer.claims || [];
identitySource = authorizer.identitySource;
identityValidationExpression = authorizer.identityValidationExpression;
@ -233,6 +235,7 @@ module.exports = {
resultTtlInSeconds,
identitySource,
identityValidationExpression,
claims,
};
},