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] Unable to add COGNITO_USER_POOLS auth to API Gateway method #9023

Closed
Ara225 opened this issue Jul 11, 2020 · 6 comments
Closed
Assignees
Labels
@aws-cdk/aws-apigateway Related to Amazon API Gateway guidance Question that needs advice or information. needs-triage This issue or PR still needs to be triaged.

Comments

@Ara225
Copy link

Ara225 commented Jul 11, 2020

Unable to add Cognito auth to API Gateway method

Reproduction Steps

        rescue_centre_api = aws_apigateway.RestApi(self, 'rescueCentreAPI', rest_api_name='rescueCentreAPI',
                                                   default_cors_preflight_options={
                                                       "allow_origins": ["*"],
                                                       "allow_methods": ["GET", "POST", "OPTIONS"]
                                                   })

        auth = aws_apigateway.CfnAuthorizer(self, "adminSectionAuth", rest_api_id=rescue_centre_api.rest_api_id,
                                            type='COGNITO_USER_POOLS', identity_source='method.request.header.Authorization',
                                            provider_arns=[
                                                'VALID_PREEXISTING_ARN'],
                                            name="adminSectionAuth"
                                            )
        rehomers_resource = rescue_centre_api.root.add_resource('rehomers')
       get_rehomers_lambda_function = aws_lambda.Function(self, "getrehomersLambda",
                                                           handler='app.lambda_handler',
                                                           runtime=aws_lambda.Runtime.PYTHON_3_8,
                                                           code=aws_lambda.Code.from_asset(
                                                               "lambdas/getLambda"),)
        get_rehomers_lambda_integration = aws_apigateway.LambdaIntegration(
            get_rehomers_lambda_function, proxy=True)
        rehomers_resource.add_method('GET', rehomers_lambda_integration,
                                     authorization_type=AuthorizationType.COGNITO,
                                     authorization_scopes=["openid", "profile", "email"], authorizer=auth)

Error Log

Invalid authorizer ID specified. Setting the authorization type to CUSTOM or COGNITO_USER_POOLS requires a valid authorizer. (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: 549f5e36-dadb-4c19-a14e-fa355b959793)
new Method (C:\Users\User2\AppData\Local\Temp\jsii-kernel-vZCqgM\node_modules@aws-cdk\aws-apigateway\lib\method.js:46:26)
_ Resource.addMethod (C:\Users\User2\AppData\Local\Temp\jsii-kernel-vZCqgM\node_modules@aws-cdk\aws-apigateway\lib\resource.js:17:16)
_ C:\Users\User2\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\jsii_embedded\jsii\jsii-runtime.js:7739:51
_ Kernel._wrapSandboxCode (C:\Users\User2\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\jsii_embedded\jsii\jsii-runtime.js:8388:20)
_ C:\Users\User2\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\jsii_embedded\jsii\jsii-runtime.js:7739:25
_ Kernel._ensureSync (C:\Users\User2\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\jsii_embedded\jsii\jsii-runtime.js:8364:20)
_ Kernel.invoke (C:\Users\User2\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\jsii_embedded\jsii\jsii-runtime.js:7738:26)
he\local-packages\Python38\site-packages\jsii_embedded\jsii\jsii-runtime.js:7377:14)
_ Immediate._onImmediate (C:\Users\User2\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\jsii_embedded\jsii\jsii-runtime.js:7380:37)
_ processImmediate (internal/timers.js:456:21)

Environment

  • **CLI Version :**1.51.0 (build 8c2d53c)
  • **Framework Version:**aws-cdk.aws-apigateway==1.45.0
  • Node.js Version: v12.16.3
  • **OS :**Windows 10
  • Language (Version): Python (3.8.3)

Other

The relevant section of the template as output by cdk synth doesn't seem to include a ID at all. I added a AuthorizerId key to the template manually and deployed it to CloudFormation that way without issue.

rescueCentreAPIrehomersGETAE24A896:
    Type: AWS::ApiGateway::Method
    Properties:
      HttpMethod: GET
      ResourceId:
        Ref: rescueCentreAPIrehomers3DD82C26
      RestApiId:
        Ref: rescueCentreAPID8DB9A2C
      AuthorizationScopes:
        - openid
        - profile
        - email
      AuthorizationType: COGNITO_USER_POOLS
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri:
          Fn::Join:
            - ""
            - - "arn:"
              - Ref: AWS::Partition
              - ":apigateway:"
              - Ref: AWS::Region
              - :lambda:path/2015-03-31/functions/
              - Fn::GetAtt:
                  - rehomerApplicationLambdaBB2EE525
                  - Arn
              - /invocations
    Metadata:
      aws:cdk:path: backend/rescueCentreAPI/Default/rehomers/GET/Resource

This is 🐛 Bug Report

@Ara225 Ara225 added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Jul 11, 2020
@github-actions github-actions bot added the @aws-cdk/aws-apigateway Related to Amazon API Gateway label Jul 11, 2020
@nija-at
Copy link
Contributor

nija-at commented Jul 14, 2020

Take a look at the examples available at #5618 for some guidance on how other folks have used user pools and see if this helps.

@nija-at nija-at added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. guidance Question that needs advice or information. and removed bug This issue is a bug. labels Jul 14, 2020
@rrrix
Copy link

rrrix commented Jul 14, 2020

Here's a TypeScript version of a Cognito User Pool Authorizer I built, modeled off of the CDK's existing IAuthorizer implementations... maybe you can convert it to Python?

import { AuthorizationType, Authorizer, CfnAuthorizer, IAuthorizer, IRestApi } from '@aws-cdk/aws-apigateway';
import { Construct, Lazy, ResourceProps, Stack } from '@aws-cdk/core';

export interface CognitoAuthorizerProps extends ResourceProps {
  /**
   * (Optional) The name of this Authorizer
   *
   * @default The node's logical ID
   */
  authorizerName?: string;
  /**
   * The Identity Source (e.g. header, query string, etc.)
   *
   * @default `method.request.header.Authorization`
   */
  identitySource?: string;
  /**
   * The Cognito User Pool ARN
   */
  userPoolArn: string;
}

/**
 * Amazon Cognito IDP Authorizer for API Gateway REST APIs
 * @extends Authorizer
 * @implements IAuthorizer
 */
export class CognitoAuthorizer extends Authorizer implements IAuthorizer {
  /**
   * The Authorizer ID
   */
  public readonly authorizerId: string;
  /**
   * The API Gateway REST API ID this Authorizer is attached to
   */
  protected restApiId?: string;
  /**
   * The ARN of this Authorizer
   */
  public readonly authorizerArn: string;
  constructor(scope: Construct, id: string, props: CognitoAuthorizerProps) {
    super(scope, id, props);

    const restApiId = this.lazyRestApiId();
    const resource = new CfnAuthorizer(this, 'Resource', {
      name: props.authorizerName ?? this.node.uniqueId,
      restApiId,
      type: 'COGNITO_USER_POOLS',
      identitySource: props.identitySource || 'method.request.header.Authorization',
      providerArns: [props.userPoolArn],
    });

    this.authorizerId = resource.ref;
    this.authorizerArn = Stack.of(this).formatArn({
      service: 'cognito-idp',
      resource: restApiId,
      resourceName: `authorizers/${this.authorizerId}`,
    });
    // We have to do this because CDK's API Gateway L2 requires that IAuthorizers be "custom"
    // even though we have to make this COGNITO
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    this.authorizationType = AuthorizationType.COGNITO;
  }

  /**
   * Attaches this authorizer to a specific REST API.
   * @internal
   */
  public _attachToApi(restApi: IRestApi): void {
    if (this.restApiId && this.restApiId !== restApi.restApiId) {
      throw new Error('Cannot attach authorizer to two different rest APIs');
    }

    this.restApiId = restApi.restApiId;
  }
  /**
   * Returns a token that resolves to the Rest Api Id at the time of synthesis.
   * Throws an error, during token resolution, if no RestApi is attached to this authorizer.
   */
  protected lazyRestApiId(): string {
    return Lazy.stringValue({
      produce: () => {
        if (!this.restApiId) {
          throw new Error(`Authorizer (${this.node.path}) must be attached to a RestApi`);
        }
        return this.restApiId;
      },
    });
  }
}

@Ara225
Copy link
Author

Ara225 commented Jul 14, 2020

Hi,
Thanks for getting back to me, will try that out and let you know.

@Ara225
Copy link
Author

Ara225 commented Jul 14, 2020

Hi,
THe below worked for me. Thanks for pointing me in the right direction, I got a little too wrapped up in the wording of some of the error messages I was getting earlier so I'm afraid I just assume the way I was doing it was right.

            method = rescue_centre_api.add_method(details["method"], lambda_integration)
            method_resource = method.node.find_child('Resource')
            method_resource.add_property_override('AuthorizationType', 'COGNITO_USER_POOLS')
            method_resource.add_property_override( 'AuthorizerId', {"Ref": cognito_auth.logical_id})

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Jul 15, 2020
@nija-at
Copy link
Contributor

nija-at commented Jul 15, 2020

Glad to be of help 😊

@0xdevalias
Copy link
Contributor

@rrrix would be awesome if you were able to open a PR to add your workaround in #9023 (comment) to CDK properly!

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 guidance Question that needs advice or information. needs-triage This issue or PR still needs to be triaged.
Projects
None yet
Development

No branches or pull requests

4 participants