I am doing a POC for an application that will use SSO from Salesforce using OpenID and pass the id_token to cognito user identity to get temporary credentials for s3. I have set up all the roles and services and app on AWS/Salesforce. I am able to access s3 when I enable unauthorized access for my identity. But whenever I try to pass the id_token for authenticated access it throws me this error:
botocore.errorfactory.NotAuthorizedException: An error occurred
(NotAuthorizedException) when calling the GetId operation: Invalid
login token. Issuer doesn't match providerName
I am following the tutorial here https://aws.amazon.com/blogs/security/building-an-app-using-amazon-cognito-and-an-openid-connect-identity-provider/
I am using python Boto3. This is my current code:
import boto3
id_token='aaaaaa.bbbbbbbb.cccccccc' #Got from the url salesforce sends after successful authentication
client = boto3.client('cognito-identity', 'us-east-2')
resp = client.get_id(AccountId='123456789123', IdentityPoolId='us-east-2:xxxxxxx-yyyy-zzz-hhhhh-jj888hhhh',
Logins={
'provider_url': id_token
}
)
Any help would be greatly appreciated.
Apparently the problem was the provider_url as the error suggested. I was simply putting login.salesforce.com when instead i had to change it to what the id_token was returning as their issuer id. I had to change it in the AWS access providers in IAM as well as in code.
Related
On Google Business Profile API (Google MyBusiness), I am getting following error when I try to impersonate with an email address:
('unauthorized_client: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.', {'error': 'unauthorized_client', 'error_description': 'Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.'})
I am trying to achieve this using a Python script which is using Google API Client Library:
file_location = '/some/folder/file.json'
impersonated_email = 'abc#abc.com'
scope = ["https://www.googleapis.com/auth/business.manage"]
credentials = ServiceCredentials.from_service_account_file(file_location, scopes=scope, subject=impersonated_email)
If I try to access the endpoint without using the subject parameter, it is working. But of course the main purpose here is impersonating. And the Google documentation says it is possible to impersonate with the subject parameter (or via with_subject function).
By the way, if I tried some invalid mail address, my error is changing to: ('invalid_grant: Invalid email or User ID', {'error': 'invalid_grant', 'error_description': 'Invalid email or User ID'})
So I assume that I can get the user credentials; but have no idea what could have been wrong.
Does anybody have any idea about the issue? What could be the possible issues?
Well, Google explains that JWT error code like that:
error field: unauthorized_client
error_description field: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.
Meaning:
A service account was authorized using the client email address rather than the client ID (numeric) in the Admin console.
How to resolve:
In the Domain-wide delegation page in the Admin console, remove the client, and re-add it with the numeric ID.
I tried that but I still got the error.
Then, after some digging; I saw that you only can impersonate G-Suite accounts.
So, after that I tried same code with another real-person mail which is a G-Suite account and it worked.
I'm new to firebase and I'm trying to update some data in an existing project but I'm getting the following error: 401 Client Error: Unauthorized for url. So how to fix this problem and thank you! I just want to mention also that I have been added to the project, so I'm not the owner.
this is my code:
from firebase import firebase
firebase = firebase.FirebaseApplication("the http path", None) # None bcz we are testing
firebase.put("/esco-lebanon/device-configs/atest-dev", "brightness", 50)
print("Updated")
According to the documentation, a 401 error means one of the following:
The auth token has expired.
The auth token used in the request is invalid.
Authenticating with an access_token failed.
The request violates your Firebase Realtime Database Rules.
The understanding here is that your client code needs to correctly identify a Firebase Authentication user with a token in access_token, and that user account must have access to read the data in the database according to its security rules. Since you haven't provided a token, your access is coming in anonymously, so you could only query data where security rules allow universal access.
If you haven't investigated using authentication in your request, you should read the documentation about that.
I have created a sample congnito app and added few users, now i am trying to access the users from python code , but getting below error, i have developer access. Please let me know how to get user details from cognito
code:
import boto3
client = boto3.client('cognito-idp',region_name='us-east-2')
response = client.admin_get_user(
UserPoolId='us-east-2_XXXXXXX',
Username='newuser'
)
error:ClientError: An error occurred (ExpiredTokenException) when calling the AdminGetUser operation: The security token included in the request is expired
I would like to use boto3 to get temporary credentials for access AWS services. The use case is this: A user in my Cognito User Pool logs in to my server and I want the server code to provide that user with temporary credentials to access other AWS services.
I have a Cognito User Pool where my users are stored. I have a Cognito Identity Pool that does NOT allow unauthorized access, only access by users from the Cognito User Pool.
So here is the code I am starting with:
import boto3
client = boto3.client('cognito-identity','us-west-2')
resp = client.get_id(AccountId='<ACCNTID>',
IdentityPoolId='<IDPOOLID>')
However, just running these three lines of code throws an exception:
botocore.errorfactory.NotAuthorizedException: An error
occurred (NotAuthorizedException) when calling
the GetId operation: Unauthenticated access is not
supported for this identity pool.
Since my Cognito Identity Pool is not set up for unauthenticated access, it seems that I cannot call get_id until I somehow authenticate somewhere.
How do I solve this? What exactly do I need to do to authenticate so I can call get_id?
UPDATE: Looks like I need to pass a Logins field and data to the get_id function call, but to do that I need the login JWT token. If I am running this inside a webapp (eg a Django backend) where I use the AWS Cognito prepackaged login screens, then yes I can get this from the homepage URL after redirection from successful login. But now I am writing some test scripts that have nothing to do with a website. Is there a way to use boto or boto3 or some other python package to login with username and password and get JWT token?
Just to add to the answer from Arka Mukherjee above, to get the token I do this:
auth_data = { 'USERNAME':username , 'PASSWORD':password }
provider_client=boto3.client('cognito-idp', region_name=region)
resp = provider_client.admin_initiate_auth(UserPoolId=user_pool_id, AuthFlow='ADMIN_NO_SRP_AUTH', AuthParameters=auth_data, ClientId=client_id)
token = resp['AuthenticationResult']['IdToken']
Here I have to use the username and password of the Cognito user, client_id is the app client id for the app client that I set up thru Cognito, and user_pool_id is the user pool id.
Note that my app client has this option checked/selected: Enable sign-in API for server-based authentication (ADMIN_NO_SRP_AUTH) and I created that app client with no secret key (apparently that is important for web clients especially).
To pass the Cognito User Pool JWT Token, you would need to use the Logins Map in the GetId API call. You could try the following Python code out on your end, after replacing the necessary placeholders.
response = client.get_id(
AccountId='string',
IdentityPoolId='string',
Logins={
'cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>': '<JWT ID Token>'
}
)
If you do not provide a Logins Map, Amazon Cognito treats the authentication event as Unauthenticated, and hence, you are facing this error.
I have been stuck on the following issue for quite some time now. Within Python I want users to retrieve a token based upon their username and password from the AWS cognito-identity-pool making use of srp authentication. With this token I want the users to upload data to s3.
This is part of the code I use (from the warrant library): https://github.com/capless/warrant
self.client = boto3.client('cognito-idp', region_name="us-east-1")
response = boto_client.initiate_auth(
AuthFlow='USER_SRP_AUTH',
AuthParameters=auth_params,
ClientId=self.client_id
)
def get_auth_params(self):
auth_params = {'USERNAME': self.username,
'SRP_A': long_to_hex(self.large_a_value)}
if self.client_secret is not None:
auth_params.update({
"SECRET_HASH":
self.get_secret_hash(self.username,self.client_id, self.client_secret)})
return auth_params
However, I keep on getting:
botocore\auth.py", line 352, in add_auth raise NoCredentialsError
botocore.exceptions.NoCredentialsError: Unable to locate credentials
I was able to get rid of this error by adding credentials in the .aws/credentials file. But this is not in line with the purpose of this program. It seems like there is a mistake in the warrant or botocore library and the it keeps on attempting to use the AWS Access Key ID and AWS Secret Access Key from the credentials file, rather than that the given credentials (username and password) are used.
Any help is appreciated
I am on to Cognito team. initiate auth is an unauthenticated call so it shouldn't require you to provide AWS credentials. The service endpoint will not validate the sigv4 signature for these calls.
That being said, some client libraries have certain peculiarities in the sense that you need to provide some dummy credentials otherwise the client library will throw an exception. However you can provide anything for the credentials.
I too ran into this, using warrant.
The problem is that the boto3 libraries are trying to sign the request to aws, but this request is not supposed to be signed. To prevent that, create the identity pool client with a config that specifies no signing.
import boto3
from botocore import UNSIGNED
from botocore.config import Config
client = boto3.client('cognito-idp', region_name='us-east-1', config=Config(signature_version=UNSIGNED))
AWS Access Key ID and AWS Secret Access Key are totally different from username and password.
The Boto3 client has to connect to the AWS service endpoint (in your case: cognito-idp.us-east-1.amazonaws.com) to execute any API. Before executing an API, the API credentials (key+secret) have to provided to authenticate your AWS account. Without autheticating your account, you cannot call cognito-idp APIs.
There is one AWS account (key/secret) but there can be multiple users (username/password).