Closed RyanWarwick closed 1 year ago
Any update on this? We are waiting on this for a feature.
Can anybody describe in simple terms how this flow is supposed to work and debugging steps for the maths?
I've been struggling for weeks looking for a working version of device auth for python, but even if it worked in .net I could potentially port it. The problem is that the docs are extremely unclear, even following https://aws.amazon.com/premiumsupport/knowledge-center/cognito-user-pool-remembered-devices/ explicitly always results in an incorrect username or password issue.
From what we've been able to establish, the DEVICE_SRP_AUTH flow in .net either isn't implemented or is undocumented. We reliably get 1 of 2 outcomes:
On the former, we confirm the device using the below:
DeviceSecretVerifierConfigType d = user.GenerateDeviceVerifier(vDeviceGroupKey, "A-RANDOM-PASSWORD", vDeviceKey)
ConfirmDeviceResponse r = await user.ConfirmDeviceAsync(vAccessToken, vDeviceKey, "deviceName", d.PasswordVerifier, d.Salt)
On a subsequent sign-in, we then do this:
CognitoDevice device = new CognitoDevice(new Amazon.CognitoIdentityProvider.Model.DeviceType()
{
DeviceKey = "eu-west-1_2a0ce014-ef11-4209-bae1-69efba93490f"
}, user);
user.Device = device;
AuthFlowResponse context = await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest()
{
Password = password,
DeviceGroupKey = "GROUP-KEY-OBTAINED-FROM-INITIAL-SIGN-IN",
DevicePass = "PASSWORD-SET-WHEN-GENERATING-DEVICE-VERIFIER",
}).ConfigureAwait(false);
The response to the above, is NotAuthorizedException. If you leave out specifying DeviceGroupKey and DevicePass, you get a DEVICE_SRP_AUTH challenge but unlike NEW_PASSWORD_REQUIRED, MFA & Custom responses, there is no handler.
We've probably got to the point that we'll go our own route for managing devices which is a shame but we're losing the will to live with this!!
HI @mads195
After bashing my head against it for far too long, reading all the code examples from both Amplify js and other sdks, I gave up. It seems this simply does not work or there is misinformation in the docs, or a combination of the two.
I was also able to get the DEVICE_SRP_AUTH challenge and then subsequent password verification challenge which always returned Not Authorized, no matter what combination of device key, username, passwords, etc I tried.
At this point, short of raising an AWS support ticket I have to assume the functionality is broken in the cognito service. The JavaScript SDK amplify seems 'closest' to what is required, but JS doesn't support client_secret either (rightly) so with zero working examples and next to no docs, I don't see a way forward until I hear from AWS.
Thanks for following up, appreciate that I'm not the only one stuck here :)
Hi everyone,
Sorry for the delay in the response, but we're investigating this issue again.
I've tried to reproduce the error using the latest version of this library (https://www.nuget.org/packages/Amazon.Extensions.CognitoAuthentication/2.2.2) and the following code, but it's returning a valid access token (I haven't seen the NotAuthorizedException
happen yet).
record UserAuthResult(string RefreshToken, string DeviceGroupKey, string DeviceKey);
var result = await AuthenticateUserWithSrp();
await AuthenticateDeviceWithSrp(result);
async Task<UserAuthResult> AuthenticateUserWithSrp()
{
using var provider = new AmazonCognitoIdentityProviderClient();
var userPool = new CognitoUserPool(POOL_ID, CLIENT_ID, provider);
var user = new CognitoUser(USER_NAME, CLIENT_ID, userPool, provider, CLIENT_SECRET);
var authResponse = await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest
{
Password = USER_PWD
});
while (authResponse.AuthenticationResult is null)
{
if (authResponse.ChallengeName == ChallengeNameType.NEW_PASSWORD_REQUIRED)
{
Console.WriteLine("Enter your desired new password:");
var newPassword = Console.ReadLine();
authResponse = await user.RespondToNewPasswordRequiredAsync(new RespondToNewPasswordRequiredRequest
{
SessionID = authResponse.SessionID,
NewPassword = newPassword
});
}
else if (authResponse.ChallengeName == ChallengeNameType.SMS_MFA)
{
Console.WriteLine("Enter the MFA Code sent to your device:");
var mfaCode = Console.ReadLine();
authResponse = await user.RespondToSmsMfaAuthAsync(new RespondToSmsMfaRequest
{
SessionID = authResponse.SessionID,
MfaCode = mfaCode
});
}
else
{
Console.WriteLine("Unrecognized authentication challenge.");
break;
}
}
var accessToken = authResponse.AuthenticationResult.AccessToken;
var deviceKey = authResponse.AuthenticationResult.NewDeviceMetadata.DeviceKey;
var deviceGroupKey = authResponse.AuthenticationResult.NewDeviceMetadata.DeviceGroupKey;
var deviceVerifier = user.GenerateDeviceVerifier(deviceGroupKey, DEVICE_PWD, USER_NAME);
await user.ConfirmDeviceAsync(accessToken, deviceKey, DEVICE_NAME, deviceVerifier.PasswordVerifier, deviceVerifier.Salt);
return new UserAuthResult(authResponse.AuthenticationResult.RefreshToken, deviceGroupKey, deviceKey);
}
async Task AuthenticateDeviceWithSrp(UserAuthResult result)
{
using var provider = new AmazonCognitoIdentityProviderClient();
var userPool = new CognitoUserPool(POOL_ID, CLIENT_ID, provider);
var user = new CognitoUser(USER_NAME, CLIENT_ID, userPool, provider, CLIENT_SECRET);
user.Device = new CognitoDevice(new DeviceType { DeviceKey = result.DeviceKey }, user);
var authResponse = await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest
{
Password = USER_PWD,
DeviceGroupKey = result.DeviceGroupKey,
DevicePass = DEVICE_PWD,
});
Console.WriteLine(authResponse.AuthenticationResult.AccessToken);
}
Can you help me figure out what I'm missing here? Not sure if it matters, but this is the configuration for my test user pool:
This issue has not received a response in 5 days. If you want to keep this issue open, please just leave a comment below and auto-close will be canceled.
@dscpinheiro in my case, for cognito settings I have remember devices as opt-in and trust remembered devices to suppress MFA as "Yes"
The DEVICE_PASSWORD_VERIFIER
flow is not working despite me re-creating the same signatureString (verified via many log statements, hardcoding bigA, littleA, timestamp, etc.) as here: https://github.com/aws-amplify/amplify-js/blob/master/packages/amazon-cognito-identity-js/src/CognitoUser.js#L718
Also, I tried the steps here: https://aws.amazon.com/premiumsupport/knowledge-center/cognito-user-pool-remembered-devices/
The formula for the PASSWORD_CLAIM_SIGNATURE
seems wildly inaccurate and does not match any AWS open source code anywhere online. It also returns a generic invalid password error like others have mentioned.
It seems like responding to DEVICE_PASSWORD_VERIFIER
is not functional
Even this python example does not seem to work if you have MFA turned on: https://docs.aws.amazon.com/code-library/latest/ug/cognito-identity-provider_example_cognito-identity-provider_InitiateAuth_section.html
You get the following error:
botocore.errorfactory.NotAuthorizedException: An error occurred (NotAuthorizedException) when calling the RespondToAuthChallenge operation: Incorrect username or password
Description
Using v2.2.1 of aws-sdk-net-extensions-cognito and attempting to auth using remembered device results in NotAuthorizedException: Incorrect username or password error, at DEVICE_PASSWORD_VERIFIER code segment in CognitoUserAuthentication.cs
Reproduction Steps
CognitoDevice device = new CognitoDevice(new Amazon.CognitoIdentityProvider.Model.DeviceType() { DeviceKey = deviceKey }, user); user.Device = device; InitiateSrpAuthRequest authRequest = new InitiateSrpAuthRequest() { Password = password, DeviceGroupKey =deviceGroupKey, DevicePass = devicePass, }; AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(authRequest).ConfigureAwait(false);
which internally calls GetDeviceAuthenticationKey() in AuthenticationHelper.AuthenticateDevice()
Environment
Resolution
Correct syntax example :![DeviceAuthIssue1](https://user-images.githubusercontent.com/29495850/118352944-c6cd5780-b596-11eb-9ae0-9a82a89d0444.PNG)