Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[apigateway] support cognito user pool authorizer #5618

Closed
nija-at opened this issue Jan 2, 2020 · 10 comments · Fixed by #12786
Closed

[apigateway] support cognito user pool authorizer #5618

nija-at opened this issue Jan 2, 2020 · 10 comments · Fixed by #12786
Assignees
Labels
@aws-cdk/aws-apigateway Related to Amazon API Gateway effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p1

Comments

@nija-at
Copy link
Contributor

nija-at commented Jan 2, 2020

Add support for cognito user pool authorizer - https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html

Upvote this issue if you'd like this feature in the CDK.


This is a 🚀 Feature Request

@nija-at nija-at added feature-request A feature should be added or improved. needs-triage This issue or PR still needs to be triaged. labels Jan 2, 2020
@SomayaB SomayaB added @aws-cdk/aws-apigateway Related to Amazon API Gateway and removed needs-triage This issue or PR still needs to be triaged. labels Jan 2, 2020
@nija-at nija-at added the effort/medium Medium work item – several days of effort label Feb 5, 2020
@0xdevalias
Copy link
Contributor

May be worth checking out and subscribing to aws/aws-cdk-rfcs#95 as well.

@meleksomai
Copy link

Any progress on this feature? Any workaround in the meantime?

Thanks!

@nija-at
Copy link
Contributor Author

nija-at commented Jul 6, 2020

@meleksomai - you can use the the construct at the CFN layer - CfnAuthorizer - to work around this. However, you will need to configure all of the properties correctly yourself.

@meleksomai
Copy link

@nija-at , thanks. I have tried without much success.

I am following the current approach which was suggested in the following comment: #723 (comment) and it works.

I am sharing a sample of the python code which might be helpful to others.

from aws_cdk import (
    core,
    aws_lambda,
    aws_apigateway,
    aws_cognito
)

class CustomStack(core.NestedStack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        
        super().__init__(scope, id, **kwargs)

        #--------------------------------
        # API Gateway
        #--------------------------------
        custom_api = aws_apigateway.RestApi(self, "CustomRestApi",
            rest_api_name='CustomApiGateway'
            )

        # Defines the AWS Lambda resources
        custom_lambda = aws_lambda.Function(
            self, 'CustomHandler',
            runtime=aws_lambda.Runtime.PYTHON_3_8,
            code=aws_lambda.Code.asset('lambda/'),
            handler='post-handler.handler',
        )
        
        # Adding the resource
        custom_api_resource = custom_api.root.add_resource('management')
        
        # Adding the lambda to the resources
        custom_api_method_post = custom_api_resource.add_method('POST', 
            aws_apigateway.LambdaIntegration(custom_lambda, proxy=True)
        )
        
        # API Gateway Cognito Authorizer
        cognito_authorizer = aws_apigateway.CfnAuthorizer(
            scope=self,
            id='CustomCognitoAuthorizer',
            rest_api_id=custom_api.rest_api_id,
            name='CustomCognitoAuth',
            type='COGNITO_USER_POOLS',
            identity_source='method.request.header.Authorization',
            identity_validation_expression="Bearer (.*)",
            provider_arns=[
                'arn:aws:cognito-idp:us-XXXX-X:XXXXXXXXXX:userpool/'
                'us-XXXX-X_XXXXXXXX']
        )
        post_method_resource = custom_api_method_post.node.find_child('Resource')
        post_method_resource.add_property_override('AuthorizationType', 'COGNITO_USER_POOLS')
        post_method_resource.add_property_override( 'AuthorizerId', {"Ref": cognito_authorizer.logical_id})

The configuration is deployed but the authorization is not triggered. I am not sure if this is because I have to provide an Oauth scope when using Cognito Authorizer.

@0xdevalias
Copy link
Contributor

0xdevalias commented Jul 31, 2020

Just ran into this need myself, and since native support doesn't seem to exist yet, here was my attempted workaround for JavaScript/TypeScript using CfnAuthorizer as suggested above:

References:

import { AuthorizationType, CfnAuthorizer } from '@aws-cdk/aws-apigateway'
import { UserPool } from '@aws-cdk/aws-cognito'

const userPool = UserPool.fromUserPoolId(this, 'UserPool', userPoolId)

// ..snip..

const cognitoAuthorizer = new CfnAuthorizer(this, 'CognitoAuthorizer', {
      name: 'CognitoAuthorizer',
      type: AuthorizationType.COGNITO,
      providerArns: [userPool.userPoolArn],
      identitySource: 'method.request.header.Authorization',
      restApiId: api.restApiId,
    })

// ..snip..

Unfortunately, when trying to use this in the authorizer field of the MethodOptions (later in my code, not shown above), I get the following error:

TS2741: Property 'authorizerId' is missing in type 'CfnAuthorizer' but required in type 'IAuthorizer'.

Hacking a naive custom 'wrapper' around CfnAuthorizer to resolve the above, I came up with:

import { Construct } from '@aws-cdk/core'
import { CfnAuthorizer, IAuthorizer } from '@aws-cdk/aws-apigateway'
import { CfnAuthorizerProps } from '@aws-cdk/aws-apigateway/lib/apigateway.generated'

/**
 * Custom construct that implements a Cognito based API Gateway Authorizer.
 *
 * @see https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_author
 *
 * @see https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apigateway.CfnAuthorizer.html
 * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-authorizer.html
 * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html
 * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-enable-cognito-user-pool.html
 *
 * @see https://github.com/aws/aws-cdk/issues/5618#issuecomment-666922559
 */
export class CognitoApiGatewayAuthorizer extends CfnAuthorizer implements IAuthorizer {
  public readonly authorizerId: string

  constructor(scope: Construct, id: string, props: CfnAuthorizerProps) {
    super(scope, id, props)

    this.authorizerId = this.ref
  }
}

Which can be used similar to the above example, as follows:

- import { AuthorizationType, CfnAuthorizer } from '@aws-cdk/aws-apigateway'
+ import { AuthorizationType } from '@aws-cdk/aws-apigateway'
import { UserPool } from '@aws-cdk/aws-cognito'

+ import { CustomNodeLambdaEndpoint } from './constructs/CustomNodeLambdaEndpoint'

const userPool = UserPool.fromUserPoolId(this, 'UserPool', userPoolId)

// ..snip..

- const cognitoAuthorizer = new CfnAuthorizer(this, 'CognitoAuthorizer', {
+ const cognitoAuthorizer = new CognitoApiGatewayAuthorizer(this, 'CognitoAuthorizer', {
      name: 'CognitoAuthorizer',
      type: AuthorizationType.COGNITO,
      providerArns: [userPool.userPoolArn],
      identitySource: 'method.request.header.Authorization',
      restApiId: api.restApiId,
    })

// ..snip..

Obviously this could be made 'nicer' by wrapping some of the required props into the 'wrapper' itself (eg. type), but I was looking for the simplest/closest 'api' to using CfnAuthorizer directly.


I noticed that @rrix also provided a more thorough TypeScript-based solution in #9023 (comment) which seems to implement authorizerId / support IAuthorizer.

@nija-at Since there seems to be a decently solid looking implementation for this, I'm wondering if we could get an official version of it merged into CDK to save having to use these hacks/workarounds?

@nija-at
Copy link
Contributor Author

nija-at commented Aug 3, 2020

@nija-at Since there seems to be a decently solid looking implementation for this, I'm wondering if we could get an official version of it merged into CDK to save having to use these hacks/workarounds?

@0xdevalias - we absolutely can. This isn't prioritized on our end at the moment, but contributions are welcome 😊

@nija-at nija-at added the p1 label Aug 18, 2020
@NukaCody
Copy link

The documentation for API Gateway may need updated or at least reference this issue.

books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
  authorizationType: AuthorizationType.COGNITO,
  authorizationScopes: ['Scope1','Scope2']
});

This doesn't refer to any authorizer id and fails deployment:

Invalid authorizer ID specified. Setting the authorization type to CUSTOM or COGNITO_USER_POOLS requires a valid authorizer.

But with 0xdevalias solution. I was able to get it running.

    const userPool = cognito.UserPool.fromUserPoolId(this, 'UserPool', '<user pool id>');
    const cognitoAuthorizer = new CognitoApiGatewayAuthorizer(this, 'CognitoAuthorizer', {
      name: 'CognitoAuthorizer',
      type: apigateway.AuthorizationType.COGNITO,
      providerArns: [userPool.userPoolArn],
      identitySource: 'method.request.header.Authorization',
      restApiId: api.restApiId,
    });

    const authDebug = debug.addResource('auth');
    authDebug.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
      authorizer: {
        authorizerId: cognitoAuthorizer.authorizerId,
        authorizationType: apigateway.AuthorizationType.COGNITO,
      },
    });

@mergify mergify bot closed this as completed in #12786 Feb 3, 2021
mergify bot pushed a commit that referenced this issue Feb 3, 2021
feat(apigateway): add support for cognito user pool authorizer

closes #5618 

----

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

github-actions bot commented Feb 3, 2021

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

@lielran
Copy link

lielran commented Feb 8, 2021

@nija-at - is it support only api-gateway v1? any support for v2 (HTTP API)?

@nija-at
Copy link
Contributor Author

nija-at commented Feb 9, 2021

@lielran - #10972

NovakGu pushed a commit to NovakGu/aws-cdk that referenced this issue Feb 18, 2021
feat(apigateway): add support for cognito user pool authorizer

closes aws#5618 

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-apigateway Related to Amazon API Gateway effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p1
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants