AWS Cognito: where is the metadata URL of Cognito User Pool? - amazon-web-services

I'm trying to use AWS Cognito as an authorizer for my REST API in AWS API Gateway.
It asks me to fill in the Issuer URL:
Digging through the AWS Cognito User Pool page, there is no such thing.
I found a related answer here: AWS: Cognito integration with a beta HTTP API in API Gateway?
and I quote:
Issuer URL: Check the metadata URL of your Cognito User Pool
(construct the URL in this format :: https://cognito-idp.
[region].amazonaws.com/[userPoolId]/.well-known/openid-configuration
:: look for a claim named "issuer". Copy its Value and paste it here.
I can of course build the url as said above.
But still, where is the metadata URL of my Cognito User Pool????
Am I missing something really basic and being absolutely silly by asking this question?
Where is it??
This is driving me crazy.

The issuer URL of a Cognito User Pool has the following format:
https://cognito-idp.[region].amazonaws.com/[userPoolId]
As you stated correctly, you can get it from Cognito's well-known metadata endpoint, which is available at
https://cognito-idp.[region].amazonaws.com/[userPoolId]/.well-known/openid-configuration
This file is JSON-formatted and contains an issuer field, which contains the URL mentioned above. The whole file looks like this:
{
"authorization_endpoint":"https://cognito-idp.[region].amazonaws.com/[userPoolId]/authorize",
"id_token_signing_alg_values_supported":[
"RS256"
],
"issuer":"https://cognito-idp.[region].amazonaws.com/[userPoolId]",
"jwks_uri":"https://cognito-idp.[region].amazonaws.com/[userPoolId]/.well-known/jwks.json",
"response_types_supported":[
"code",
"token"
],
"scopes_supported":[
"openid",
"email",
"phone",
"profile"
],
"subject_types_supported":[
"public"
],
"token_endpoint":"https://cognito-idp.[region].amazonaws.com/[userPoolId]/token",
"token_endpoint_auth_methods_supported":[
"client_secret_basic",
"client_secret_post"
],
"userinfo_endpoint":"https://cognito-idp.[region].amazonaws.com/[userPoolId]/userInfo"
}

Related

Cognito Access Token "cognito:groups" missing

I want to authenticate my API Gateway requests with Cognito.
For that i created custom scopes. API Gateway checks those scopes and proxies these requests to my Elastic Beanstalk API. This works fine.
But another part of my Authorization are groups. Based on a assigned group some actions have restricted Access. I need to use groups because i want to be able to add or remove those groups during user-lifecycle. The group will be checked in my Elastic Beanstalk API.
Problem
The documentation states that Access Tokens contain the cognito:groups claim. But a setup like in the Image below does not include this claim in my token.
The following decoded jwt will be produced after a login via hosted-UI. As you can see the claim is missing. ID tokens (with openid scope) will include this group. I am also sure that i've tested Cognito earlier with Amplify JS-SDK which included the group. But there i was unable to include my custom scopes.
{
"sub": "xxxxxxxxxxxxxxxxxxxxxx",
"token_use": "access",
"scope": "api.example.com/item.read api.example.com/item.write",
"auth_time": 1615325374,
"iss": "https://cognito-idp.eu-central-1.amazonaws.com/eu-central-1_xxxxxxx",
"exp": 1615328974,
"iat": 1615325374,
"version": 2,
"jti": "f37219a5-c8b0-411b-bdb3-ab7d9201b491",
"client_id": "xxxxxxxxxxxxxxx",
"username": "xxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Do I miss about a restriction or configuration issue? Why is the group missing inside my Access Tokens?
Thanks for your help!
I had the same issue. The cognito:groups value appeared after I added the openid scope:
and the access token is still supplied, as per earlier comments.

AWS Amplify 'currentUserCredentials()' returns unexpected authenticated value, bug?

When calling Auth.currentUserCredentials() after Auth.signIn() I get valid valid credentials, but for an unauthenticated user, why?
Code:
async signIn({ dispatch, state }, { email, password }) {
try {
const user = await Auth.signIn(email, password);
console.log("User state after login")
const userCredentialsAfterLogin = await Auth.currentUserCredentials();
console.log(userCredentialsAfterLogin)
} catch (error) {
console.log("error")
console.log(error)
return
}
await dispatch('fetchUser')
},
Expected behaviour:
After signing in with a valid user, Auth.currentUserCredentials() should return an authenticated set of Credentials.
Actual behaviour:
Auth.currentUserCredentials() returns an unauthenticated user with the authenticated property set to false and a 400 error, "ResourceNotFoundException: IdentityPool 'eu-west-1:62dab5ed-5a84-4064-a7a2-87d1d0df511b'
System:
authenticationFlowType: "USER_SRP_AUTH"
Versions: "aws-amplify": "^3.3.14", "aws-amplify-vue": "^2.1.4", amplify version 4.42.0
config
{
"authSelections": "userPoolOnly",
"resourceName": "testapp89e81d50",
"serviceType": "imported",
"region": "eu-west-1"
}
I understand where you're coming from, and honestly I can't really show you clear documentation that exactly states why this won't work. AWS documentation on Cognito and Amplify is difficult to piece together, both because the Amplify framework still uses an old library under the hood ('amazon-cognito-identity-js') and Cognito is the name for both a connect-login-with-IAM and signup/signin-as-a-service offering. Cognito is super powerful and rock solid in terms of security if done right, but the setup is a bit of a pain.
There's a bit of documentation, e.g. the API docs of Amplify Auth here. You can see there that currentCredentials / currentUserCredentials gives you some object which contains among other things an 'identitiId'. Credentials, in the Amplify Auth framework, refer to AWS IAM credentials that refer to an Cognito Identity.
You seem to be using Amplify to login to a Cognito User Pool, using email/password. A Cognito User Pool can be connected to a Cognito Identify pool, to 'exchange' a Cognito JWT token for some credentials that can be used to use AWS resources (IAM credentials). This is not needed to have a normal sign in / sign up flow working though.
So, the question is: what do you want?
Do you want to know about the currently logged in Cognito User Pool user, e.g. his email, JWT token and other fields that are stored in the JWT token? Use 'currentUserInfo' or 'currentUserSession'
Do you actually want to have some IAM credentials to invoke AWS resources? Make sure to create and connect your Cognito User Pool with a Cognito Identity Pool and configure your Identity Pool id in your frontend settings. If you've done that, you should be able to use 'currentCredentials'.

Cannot test Cognito authenticated API Gateway call in Postman (its an ADMIN_NO_SRP_AUTH pool)

I've managed to successfull login to the API gateway I've made via my iOS device and Cognito. The problem is I'd like to use postman to test the API calls then implement them on the phone. Currently, Postman cannot authenticate (despite AWS saying it can). No matter what I do I get a 401 error (visible in the screen-shots)
What I've tried
Downloaded the postman collection from AWS Api Gateway
Then imported it into postman, and switch the authentication to "AWS Signature"
And Here is a screen shot of the Postman Generated Header Info
If I understand correctly, you are trying to call an API Gateway endpoint that is behind the built-in Cognito Authoriser.
I think you've misunderstood how you call an Cognito Authorised API Gateway:
Authorise against Cognito to get an id_token
Call API Gateway with the Authorization header set to id_token
Renew id_token every hour
By enabling ADMIN_NO_SRP_AUTH you're allowing the first step (sign-in to Cognito) to be simplified so that you can more easily do it manually. (If you hadn't, then you would need to do SRP calculations).
One way to get the id_token is to use the aws cli (further ways are shown in the documentation):
aws cognito-idp admin-initiate-auth --user-pool-id='[USER_POOL_ID]' --client-id='[CLIENT_ID]' --auth-flow=ADMIN_NO_SRP_AUTH --auth-parameters="USERNAME=[USERNAME],PASSWORD=[PASSWORD]"
You can then use the result (AuthenticationResult.IdToken) as the Authorization header in Postman (no need for the AWS v4 signature- that is only for IAM authentication).
n.b. a much fuller explanation with images can be found here.
Here is what I finally did to fix postman auth issues
1) Turned off App Client Secret in the Cognito pool.
2) Ran aws --region us-east-1 cognito-idp admin-initiate-auth --cli-input-json file://gettoken.json
JSON file example
{
"UserPoolId": "us-east-1_**********",
"ClientId": "******************",
"AuthFlow": "ADMIN_NO_SRP_AUTH",
"AuthParameters": {
"USERNAME": "*********",
"PASSWORD": "***********"
}
}
3) Went to Postman > Authorization > Bearer Copied the idToken value into the token field and everything worked.
NOTE: For those wondering if not using a secret client key is safe. See this article.

AWS Cognito Post Authentication Lambda Trigger - groupConfiguration

Is it possible, via a post-authentication lambda to alter the list of groups exposed by the AWS Cognito Identity token?
The documentation for the post-authenticaion Lambda states the following:
"....
groupConfiguration structure – contains group-related information that can override group-related claims in the identity token."
Full docs: http://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-post-auth
The AWS Cognito Identity token exposes the current payload:
{
sub: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
cognito:groups: [
"group1",
"group2"
],
iss: "https://cognito-idp.*****/**-****-1_********",
cognito:username: "Google_*****************",
.....
}
What I would like to to, via a post-authentication lambda is to alter the list of cognito-groups.
Any suggestions on how to do this?
There is a mixup in the documentation. This is not currently supported. We are actively working to fix it.

Using Firebase OpenID Connect provider as AWS IAM Identity Provider

I get the following error while setting up Firebase as an AWS IAM Identity Provider using OpenID Connect.
We encountered the following errors while processing your request:
Please check .well-known/openid-configuration of provider:
https://securetoken.google.com/<Project ID> is valid.
The AWS IAM Identity Provider setup requires two input parameters, to which I plugged in the following:
Provider URL: https://securetoken.google.com/<Firebase Project ID>
Audience: <Firebase Client ID>
To troubleshoot the error, I opened http://<Provider URL>/.well-known/openid-configuration in a browser and noted the JSON response has the Issuer and jwks_uri fields. I believe these JSON fields indicate the Firebase OpenID Connect Provider URL is valid.
Any idea how I could avoid the above error and successfully set up the AWS IAM Identity Provider?
I contacted AWS support and they helped resolve the problem. Thanks to Shaun H # AWS!
The solution to the problem is to use AWS CLI instead of AWS console to set up an OIDC provider.
I'm pasting relevant parts of Shaun's response below:
1.) Manually obtain and verify the thumbprint using the procedure described here[1].
"ThumbprintList" = "6040DB92306CC8BCEB31CACAC88D107430B16AFF"
2.) Create the OIDC identity provider using the AWS Cli [2].
For example: $ aws iam create-open-id-connect-provider --cli-input-json file://oidc.json Note - the format would be:
aud Audience Must be your Firebase project ID, the unique identifier for your Firebase project, which can be found in the URL of that project's console.
iss Issuer Must be https://securetoken.google.com/<projectId>, where is the same project ID used for aud above.
Content for file://oidc.json: (replace with your Project ID)
{
"Url": "https://securetoken.google.com/<Firebase Client ID>",
"ClientIDList": [ "<Firebase Client ID>" ],
"ThumbprintList": [ "6040DB92306CC8BCEB31CACAC88D107430B16AFF" ]
}
[1] http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
[2] http://docs.aws.amazon.com/cli/latest/reference/iam/create-open-id-connect-provider.html