[ad_1]
I have a Cognito User Pool working with MFA enabled (optional), and I am currently working on setting up Device Tracking so that users can bypass MFA for trusted devices (“Allow users to bypass MFA for trusted devices” set to “Yes”).
I am using the AWS SDK for Ruby, and can successfully step through the admin_initiate_auth
and admin_respond_to_auth_challenge
steps. When I run confirm_device
I am getting an exception:
Invalid device credentials given, no credentials given
Searching on Google for the exception message, I’ve so far been unable to find any examples of error message for Cognito.
The code I’m using:
class Cognito
attr_reader :client,
:user_pool_id,
:app_client_id,
:app_client_secret
def initialize
@client = Aws::CognitoIdentityProvider::Client.new(
region: ENV['AWS_REGION'],
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
)
@user_pool_id = ENV['AWS_USER_POOL_ID']
@app_client_id = ENV["AWS_APP_CLIENT_ID"]
@app_client_secret = ENV["AWS_APP_CLIENT_SECRET_KEY"]
end
class << self
def secret_hash(username)
cognito = self.new
Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', cognito.app_client_secret, username + cognito.app_client_id))
end
def authenticate(username:, password:)
cognito = self.new
user_object = {
USERNAME: username,
PASSWORD: password,
SECRET_HASH: Cognito.secret_hash(username),
}
auth_object = {
user_pool_id: cognito.user_pool_id,
client_id: cognito.app_client_id,
auth_flow: "ADMIN_NO_SRP_AUTH",
auth_parameters: user_object,
}
cognito.client.admin_initiate_auth(auth_object)
end
def admin_respond_to_auth_challenge(session:, mfa_code:, username:)
cognito = self.new
cognito.client.admin_respond_to_auth_challenge({
user_pool_id: cognito.user_pool_id,
client_id: cognito.app_client_id,
challenge_name: "SMS_MFA", # required, accepts SMS_MFA, SOFTWARE_TOKEN_MFA, SELECT_MFA_TYPE, MFA_SETUP, PASSWORD_VERIFIER, CUSTOM_CHALLENGE, DEVICE_SRP_AUTH, DEVICE_PASSWORD_VERIFIER, ADMIN_NO_SRP_AUTH, NEW_PASSWORD_REQUIRED
challenge_responses: {
"SMS_MFA_CODE" => mfa_code,
"USERNAME" => username,
"SECRET_HASH" => Cognito.secret_hash(username),
},
session: session,
context_data: {
# TODO get these from request.
ip_address: "127.0.0.1", # required
server_name: "localhost", # required
server_path: "https://127.0.0.1/", # required
http_headers: [ # required
{
header_name: "StringType",
header_value: "StringType",
},
],
},
})
end
def confirm_device(device_key:, access_token:, device_name: nil)
cognito = self.new
cognito.client.confirm_device({
device_key: device_key,
access_token: access_token,
device_name: device_name,
})
end
end
end
And called with:
r = Cognito.authenticate(username: '[email protected]', password: "Password1")
challenge = Cognito.admin_respond_to_auth_challenge(session: r.session, mfa_code: "123456", username: '[email protected]')
confirm = Cognito.confirm_device(device_key: challenge.authentication_result.new_device_metadata.device_key, access_token: challenge.authentication_result.access_token, device_name: "John's Machine")
With the full error being:
/Users/myname/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/aws-sdk-core-3.126.0/lib/seahorse/client/plugins/raise_response_errors.rb:17:in `call': Invalid device credentials given, no credentials given (Aws::CognitoIdentityProvider::Errors::InvalidParameterException)
I’m not sure what credentials I’m missing. Any help would be appreciated. Thank you.
[ad_2]