2

I made a custom lambda authorizer that validates the JWT and returns Allow policy.

 var context = new APIGatewayCustomAuthorizerContextOutput();

 var tokenUse = ExtractClaims(claims, "token_use");
 context["tokenType"] = tokenUse;
 var response = new APIGatewayCustomAuthorizerResponse
 {
     PrincipalID = "asd",
     PolicyDocument = new APIGatewayCustomAuthorizerPolicy
     {
         Version = "2012-10-17",
         Statement = new List<APIGatewayCustomAuthorizerPolicy.IAMPolicyStatement>()
         {
             new APIGatewayCustomAuthorizerPolicy.IAMPolicyStatement
             {
                 Action = new HashSet<string>() {"execute-api:Invoke"},
                 Effect = "Allow",
                 Resource = new HashSet<string>() {"***"} // resource arn here
              }
          },
      },
      Context = context
 };

 return response;

Now I need to use this Identity on my resource server.

The problem is that the claims I put in the authorizer context appears under authorizer directly

 "authorizer": {
            "cognito:groups": "Admin", ...
 }

but my Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction expects those under authorizer.claims.

like such:

 "authorizer": {
            "claims": {
                "cognito:groups": "Admin", ... 
             }
  }

And I know that, because it was working when I was using the built in Cognito User Pool authorizer, which was making the input like that.

I managed to find that Lambda Authorizer is not allowed to add nested objects to the context (and tested that it throws authorizer error if I do.)

I also found that when APIGatewayProxyFunction is extracting the Identity, it looks at Authorizer.Claims.

So I need to either extract them on my resource server bypassing the Claims property somehow, or add a nested object to the authorizer response, which is not allowed.

What do?

LLL
  • 2,900
  • 2
  • 20
  • 36

1 Answers1

2

So I solved this by overriding the PostCreateContext method on my LambdaEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction.

protected override void PostCreateContext(
        HostingApplication.Context context,
        APIGatewayProxyRequest apiGatewayRequest, ILambdaContext lambdaContext)
{
        // handling output from cognito user pool authorizer
        if (apiGatewayRequest?.RequestContext?.Authorizer?.Claims != null)
        {
            var identity = new ClaimsIdentity(apiGatewayRequest.RequestContext.Authorizer.Claims.Select(
                entry => new Claim(entry.Key, entry.Value.ToString())), "AuthorizerIdentity");

            context.HttpContext.User = new ClaimsPrincipal(identity);
            return;
        }

        // handling output from lambda authorizer
        if (apiGatewayRequest?.RequestContext?.Authorizer != null)
        {
            var identity = new ClaimsIdentity(apiGatewayRequest.RequestContext.Authorizer.Select(
                entry => new Claim(entry.Key, entry.Value.ToString())), "AuthorizerIdentity");

            context.HttpContext.User = new ClaimsPrincipal(identity);
        }
    }

Edit: also submitted a pull reqeust to the aws-lambda-dotnet library fixing this.

Edit 2: My pull request has been merged for some time and this is not an issue anymore if using an up to date Amazon.Lambda.AspNetCoreServer (not sure which version first had it, but 3.1.0 definitely has it)

LLL
  • 2,900
  • 2
  • 20
  • 36