Reputation: 1
I have a local moto server and am verifying cognito-idp in boto3 with awssrp, but I get an error.
The error message is.
Traceback (most recent call last):
File "/tests/get_token.py", line 71, in <module>
token_res = get_cognito_token(cognito_user_name, cognito_user_password)
File "/tests/get_token.py", line 63, in get_cognito_token
tokens = response.authenticate_user()
File "/Users/myuser/.pyenv/versions/3.9.14/lib/python3.9/site-packages/warrant/aws_srp.py", line 210, in authenticate_user
tokens = boto_client.respond_to_auth_challenge(
File "/Users/myuser/.pyenv/versions/3.9.14/lib/python3.9/site-packages/botocore/client.py", line 530, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/Users/myuser/.pyenv/versions/3.9.14/lib/python3.9/site-packages/botocore/client.py", line 960, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.errorfactory.UserNotFoundException: An error occurred (UserNotFoundException) when calling the RespondToAuthChallenge operation: User does not exist.
The code is as follows.
create user and sign up code no error... create_user.py
import boto3
import json
cognito_client = boto3.client('cognito-idp', region_name="us-east-1", endpoint_url='http://localhost:5000')
response = cognito_client.create_user_pool(
PoolName='local_pool'
)
# print(response)
cl_pool_id = response['UserPool']['Id']
print(f"response_code:{response['ResponseMetadata']['HTTPStatusCode']}")
print(f"pool_id:{response['UserPool']['Id']}")
create_user_res = cognito_client.create_user_pool_client(
UserPoolId=cl_pool_id,
ClientName='local_user7',
ExplicitAuthFlows=[
# 'ADMIN_NO_SRP_AUTH',
# 'CUSTOM_AUTH_FLOW_ONLY',
# 'USER_PASSWORD_AUTH',
'ALLOW_ADMIN_USER_PASSWORD_AUTH',
# 'ALLOW_CUSTOM_AUTH',
'ALLOW_USER_PASSWORD_AUTH',
'ALLOW_USER_SRP_AUTH',
'ALLOW_REFRESH_TOKEN_AUTH',
],
)
cl_client_id = create_user_res['UserPoolClient']['ClientId']
print(f"client_id:{cl_client_id}")
cognito_user_name = "dummy7"
cognito_user_email = "[email protected]"
cognito_user_password = "P@ssw0rd"
create_user_res = cognito_client.admin_create_user(
UserPoolId=cl_pool_id,
Username=cognito_user_name,
UserAttributes=[
{
'Name': 'email',
'Value': cognito_user_email
},
{
'Name': 'email_verified',
'Value': "true"
},
],
MessageAction='SUPPRESS',
)
print(f"create_user_res:{create_user_res}")
set_user_pass = cognito_client.admin_set_user_password(
UserPoolId=cl_pool_id,
Username=cognito_user_name,
Password=cognito_user_password,
Permanent=True
)
print(f"set_user_pass_res:{set_user_pass}")
list_users = cognito_client.list_users(
UserPoolId=cl_pool_id,
)
print(f"list_users:{list_users}")
user_pool_client = cognito_client.describe_user_pool_client(
UserPoolId=cl_pool_id,
ClientId=cl_client_id,
)
print(f"user_pool_client:{user_pool_client}")
authenticate code with error. get_token.py
import ast
import base64
import boto3
import json
import logging
import os
import re
from warrant.aws_srp import AWSSRP
pool_id = "us-east-1_8d32eabf665f214687c6ba15282a4ad20d36fdae19d630"
client_id = "jp4v9277l6pca2v5ei2v0p5ayh"
cognito_user_name = "dummy7"
cognito_user_email = "[email protected]"
cognito_user_password = "P@ssw0rd"
cognito_client = boto3.client('cognito-idp', region_name="us-east-1", endpoint_url='http://localhost:5000')
def get_cognito_token(username, password):
response = AWSSRP(
username=cognito_user_name,
password=cognito_user_password,
pool_id=pool_id,
client_id=client_id,
client=cognito_client,
)
print(f"response:{response}")
print(f"response_dir:{dir(response)}")
# print(f"response_vars:{vars(response)}")
tokens = response.authenticate_user()
result = tokens["AuthenticationResult"]
return result
token_res = get_cognito_token(cognito_user_name, cognito_user_password)
print(f"token_res:{token_res}")
error I search various things from the contents, but moto server itself seems to support srp as well. I tried password authentication with moto server, which is not srp, for a user that has already been created, and it authenticated without problems. I would like to know if anyone has succeeded in mocking with moto server using srp.
Upvotes: 0
Views: 430
Reputation: 1
I ran into a very similar error. Repro below. For me, specifying UsernameAttributes when creating the User Pool (uncommenting the commented line) makes it work.
From the logs, Warrant is sending the user ID in the challenge response (rather than the username). But it looks like moto uses admin_get_user which is ultimately keyed from the username unless the UsernameAttributes
are specified. Because I'm using the email as the username, this works in my case. But I don't think that works in your case.
I can see from the logs of a production AWSSRP handshake that that is also sending the username in the InitiateAuth but the user ID in the RespondToAuthChallenge. This makes me think that respond_to_auth_challenge in moto isn't quite replicating the API here.
import boto3
import moto
from warrant.aws_srp import AWSSRP
boto3.set_stream_logger("botocore")
mock = moto.mock_cognitoidp()
mock.start()
REGION = "us-east-1"
client = boto3.client("cognito-idp", region_name=REGION)
USER_POOL_ID = client.create_user_pool(
PoolName="MyPool",
UsernameConfiguration={
"CaseSensitive": False,
},
# UsernameAttributes=["email"],
)["UserPool"]["Id"]
USER_POOL_CLIENT_ID = client.create_user_pool_client(
UserPoolId=USER_POOL_ID,
ClientName="MyClient",
ExplicitAuthFlows=["ALLOW_USER_SRP_AUTH"],
)["UserPoolClient"]["ClientId"]
USERNAME = "[email protected]"
client.admin_create_user(
UserPoolId=USER_POOL_ID,
Username=USERNAME,
MessageAction="SUPPRESS",
)
PASSWORD = "abc123"
client.admin_set_user_password(
UserPoolId=USER_POOL_ID,
Username=USERNAME,
Password=PASSWORD,
Permanent=True,
)
srp = AWSSRP(
username=USERNAME,
password=PASSWORD,
pool_id=USER_POOL_ID,
client_id=USER_POOL_CLIENT_ID,
client=client,
)
srp.authenticate_user()
Upvotes: 0