C# Lambda Get Cognito Identity

Hi,
I’ve created some serverless functions that use a cognito user pool as the authorizer.
I can successfully call the lambdas behind them.

What i can’t seem to work out is how to get the “sub”, or any identifier for that matter, of the caller of the lambda.
The serverless documentation points out that they have mapped to the “identity” field of the request, but this is null when i read it in.
The lambda documentation says they have an Identity property of the ILambdaContext class. This is not null, but the values for IdentityId and IdentityPoolId are empty.

Some googling found some people suggesting to use AWS_IAM rather than Cognito as the authorizer, however i don’t think this is right for my use case as i want the ID of the caller, not just to know they are authenticated.

This may be that C# is not yet fully featured by serverless?
Does anyone have any advice?

Thanks,

I’ve found the solution to this, details about the claimed identity are available as part of the “requestContext” attribute.

Sample"

"requestContext": {
    "accountId": "1234",
    "resourceId": "abc",
    "stage": "dev",
    "authorizer": {
        "claims": {
            "sub": "sub",
            "aud": "aud",
            "email_verified": "true",
            "token_use": "id",
            "auth_time": "1234",
            "iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/user_pool_id",
            "cognito:username": "you@email.com",
            "exp": "Wed Apr 05 12:50:18 UTC 2017",
            "iat": "Wed Apr 05 11:50:18 UTC 2017",
            "email": "you@email.com"
        }
    },
    "requestId": "1234-1234-1234",
    "identity": {
        "cognitoIdentityPoolId": null,
        "accountId": null,
        "cognitoIdentityId": null,
        "caller": null,
        "apiKey": null,
        "sourceIp": "220.244.228.54",
        "accessKey": null,
        "cognitoAuthenticationType": null,
        "cognitoAuthenticationProvider": null,
        "userArn": null,
        "userAgent": "agent-string",
        "user": null
    },
    "resourcePath": "/api/do",
    "httpMethod": "POST",
    "apiId": "abc123"
},
"body": "{field:'value'}"

interesting/disappointing that “identity” is not populated at all.

Hope this helps someone.

Hi @barticus,
IMO “serverless” is mainly a tool to deploy your function(s) and doesn’t limit what your function(s) can do.

If you protect your endpoint with a “Cognito Authorizer” and assuming you use lambda proxy integration and you pass the ID token as a request header, then you should be able to get the “sub” claim as follows:

<yourRequestObject>.requestContext.authorizer.claims.sub 

(edit: it’s requestContext and not context)
see AWS’ mapping reference

In case it helps, here is a Java example for my framework JRestless that also explains how to set everything up: aws-gateway-security-cognito-authorizer

The cognito related data in the lambda context (ILambdaContext in case of C#) as well as in “yourRequestObject.context.identity…” will only be set if you invoke your API Gateway endpoint through the AWS SDK and you use “Cognito (Federated) Identity” (working on an example for this for JRestless, as well :wink: ).

Hope this helps.

The cognito related data in the lambda context (ILambdaContext in case of C#) as well as in “yourRequestObject.context.identity…” will only be set if you invoke your API Gateway endpoint through the AWS SDK and you use “Cognito (Federated) Identity” (working on an example for this for JRestless2, as well :wink: ).

This was really confusing for me too. You would think since they have a shiny button in the console for using Cognito Pools as an authorizer they would fill out all that for us instead of just dumping the claims. In NodeJS this is the output when I invoke my API via postman

            "identity": {
                "cognitoIdentityPoolId": null,
                "accountId": null,
                "cognitoIdentityId": null,
                "caller": null,
                "apiKey": "",
                "sourceIp": "REDACTED",
                "accessKey": null,
                "cognitoAuthenticationType": null,
                "cognitoAuthenticationProvider": null,
                "userArn": null,
                "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3175.3 Safari/537.36",
                "user": null
            },

Furthermore, if you used Federated Identities to get IAM creds to auth with the api via sig4 how does the API know who the user is? Do you have an example of how to invoke api gateway endpoints using “Cognito (Federated) Identity” so that those properties are not null?

Hi VictorioBerra,

I don’t think this is possible, when you get iam creds you are assuming a particular iam role, and are thus acting as that role rather than as the user you assumed the credentials with.
In my application, i don’t get IAM creds or use the sig4 authentication, once you have authenticated the user directly with cognito you will get a JWT which you supply as your authorization header and thats all there is to it. API Gateway gives you a little tool to validate that a token is valid for it.

It depends on what language you are using for your front end, I am using javascript so this project was a great reference i looked at when creating my interactions between cognito, and then to API gateway.

Hope that helps.

Hi @VictorioBerra ,
It’s a little difficult to present you a full example, here.
In general you need an Identity Pool and use that to log your user in using the SDK. If you also use a User Pool as an authentication provider and want to invoke your APIGW through JS, later, you may find “Use Case 17” here useful.
Once you managed to log users in, you furthermore need to generate an SDK for your APIGW and invoke the endpoints through it. You may find this useful: Invoke API Gateway function with Cognito Authentication from Javascript

Note: the “cognitoIdentityId” will be the “user’s” ID in the Identity Pool; not the User Pool.

Whats the difference between these?

Okay everyone I got it working. Here is what I did.

In the AWS Console

  • Create a lambda function
  • Create a user pool
    • Create a user for yourself and verify the email. We will change the password later
    • Create a client app. Uncheck the client secret checkbox
  • Create a federated identity (that uses the user pool)
  • Create/Edit Authed and Unauthed roles
    • On the Authed role, go to IAM and add a managed policy to allow full access to invoke APIG
  • Create an API Gateway resource and a method (ANY)
    • Use lambda as the integration, proxy requests to it
    • Enable CORS on resource
    • Set Authorization to AWS_IAM

In your code

Auth and get creds. There are a number of ways to do this. Now that you have a user pool you can use the front-end library amazon-cognito-identity-js this will allow you to authenticate and get a JWT (call authenticate() with the above library). With the JWT you can use the CognitoIdentityCredentials and config.credentials.get to actually populate the AccessKeyId and SecretAccessToken and SessionToken.

FINALLY use Postman (NOT THE CHROME APP, you must download the desktop app) to call your APIG and there you go!

Postman

I have some code samples and blog posts coming soon. I have to clean up my code a lot and move hardcoded stuff to text inputs.

2 Likes

any news on your blog posts? I am on my way too and any more infos are badly needed… :wink:

Its been a while since I worked on this, but i think this is what you want:

My github code samples:

1 Like