Change AWS Cognitio "Enabled Identity Providers" via Python SDK - amazon-web-services

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.

Related

How do you connect Cognito to Pinpoint for analytics?

I'm trying to get some basic analytics for a Cognito user pool. It seemed simple enough to do, I created a project in Pinpoint, then I went to my user pool, went to General settings > Analytics, clicked the Add Analytics button, choose the Amazon Cognito app client that my app uses, pointed to the Pinpoint project I just created, checked the "Share user profile data" checkbox (though I assume that's not absolutely necessary), and it had the message telling me if would use the IAM role and so on. Clicked Save, got no error, I assumed at this point I would start seeing Analytics in Pinpoint, but there's absolutely nothing showing up.I do have a message saying I haven't enabled any features yet, but I don't see any features I'd need to enable. I don't care about the campaigns as of now, and then under Application analytics it seems geared to you manually updating your mobile or web app to send something, but I thought that was if you need to customize something. Am I mistaken? Will this integration only work if you change your web app to explicitly send things to Pinpoint? I just assumed if I connected Cognito and Pinpoint the analytics would show since Cognito obviously knows people are logging in without you needing to manually make some extra request.
From my research, I found out that since you are using a Web Application without using AWS Amplify framework, you need to add additional lines of code to your application in order to send Cognito authentication analytics data to your Amazon Pinpoint project.
If you are using the Javascript SDK you may add the initate-Auth property code snippet to your front-end application:
var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
var params = {
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: 'STRING_VALUE', /* the client ID attached to the Pinpoint project */
AuthParameters: {
'USERNAME': 'STRING_VALUE',
'PASSWORD': 'STRING_VALUE'
},
AnalyticsMetadata: {
AnalyticsEndpointId: 'STRING_VALUE' /* the Pinpoint project ID */
},
};
cognitoidentityserviceprovider.initiateAuth(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
In the above code snippet, the Pinpoint project/application ID is added as part of the "AnalyticsMetadata" parameter when the client makes the API calls (e.g. sign-in, sign-up, etc.) to the Cognito user pool. Therefore, the API calls will have the pinpoint project ID attached to them and Cognito can use that information to send the data to your Pinpoint project. Without this crucial step, analytics data will not be sent to Pinpoint and will result in the behavior you have described.
If using CLI (for verification/testing purpose), you may execute the following AWS CLI initiate-auth command below :
$ aws cognito-idp initiate-auth --auth-flow USER_PASSWORD_AUTH --auth-parameters USERNAME=STRING_VALUE,PASSWORD=STRING_VALUE --client-id STRING_VALUE --analytics-metadata AnalyticsEndpointId=STRING_VALUE
The take away point is that :
Amazon Cognito integration with Amazon Pinpoint only works for apps (clients) that are using Cognito SDK for Mobile Apps (AWS Mobile SDKs or JavaScript - AWS Amplify JavaScript library).
Just a note to syumaK's response, yes you need to update your code's initAuth call to include the AnalyticsMetadat property. However, I found out that the AnalyticsEndpointId should NOT be the Pinpoint project ID.
I believe that since you've configured Cognito already to integrate with the pinpoint project, it knows which pinpoint project you are sending metrics to already. The AnalyticsEndpointId should be a uniquely identifier for the login.
The documentation is definitely flaky here. The cli one from syumaK's seems to describe it differently than Cognito API Reference
What happened to me was that I used the pinpoint project id, and when I log in with multiple users, it thinks it's the same one. The daily active users remains at one. AWS Support clarified that it should be a unique identifier for each user. So after changing the id to be the user's email, I am starting to get accurate numbers for the daily active users.
It also seems like this is just about as useful as it is going to be for not using the Cognito SDK for Mobile Apps or Amplify. You can only get information like daily/monthly active users, authentication metrics. You don't have the ability to further break down by segments, etc.

Is it possible to login to Amazon Cognito via REST API without using the SDK

I'm looking at AWS Cognito documentaion here
Authentication with a User Pool
Actually I looked at many links in the documentation without finding clear information about this.
In AWS Cognito, I successfully created user pool, app client and integrated signup and login in Android and iOS using the platform provided SDK (amplify). But I want to do that directly from REST client, for testing purposes to generate user tokens. I want to submit the required credentials, username and password and get the user token as I do from the SDK.
I also tried the answer here but it gives an error
{
"__type": "NotAuthorizedException",
"message": "Unable to verify secret hash for client 1034me0p4rkfm17oidu7mkunu5"
}
Is this is something possible and how?
I just managed to get it done. There is a setting while you create an application client in Cognito console Enable Client Secret
To get that functionality to work, You need to create another App client with Enable Client Secret disabled. Then use the example mentioned in this answer

Register user cognito in django

I am applying cognito into django and try to write a registered user api I used warrant library and are faulty.
boto3.setup_default_session(region_name='ap-southeast-2')
user_cognito = Cognito('your-user-pool-id','your-client-id')
user_cognito.register(user['username'], user['password'])
print(user_cognito)
my error is:
NotAuthorizedException at /api/register_user
An error occurred (NotAuthorizedException) when calling the SignUp operation: Unable to verify secret hash for client 'your-client-id'
please help me
You need to create an app without client secret.
It seems that currently, AWS Cognito doesn't handle client secret as it should. In your user pool try to create a new app without generating a client secret. Then use that app to signup a new user or to confirm registration. It worked for me.

PermissionDenied: 403 IAM permission 'dialogflow.intents.list'

I'm trying to get the list of the intents in my Dialogflow agent using Dialogflow's V2 APIs but have been getting the following error:
PermissionDenied: 403 IAM permission 'dialogflow.intents.list' on 'projects/xxxx/agent' denied.
I adopted the following steps:
I created a new agent(with V2 APIs enabled) and a new service account for it.
I downloaded the JSON key and set my GOOGLE_APPLICATION_CREDENTIALS variable to its path.
Following is my code:
import dialogflow_v2 as dialogflow
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]="/home/user/folder/service-account-key.json"
client=dialogflow.IntentsClient()
parent = client.project_agent_path('[PROJECT_ID]')
for element in client.list_intents(parent):
pass
I have made various agents and service accounts and even changed the role from Admin to Client but can't figure out any solution. I tried the following solution but didnt' work
Tried Solution: DialogFlow PermissionDenied: 403 IAM permission 'dialogflow.sessions.detectIntent'
There is no need for creating a new Agent. You can edit the existing agents IAM.
In Dialogflow's console, go to settings ⚙ > under the general tab, you'll see the project ID section with a Google Cloud link to open the Google Cloud console > Open Google Cloud.
In google cloud, go to IAM Admin > IAM under tab Members. Find the name of your agents and then click on edit.
Give admin permissions to the agent to give permissions to list intent.
The problem lies in the IAM section of GCP. Probably you are making a POST request with a role that does not have the necessary authorizations.
Look into your key.json file that contains the field "client_email"
Proceed to the IAM page and set the relevant role with that email to
a role that has posting capabilities. (e.g. Admin)
This solved my problem.
In Dialogflow's console, go to settings ⚙ > under the general tab, you'll see the project ID section with a Google Cloud link to open the Google Cloud console > Open Google Cloud.
(Optional) In the Cloud console, go to the menu icon > APIs & Services > Library. Select any APIs (if any) > Enable.
In Cloud Console > under the menu icon ☰ > APIs & Services > Credentials > Create Credentials > Service Account Key.
Under Create service account key, select New Service Account from the dropdown and enter a project name and for role choose Owner > Create.
JSON private key file will be downloaded to your local machine that you will need.
For Javascript:
In the index.js file you can do service account auth with JWT:
const serviceAccount = {}; // Starts with {"type": "service_account",...
// Set up Google Calendar Service account credentials
const serviceAccountAuth = new google.auth.JWT({
email: serviceAccount.client_email,
key: serviceAccount.private_key,
scopes: 'https://www.googleapis.com/auth/xxxxxxx'
});
For Python:
There's a Google Auth Python Library available via pip install google-auth and you can check out more here.
When you create the intentClient, use following:
key_file_path = "/home/user/folder/service-account-key.json";
client=dialogflow.IntentsClient({
keyFilename: key_file_path
})
Intents list
This error message is usually thrown when the application is not being authenticated correctly due to several reasons such as missing files, invalid credential paths, incorrect environment variables assignations, among other causes. Keep in mind that when you set an environment variable value in a session, it is reset every time the session is dropped.
Based on this, I recommend you to validate that the credential file and file path are being correctly assigned, as well as follow the Obtaining and providing service account credentials manually guide, in order to explicitly specify your service account file directly into your code; In this way, you will be able to set it permanently and verify if you are passing the service credentials correctly.
Passing the path to the service account key in code example:
def explicit():
from google.cloud import storage
# Explicitly use service account credentials by specifying the private key
# file.
storage_client = storage.Client.from_service_account_json('service_account.json')
# Make an authenticated API request
buckets = list(storage_client.list_buckets())
print(buckets)
Try also to create project in DialogFlow Console
https://dialogflow.cloud.google.com/
You need to create the following as environment variable
googleProjectID: "",
dialogFlowSessionID: "anything",
dialogFlowSessionLanguageCode: "en-US",
googleClientEmail: "",
googlePrivateKey:
I think you might have missed the Enable the API section in the documentation setup.
Here is that link:
https://cloud.google.com/dialogflow/cx/docs/quick/setup#api
After clicking the link, select the chatbot project you created and fill the necessary instructions given there.
The permissions that I have given for that project are Owner, and editor.
After this, try the code in this link:
https://cloud.google.com/dialogflow/es/docs/quick/api#detect_intent
You should get a response from your chatbot
Hope this helps!

From AWS SDK, how to I get the current logged in username (or IAM user)?

I'm using the Ruby SDK (V2), but I guess my question is more general than the specific implementation as I couldn't find an answer in any of the SDKs.
How do I get the username (and/or IAM user) that my session currently belongs to?
I let the SDK run its default behaviour for choosing credentials (ENV vars, then 'default' profile or other if specified and then machine role). Then I initialize my client and run commands. I'd like to know 'who is running the commands'. I expect to get the AWS username and if the chosen credentials were of an IAM user in it, then this username too.
Any ideas?
The best I got so far was that after I build a Client object, I can query it's actual config and get Credentials. But that only gives me what credentials were chosen (i.e. SharedCredentials profile='default' vs. Credentials key=.. secret=..) and doesn't tell me who is the username behind it.
Many thanks!
Be careful with your terminology -- interactions with the AWS APIs are all over HTTP, and are sessionless and stateless, so there's not really a concept of the currently "logged in" user, or a "session."
However, for a given set of credentials, you can fetch the attributes of the "current" user (the user whose credentials you're using) from Aws::IAM::CurrentUser.
http://docs.aws.amazon.com/sdkforruby/api/Aws/IAM/CurrentUser.html
Apologies for the lack of an example -- I am unfamiliar with Ruby in general -- but found this based on what I knew could be done with the direct query APIs and command line client with aws iam get-user. The available attributes are all the same: user_name, password_last_used, create_date, user_id, path, and arn... so I suspect this is what you're looking for.
From the Query API docs:
it defaults to the user making the request
STS (Security Token Service) provides an API for this:
GetCallerIdentity Returns details about the IAM identity whose credentials are used to call the API.
http://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html