From 39e3089396e1daa19429e956c8ba6ca4431f5fe3 Mon Sep 17 00:00:00 2001 From: Simon Elder Date: Fri, 5 Apr 2019 16:25:44 +1100 Subject: [PATCH 1/2] Add authorization scopes support for cognito user pool integration --- .../apiGateway/lib/method/authorization.js | 18 ++++++++++++++---- .../events/apiGateway/lib/method/index.test.js | 6 ++++++ .../compile/events/apiGateway/lib/validate.js | 3 +++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/method/authorization.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/method/authorization.js index c9314397b..03957b8e8 100644 --- a/lib/plugins/aws/package/compile/events/apiGateway/lib/method/authorization.js +++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/method/authorization.js @@ -26,15 +26,25 @@ module.exports = { const authorizerLogicalId = this.provider.naming .getAuthorizerLogicalId(http.authorizer.name); - let authorizationType; const authorizerArn = http.authorizer.arn; + + let authorizationType; if (typeof authorizerArn === 'string' && awsArnRegExs.cognitoIdpArnExpr.test(authorizerArn)) { authorizationType = 'COGNITO_USER_POOLS'; - } else { - authorizationType = 'CUSTOM'; + const cognitoReturn = { + Properties: { + AuthorizationType: authorizationType, + AuthorizerId: { Ref: authorizerLogicalId }, + }, + DependsOn: authorizerLogicalId, + }; + if (http.authorizer.scopes) { + cognitoReturn.Properties.AuthorizationScopes = http.authorizer.scopes; + } + return cognitoReturn; } - + authorizationType = 'CUSTOM'; return { Properties: { AuthorizationType: authorizationType, diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/method/index.test.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/method/index.test.js index 705e477ce..0c457203d 100644 --- a/lib/plugins/aws/package/compile/events/apiGateway/lib/method/index.test.js +++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/method/index.test.js @@ -502,6 +502,7 @@ describe('#compileMethods()', () => { authorizer: { name: 'authorizer', arn: 'arn:aws:cognito-idp:us-east-1:xxx:userpool/us-east-1_ZZZ', + scopes: ['myapp/read', 'myapp/write'], }, integration: 'AWS', path: 'users/create', @@ -516,6 +517,11 @@ describe('#compileMethods()', () => { .Resources.ApiGatewayMethodUsersCreatePost.Properties.AuthorizationType ).to.equal('COGNITO_USER_POOLS'); + expect( + awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate + .Resources.ApiGatewayMethodUsersCreatePost.Properties.AuthorizationScopes + ).to.contain('myapp/read'); + expect( awsCompileApigEvents.serverless.service.provider.compiledCloudFormationTemplate .Resources.ApiGatewayMethodUsersCreatePost.Properties.AuthorizerId.Ref diff --git a/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js b/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js index f0b724b68..fd957ddc3 100644 --- a/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js +++ b/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js @@ -220,6 +220,7 @@ module.exports = { let identityValidationExpression; let claims; let authorizerId; + let scopes; if (typeof authorizer === 'string') { if (authorizer.toUpperCase() === 'AWS_IAM') { @@ -258,6 +259,7 @@ module.exports = { resultTtlInSeconds = Number.parseInt(authorizer.resultTtlInSeconds, 10); resultTtlInSeconds = Number.isNaN(resultTtlInSeconds) ? 300 : resultTtlInSeconds; claims = authorizer.claims || []; + scopes = authorizer.scopes; identitySource = authorizer.identitySource; identityValidationExpression = authorizer.identityValidationExpression; @@ -295,6 +297,7 @@ module.exports = { identitySource, identityValidationExpression, claims, + scopes, }; }, From cabed40f3aa7e66441068ead1fd8da6db5853459 Mon Sep 17 00:00:00 2001 From: Simon Elder Date: Mon, 8 Apr 2019 14:55:05 +1000 Subject: [PATCH 2/2] Scope example ... --- docs/providers/aws/events/apigateway.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/providers/aws/events/apigateway.md b/docs/providers/aws/events/apigateway.md index b32ca8b88..dd3e98439 100644 --- a/docs/providers/aws/events/apigateway.md +++ b/docs/providers/aws/events/apigateway.md @@ -279,7 +279,7 @@ functions: maxAge: 86400 ``` -If you are using CloudFront or another CDN for your API Gateway, you may want to setup a `Cache-Control` header to allow for OPTIONS request to be cached to avoid the additional hop. +If you are using CloudFront or another CDN for your API Gateway, you may want to setup a `Cache-Control` header to allow for OPTIONS request to be cached to avoid the additional hop. To enable the `Cache-Control` header on preflight response, set the `cacheControl` property in the `cors` object: @@ -446,7 +446,7 @@ functions: ``` You can also configure an existing Cognito User Pool as the authorizer, as shown -in the following example: +in the following example with optional access token allowed scopes: ```yml functions: @@ -458,6 +458,8 @@ functions: method: post authorizer: arn: arn:aws:cognito-idp:us-east-1:xxx:userpool/us-east-1_ZZZ + scopes: + - my-app/read ``` If you are using the default `lambda-proxy` integration, your attributes will be @@ -1242,7 +1244,7 @@ functions: events: - http: path: /users - ... + ... authorizer: # Provide both type and authorizerId type: COGNITO_USER_POOLS # TOKEN or REQUEST or COGNITO_USER_POOLS, same as AWS Cloudformation documentation @@ -1254,7 +1256,7 @@ functions: events: - http: path: /users/{userId} - ... + ... # Provide both type and authorizerId type: COGNITO_USER_POOLS # TOKEN or REQUEST or COGNITO_USER_POOLS, same as AWS Cloudformation documentation authorizerId: