1
votes

I am trying to utilize AWS Cognito User Pools in my cross platform Xamarin app. I correctly begin registration for the user in the user pool (The user shows up in the user pool and the email with the verification code is sent). I can't seem to figure out the correct way to verify the users email to confirm them in the user pool. I keep getting NotAuthorizedException.

--------EDIT: The code blocks below have been updated to my latest attempts--------

Code for registering user:

public async Task<Exception> RegisterUserInUserPool(String sUsername, String sPassword, String sEmail)
    {

        AmazonCognitoIdentityProviderClient oClient = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), Amazon.RegionEndpoint.USEast2);
        CognitoUserPool oUserPool = new CognitoUserPool(sUserPoolID, sClientID, oClient);

        try
        {
            await oUserPool.SignUpAsync(sUsername, sPassword, new Dictionary<string, string> { { "email", sEmail } }, null);
            return null;
        }
        catch (Exception e)
        {
            return e;
        }
    }

My latest attempt at verifying the user:

public async Task<Exception> VerifyEmail(String sUsername, String sVerificationCode)
    {

        CognitoAWSCredentials oCreds = new CognitoAWSCredentials(sIdentityPoolID, Amazon.RegionEndpoint.USEast2);
        AmazonCognitoIdentityProviderClient oClient = new AmazonCognitoIdentityProviderClient(oCreds, Amazon.RegionEndpoint.USEast2);
        CognitoUserPool oUserPool = new CognitoUserPool(sUserPoolID, sClientID, oClient);
        CognitoUser oCognitoUser = new CognitoUser(sUsername, sClientID, oUserPool, oClient);

        try
        {
            await oCognitoUser.ConfirmSignUpAsync(sVerificationCode, false);
            return null;
        }
        catch (Exception e)
        {
            return e;
        }
    }

EDIT: The updated code above for confirming user verification is returning a NotAuthorizedException exception that says "Unauthenticated access is not supported for this identity pool."
What are the correct settings for the user pool to allow this kind of confirmation? Is my code missing any steps?

Any help or clarification is appreciated!

4

4 Answers

1
votes

CognitoIdentityServiceProvider SDK:

Use the confirmRegistration() or adminconfirmSignUp() functions.

Example Code

1
votes

I am using the following code and it works well

AmazonCognitoIdentityProviderClient providerClient = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), AWSSettings.AWS_REGION);
ConfirmSignUpRequest confirmRequest = new ConfirmSignUpRequest()
{
    Username = username,
    ClientId = AWSSettings.AWS_CLIENT_ID, //use your own client id
    ConfirmationCode = code
};
return await providerClient.ConfirmSignUpAsync(confirmRequest);

Also, the AWS Cognito client app should not have the secretId and ADMIN_NO_SRP_AUTH should not be marked.

1
votes

Thanks to everyone who took the time to answer. A combination of things led me to working code. I want to post the code that works for me as well as a few tips that I could've used. Hopefully it can help someone!

Register the user in the user pool:

public async Task<Exception> RegisterUserInUserPool(String sUsername, String sPassword, String sEmail)
    {

        AmazonCognitoIdentityProviderClient oClient = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), Amazon.RegionEndpoint.USEast2);
        CognitoUserPool oUserPool = new CognitoUserPool(sUserPoolID, sClientID, oClient);

        try
        {
            await oUserPool.SignUpAsync(sUsername, sPassword, new Dictionary<string, string> { { "email", sEmail } }, null);
            return null;
        }
        catch (Exception e)
        {
            return e;
        }
    }

Confirm the user's email:

public async Task<Exception> VerifyEmail(String sUsername, String sVerificationCode)
    {

        AmazonCognitoIdentityProviderClient oClient = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), Amazon.RegionEndpoint.USEast2);
        CognitoUserPool oUserPool = new CognitoUserPool(sUserPoolID, sClientID, oClient);
        CognitoUser oCognitoUser = new CognitoUser(sUsername, sClientID, oUserPool, oClient);

        try
        {
            await oCognitoUser.ConfirmSignUpAsync(sVerificationCode, false);
            return null;
        }
        catch (Exception e)
        {
            return e;
        }
    }

A few tips:

  • Know the difference between AWS user pools and identity pools.
  • Check the spam folder for the verification code. (seems simple, but this had me going for a while)
  • The .NET AWS docs are useful for some things. (A little lacking overall in my opinion)
  • The next step to authenticate users and allow them to access AWS resources is to call StartWithSrpAuthAsync on the CognitoUser model.
  • Keep in mind this is all utilizing the AWSSDK.Extensions.CognitoAuthentication Nuget package.
0
votes

I just wanted to add extra info, as this is the first stackoverflow option from google, for anyone struggling with cognito email verification.

If you are registering a user but NOT getting email verification links, check that you have set up an email forwarder.

On the Cognito User Pool Page goto:

App Integration > Domain Name: Enter a domain prefix here to allow verification emails to be sent.

This is the code that I have used to register a user and send a confirmation link.

    public async Task<SignUpResponse> SignupUserAsync(CognitoUser user)
    {
        var region = "eu-west-2";
        var provider = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(),
            RegionEndpoint.GetBySystemName(region));

        var signupRequest = new SignUpRequest
        {
            ClientId = _clientId,
            Username = user.Email,
            Password = user.Password
        };
        AttributeType emailAttribute = new AttributeType
        {
            Name = "email",
            Value = user.Email
        };
        signupRequest.UserAttributes.Add(emailAttribute);
        var newUser = provider.SignUpAsync(signupRequest);
        return await newUser;
    }

CognitoUser is a custom class that inherits from IdentityUser, found on a tutorial, I just copied it.

public class CognitoUser : IdentityUser
{
    public string Password { get; set; }
    public UserStatusType Status { get; set; }
}

Onto the next problem which I am sure isn't too far in the future. Aha

Hope it helps!