Custom attribute not passed into ID_TOKEN created by AWS Cognito - amazon-web-services

I am not able to get custom attribute in ID_TOKEN returned from AWS Cognito after successful user login.
Steps I tried :
1.Created user pool
2.Created app client and checked the custom attribute(customattrib1,customattrib2)
User Pool screen :
Check custom attribute in app client config
3.Created user using admin-create-user api
Below image shows the value for user attributes:
4.Signed in user using aws-cognito-auth.js in client app.The ID token returned do not contain the custom attribute.
ID_TOKEN
{
"at_hash": "PKfjYDaiEty5mUOyJZlPQA",
"sub": "639d5016-2bd3-4c6f-b82d-21ae38071b09",
"email_verified": true,
"iss": "https://cognito-idp.ap-south-1.amazonaws.com/ap-south-1_XXXXXXX",
"phone_number_verified": true,
"cognito:username": "testuser",
"aud": "XYXYXYXYX",
"token_use": "id",
"auth_time": 1549349674,
"phone_number": "##########",
"exp": 1549353274,
"iat": 1549349674,
"email": "testuser#somedomain.com"
}
I have already checked links below, which had some info regarding this issue, but nothing helped so far.
Adding Cognito custom attributes post pool creation?
Cognito User Pool custom attributes do not show up in the ID token if user pool is configured with a SAML identity provider
Cognito User Pool custom attributes do not show up in the ID token if user pool is configured with a SAML identity provider
https://www.reddit.com/r/aws/comments/a07dwg/cognito_add_custom_attribute_to_jwt_token/
Please help me figure out if I am missing something..

In your Cognito user pool go to General Settings -> App Clients, then for each app client click on Show Details, then Set attribute read and write permissions. Check the checkbox next to your attribute name under Readable Attributes.
In your Cognito user pool go to App client settings -> Allowed OAuth Scopes and enable profile scope.

I had the same trouble and your question came up when I was searching for a solution.
My custom attributes started to appear in ID token when I enabled profile scope in 'App client settings'. (available at: AWS console-> 'User pools'-> click your pool -> 'App client settings' -> 'Allowed OAuth Scopes')
(BTW: I was misled by this sentence from the documentation: "The openid scope returns all user attributes in the ID token that are readable by the client". In my case openid scope was not enough.)

For me the problem was that I was getting my token (after authenticating with the Amplify js library) from:
Auth.currentSession().then(u => u.getAccessToken().getJwtToken())
Instead of:
Auth.currentSession().then(u => u.getIdToken().getJwtToken());
After changing it worked fine! Hope it helps!

For anyone coming here that is using the Amplify SDK like the OP - Copy and Paste calls out an important point that your client ALSO needs to explicitly ask for the scope.
In my case we I am using Angular. After adding "profile" to the User Pool "Allowed OAuth Scopes" - you also need to specify it in your client configuration:

Related

How to debug Cognito's idpresponse endpoint

I'm setting up OIDC provider for Cognito User pool. The open id connect service I'm using is Paypal. At the step where paypal issues code and redirects to cognito's /oauth2/idpresponse endpoint after which cognito is supposed to exchange the code for access token, I'm receiving "Exception processing authorization code" error. As you can see the error message is not very discriptive.
I have no idea what I'm doing wrong. I did setup open id connect properly. Setup client settings in cognito and etc.
These are the endpoints I'm using for openid connect:
https://www.sandbox.paypal.com/signin/authorize
https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice
https://api.sandbox.paypal.com/v1/oauth2/token/userinfo
https://api.sandbox.paypal.com/v1/oauth2/certs
In app client settings I have auth code grant flow and implicit flow enabled. I have custom domain setup. I provided paypal client id and secret
My guess is if I'm able to somehow debug idpresponse endpoint I should be able to solve the problem. Is there any way to do that? Maybe cloudwatch?
I don't know about debugging Cognito's endpoints, but I had the same problem and fixed it by doing the following:
Go to your User Pool in AWS.
In the side navigation under Federation, select Attribute mapping.
Click the tab of the identity provider you're having issues with (in my case it was Google).
There should be three columns, Capture, Google attribute, and User pool attribute. Make sure all of the attributes that are checked in the Capture column are mapped to an attribute in the User pool attribute column.
UPDATE:
After submitting this answer, I realized that the checkboxes in the Capture column are not checked by default. If you marked any attributes as required in the Attributes section of your user pool, then you need to map those attributes to the attributes provided by your external identity providers.
For example, I marked email as a required attribute in my user pool settings. So, when I added Google as an identity provider, I had to go to Federation->Attribute mapping, click on the tab for Google, check the box in the Capture column next to email, and select Email from the dropdown box in the User pool attribute column.
After taking these steps, the sign in work-flow worked for me.
My guess is the auth flow works just fine between Cognito and your identity provider, but Cognito doesn't know how to map the attributes returned from the identity provider to the attributes you have set in your user pool (in General settings->Attributes under the Which standard attributes are required section).

Change AWS Cognitio "Enabled Identity Providers" via Python SDK

There is a setting I want to change via Python SDK reguarding AWS Cognito. I can change the setting in the AWS Web Console via "Cognito -> User Pools -> App Client Settings -> Cognito User Pool" (See image)
Here is my code
client = boto3.client('cognito-idp')
client.update_user_pool_client(
UserPoolId=USER_POOL_ID,
ClientId=user_pool_client_id,
SupportedIdentityProviders=[
'CognitoUserPool'
]
)
The error I am receiving is
An error occurred (InvalidParameterException) when calling the
UpdateUserPoolClient operation: The provider CognitoUserPool
does not exist for User Pool xxxxxx
It is unclear what string values I should pass for SupportedIdentityProviders. The only hint I have seen is from https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-idp-settings.html
--supported-identity-providers '["MySAMLIdP", "LoginWithAmazon"]'
I am not even 100% sure if the SupportedIdentityProviders relates to the setting I am trying to change, but can't find any clarification in the docs.
The correct value to pass is COGNITO
client.update_user_pool_client(
UserPoolId=USER_POOL_ID,
ClientId=user_pool_client_id,
SupportedIdentityProviders=[
'COGNITO'
]
)
I only discovered this by reviewing source code of someone else CloudFormation Custom resource https://github.com/rosberglinhares/CloudFormationCognitoCustomResources/blob/master/SampleInfrastructure.template.yaml#L105
I can not find the correct soluion to this from offical AWS Docs/Boto3 docs. If anyone knows where the possible values for SupportedIdentityProviders are documented please comment.
For SAML/ OIDC, the array of provider names can be passed as SupportedIdentityProviders when update user pool client.
In order to update the existing SupportedIdentityProviders in user pool client, first fetch the existing SupportedIdentityProviders using describeUserPoolClient function.
Then you can push your provider name to exisiting SupportedIdentityProviders and update the user pool client with this value.

How do I integrate amazon cognito login in postman?

I was using Amazon Cognito user pool for login. When I access my web application, I get a redirect to
https://<domain>.auth.<region>.amazoncognito.com/login?response_type=code&client_id=<client id>&redirect_uri=<callback> .
Once logged in with the username/password of a user from the pool, I will be redirected to the callback URL with the code as a query parameter. I can use this to get tokens. How do I integrate this in postman so that I can use the token for my upcoming request?
I have an example of doing this...
The callback URL as defined in the Cognito User Pool console under App Integration / App client settings.
The URL for the login endpoint of your domain. This will be under Cognito User Pool / App Integration / Domain Name
Client ID is found under Cognito User Pool / General Settings / App clients
List the scopes you want to include in the Access Token. These must be enabled under Cognito User Pool / App Integration / App client settings. These can be either standard or custom scopes. Custom scopes are defined under App Integration / Resource servers and must include the resource server ID (e.g. https://myresource.com/myscope)
Click Request Token
You may now log in to your Cognito User Pool and receive an Access Token!
The problem is that once you have the Access Token it isn't usable within Postman because Cognito expects it to be bare and Postman automatically prepends 'Bearer' to the token:
The token can be used in cURL though:
curl -i -H "Authorization: dyJraWQiOiI1YVcwTUlqN1hBaHg4Yzh4Q3JNT2RsQjhZWjlCR3NQOE9BbkFlVFJtUklRPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI3YmEwZmMzOC01ZDcwkYS05MTI5ZTBmYTUzNTEiLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6Imh0dHBzOlwvXC9hcGkubXk5MC5jb21cL3BvbGljZURlcGFydG1lbnRzLnJlYWQiLCJhdXRoX3RpbWUiOjE1NDA1OTIzMTYsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX2xIbGo4NXpRYSIsImV4cCI6MTU0MDU5NTkxNiwiaWF0IjoxNTQwNTkyMzE2LCJ2ZXJzaW9uIjoyLCJqdGkiOiJhN2JiOWU2MC1kNmY1LTQ3ODYtODMwYi0xODdkZDZmYTZlODAiLCJjbGllbnRfaWQiOiI2MzhlYmZ1dTdiZDRkMXVkYnRzY2pxcnJncyIsInVzZXJuYW1lIjoicm9qbyJ9.O_GAxfFX3IQfLUu5Hxr05Wrk_2QDwNSL8tvDdEU0Dzs9d1XhQPafT6ney6yiGnKPOwsO8HhWdbT1QdDmByjuwQAURf1Da4Au7c-yhfgJcqWuHWZ4mledTSP8ukXqihMb4PoaDdU4JXyOdMLa50dBXVMgJNyXTpIulWOxFhiTW6DeQbnxNDk94cGNz_CTKCEqKStiloFZfLR7ndSrWqdOQ_SU__YV0RyKXZyK5yguv3nkUcI6cuKpbPVIZ5DNdpufbrtOLuZcC6HePBKrbTKjSZCt5-swy3YrwnY4ApTX7QUFzof6FylWaLA_KVP3Zv6ksSJ_IjBMFH1NRVHh4lbsOA" \
https://xxxxx.execute-api.us-east-1.amazonaws.com/v1/myresource/1234
by yl.
Thanks to Robert Jordan for his above postman OAuth2.0 configuration post.
I'll try to cover here the entire Cognito user pool definition part to make it easier.
Ok,
Open the Cognito console and follow the bellow stages:
1) create new user pool
name: Test1
left panel menu->Attributes
Select the following radio buttons:
o Email address or phone number - Users can use an email address or phone number as
their "username" to sign up and sign in.
o Allow email addresses
And checkboxes:
[v] email
[v] name
Screenshot:
Press the [Create Pool] button.
(if not available yet to the wizard - press [Review Details] option on the left panel menu)
2) left panel menu->App Clients
press: [add app client]
App client name: me1
clear all checkboxes but the:
[v] Enable username password based authentication (ALLOW_USER_PASSWORD_AUTH)
Leave Radio buttons as is:
o Enabled (Recommended)
Screenshot:
press [create app client]
3) copy and keep the 'App client id'
this is a string format similar to 5psjts111111117jclis0mu28q
Screenshot:
4) left panel menu->App Client settings
Enabled Identity Providers: [v]Select all
[v] Cognito User Pool
Callback URL(s): put the api gw url or https://www.google.com/
OAuth 2.0
Allowed OAuth Flows
[v] Implicit grant
Allowed OAuth Scopes
[v] openid
Screenshot:
5) left panel menu->Domain name
put a string in the prefix field, for instance: music123456789
check if available using the 'check' button.
your domain now is: https://music123456789.auth.us-east-1.amazoncognito.com
Screenshot:
6) left panel menu->Users and Groups
press [Create user]
Username (Required): Your.Mail#company.com
clear all [v] check boxes
Temporary password: Xx123456!
eMail: Your.Mail#company.com
7) in POSTMAN
Press new Request
enter the 'Authorization' tab
Select TYPE: OAuth 2.0
press the [Get new Access Token] button and fill in:
Token Name: myToken123
Grant Type: select 'implicit' from the listbox
callback URL: https://www.google.com/
(as in clause 4 or in cognito console->App Integration->App client settings)
Auth URL: https://music123456789.auth.us-east-1.amazoncognito.com/login
(as in clause 5 + '/login' suffix, what you have defined in cognito
console->App Integration->Domain Name)
Client ID: 5psjts343gm7gm7jclis0mu28q (the app client id - as in 3,
what you have defined in cognito console->General Settings->App clients)
Scope: openid (as in 4, what you have defined in cognito console->App
client settings->Allowed OAuth Scopes)
COGNITO to OKTA idp configuration
When connecting Cognito to Okta IDP, Configuration should be as follows:
Okta Setup
Cognito Setup
Postman setup
As an addition to very through explanations of Robert Jordan and ylev, I made it work by using the id_token instead of the Access Token.
In the token details page, copy the id_token and add it to the header manually without Bearer prefix:
Source: https://github.com/postmanlabs/postman-app-support/issues/6987
For those wanting to move away from the deprecated "implicit" grant to the recommended "authorization" aka "authorization code" grant, you'll want to have the following in Postman:
Grant Type: Authorization Code (Authorization Code with PKCE would prevent the code from being used by anyone else if it were intercepted in transit but either or... you probably want to start with getting "Authorization Code" working.)
Callback URL: https://oauth.pstmn.io/v1/callback (or whatever Postman sets it to when you check "Authorize using browser"
Auth URL: https://{app name you chose when creating the custom auth domain}.auth.{aws region}.amazoncognito.com/login e.g. https://myapp.auth.us-east-1.amazoncognito.com/login. You can find this in AWS Console -> Cognito -> the user pool -> App Integration tab -> Domain section -> Cognito domain (use the Actions dropdown to create a custom domain if you don't already have one).
Access Token URL: https://{app name}.auth.{aws region}.amazoncognito.com/oauth2/token e.g. https://myapp.auth.us-east-1.amazoncognito.com/oauth2/token.
Client ID: The Client ID corresponding to the "App Client" (e.g. the web app users will be authenticating through Cognito to use), found in AWS Console -> Cognito -> the user pool -> App Integration tab -> App Client List section -> the App Client.
Client Secret: An optional added security measure. This should never be sent to the web app as the client secret could then be extracted by a nefarious user via Chrome Dev Tools or the like. You can (and should) however use Client Secret with backend applications e.g. the API service backing your frontend web app. This is a decision that has to be made in AWS when the App Client is created within the Cognito User Pool, but don't fret- App Clients are easy to create/delete/recreate if you change your mind or pick the wrong setting.
Scope: OAuth uses "scopes" as a means of defining what the application which holds and uses the access token (e.g. some web app) can do/access on behalf of the user whose account it's using. It's similar to authorization in a web app (e.g. only users in the "admin" group can access the settings page) but it's meant to be authorization with respect to a user's metadata, so typically that manifests as user metadata the app has access to, for example the user's calendar or contacts or phone number. OAuth scope is not meant to replace an app's authorization system (e.g. RBAC) so if you're just making some web app and just need Cognito to handle user signup, storing and resetting passwords for users, etc. you can more or less ignore OAuth "scope", though you should probably be setting the "Scope" value in Postman to something like "openid email" (Scopes are separated by a single space and you can't request and obtain the "email" scope without also requesting "openid") so you at least get the user's email address in the access token to compare with your "Users" table in your app's database. Scope makes more sense and becomes more relevant in a scenario where your web app is authenticating with an actual third-party (not your own Cognito user pool), like Facebook or Google. Maybe you're making an app that syncs users' friends' contact data from Facebook to.. I don't know, a CSV file downloaded to your computer for backup purposes. In this case you want to request from Facebook's OAuth server the "friends-list" scope or whatever Facebook decided to call that scope. On the other hand, if you just need Facebook as a means for allowing your users to easily sign in to your app without having to create an account, you don't need the "friends-list" or any other scope from Facbeook (maybe just the scope that gives you the user's email address?).
Other fields:
Client Authentication: Send client credentials in body
Type: OAuth 2.0
Add authorization data to: Request Headers
Sources:
https://www.czetsuyatech.com/2021/01/aws-generate-cognito-access-token.html
https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-user-pool-oauth-2-0-grants/
https://api.slack.com/legacy/oauth-scopes
If your client supports USER_PASSWORD_AUTH you can request valid bearer tokens using the aws client.
read -s -p "Password: " && \
aws cognito-idp initiate-auth \
--client-id <client id> \
--auth-flow USER_PASSWORD_AUTH \
--auth-parameters "USERNAME=<username>,PASSWORD=$REPLY"
This can be added to Postman under Authorization / Type: Bearer Token.
For Postman 8.5.1 and AWS Chalice + Cognito user pool on the backend I have working example:
Cognito > User pools > > App integration > App client settings
About vars:
{{cognito_callback_url}} - Your Callback URL(s) from App client
settings
{{cognito_auth_url}} - Cognito > User pools >
> App integration > Domain name + /login
(https://.....auth.ap-south-1.amazoncognito.com/login)
{{cognito_client_id}} - Your App client web id from App client
settings
{{cognito_scope}} - Use 'openid'
Now click the Get the new access token in the bottom and authorize yourself using existing user data from pool
I thought i would post some more information about using cognito with an elastic load balancer. AWS load balancers do not current support auth via headers :( you can get it working on postman by copying cookies from a successfull web request into the postman request
The use-case you want to implement can be achieved by using the OAuth 2.0 authorization. If you can get the Auth URL/ Access Token URL, Client ID, and the Client Secret- you should be able to do it.
Here's a link to the documentation of the various authorization types we support including the above mentioned one- https://www.getpostman.com/docs/v6/postman/sending_api_requests/authorization.
Cheers.

How to block Facebook webhook calls for app specific users? [duplicate]

There is documentation for test users in the Facebook Developer online documentation but how do you delete actual users where the application doesn't show in their app list anymore? This is with the knowledge of the access_token and facebook_user_id.
Used to delete Test Users:
https://graph.facebook.com/893450345999?method=delete&access_token=A2ADI1YMySweBABBGrWPNwKMlubZA5ZCrQbxwhtlEd9FIQUrOVjsGD3mnIWEbUhzDz7dkuBekMFdHvjvJ9CZAU7EMSSaZBsgN60FkMCi3AAZDZD
Running the test user link produces the following error:
"error": {
"message": "(#100) Can only call this method on valid test users for your app",
"type": "OAuthException",
"code": 100
}
You seek for application de-authorization:
You can de-authorize an application or revoke a specific extended permissions on behalf of a user by issuing an HTTP DELETE request to PROFILE_ID/permissions with a user access_token for that app.
permission - The permission you wish to revoke. If you don't specify a permission then this will de-authorize the application completely.
To achieve this issue request to:
https://graph.facebook.com/me/permissions?method=delete&access_token=...
Once application de-authorized it will not appear in the list of user's applications.
Update December 2021
Follow the reference for Requesting & Revoking Permissions:
To remove single permission issue a DELETE request to /{user-id}/permissions/{permission-name} passing user access token or an app access token
To de-authorize an app completely issue similar request to the /{user-id}/permissions endpoint
Real users 'delete' themselves from your app when they remove your app from their account, you don't have to do anything.
If you would like to know when users de-authorize your app like this, you can specify a Deauthorize Callback URL in your app's settings. As described in the docs at https://developers.facebook.com/docs/authentication/:
Upon app removal we will send an HTTP POST request containing a single parameter, signed_request, which, once decoded, will yield a JSON object containing the user_id of the user who just deauthorized your app. You will not receive an user access token in this request and all existing user access tokens that were previously issued on behalf of that user will become invalid.
UPDATE: To remove your own app from the user's authorized applications, issue an HTTP DELETE to https://graph.facebook.com/[userid]/permissions?access_token=... as per https://developers.facebook.com/docs/reference/api/user/.
Typically Graph API calls also support doing an HTTP POST with an extra parameter, method=DELETE, in case DELETE calls are not possible/supported.
To do it:
You must have the user access token.
Visit https://developers.facebook.com/tools/debug/accesstoken/ and debug the user access token.
Copy App-Scoped User ID
Via API call HTTP DELETE to https://graph.facebook.com/[App-Scoped User ID]/permissions?method=delete&access_token=[YOUR-APP-ACCESS-TOKEN]

Retrieve all user attributes and user Roles into JWT self-contained

Which configuration needs to put, to retrieve all user attributes (Claims) and associated user Roles into JWT acces_token self-contained on OAuth 2 authentication patterns ?
Please note that I am into a multi-tenant configuration, with only one Service Provider where we have configured Inbound Authentication Configuration to OAuth/OpenID Connect Configuration, with OAuth-2.0.
Action that has been realised:
1. Specify Requested Claims into Service Provider (use Local Claim Dialect), see below
Service Provider Claim Configuration
Verify if default information is present into Registry, section: /_system/config/oidc into openid property:
openid=sub,email,email_verified,name,family_name,given_name,middle_name,nickname,preferred_username,profile,picture, website,gender,birthdate,zoneinfo,locale,updated_at,phone_number,phone_number_verified,address,street_address,country,formatted,postal_code,locality,region
3.Retrieve an acces_token https://{{auth0_domain}}/oauth2/token
Each time we have only :
{
"sub": "SANDBOX-TEST.COM/usertest#sandbox-test.com",
"aud": [
"Y058MDvS1NSe_NrqSV84vDJ6JHga"
],
"azp": "V0458MDvS3NSe_NrqSE84vDJ8JHga",
"iss": "https://localhost:9443/oauth2/token",
"exp": 1519148273,
"iat": 1519144673,
"jti": "4366e42c-48b1-42c6-bf52-a084f1521851"
}
Any help/ideas is much appreciated.
I hope this is the latest IS version. I will give you few tips to troubleshoot this issue.
Make sure the user that you trying to authenticate do have values for given claims. You can do this by login in to admin portal of Identity Server and viewing the user profile of the specified user.
In "/_system/config/oidc" claims are given in OIDC dialect. Make sure you have correct mapping to local claim dialect to the respective OIDC claim in the claim configurations section.
Since this is OIDC make sure you pass the "openid" scope.