aws / aws-sdk-net-extensions-cognito

An extension library to assist in the Amazon Cognito User Pools authentication process
Apache License 2.0
102 stars 49 forks source link

Awaiting UpdateAttributesAsync() throws a NullReferenceException #47

Closed PorkWings closed 3 years ago

PorkWings commented 4 years ago

As the title implies, awaiting the UpdateAttributesAsync method causes a NRE to be thrown.

I am able to successfully update attributes when the method is not awaited, but this has the drawbacks of not knowing whether the the update was successful, and the inability to catch any real errors during the update process.

For testing, I am using this method after successful login, passing in the authenticated CognitoUser:

public async Task UpdateAttributes(CognitoUser user)
        {
            try
            {
                Dictionary<string, string> userAttributes = new Dictionary<string, string>();
                userAttributes.Add("custom:custom_attribute_name", "0");

                await user.UpdateAttributesAsync(userAttributes);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
ashishdhingra commented 3 years ago

Reproducible using the following code:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.CognitoIdentityProvider;
using Amazon.Extensions.CognitoAuthentication;
using Amazon.Runtime;

namespace CognitoTest
{
    class Program
    {
        private static string clientId = "** Client ID**";
        private static string poolId = "** Pool ID **";
        private static string userName = "** User Name **";
        private static string userPassword = "** User Password **";

        static void Main(string[] args)
        {
            TestUserAuth().GetAwaiter().GetResult();
        }

        static async Task TestUserAuth()
        {
            var provider = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), FallbackRegionFactory.GetRegionEndpoint());
            var userPool = new CognitoUserPool(poolId, clientId, provider);
            var user = new CognitoUser(userName, clientId, userPool, provider);
            string accessToken = null;

            AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest()
            {
                Password = userPassword
            }).ConfigureAwait(false);

            while (authResponse.AuthenticationResult == null)
            {
                if (authResponse.ChallengeName == ChallengeNameType.NEW_PASSWORD_REQUIRED)
                {
                    Console.WriteLine("Enter your desired new password:");
                    string newPassword = Console.ReadLine();

                    authResponse = await user.RespondToNewPasswordRequiredAsync(new RespondToNewPasswordRequiredRequest()
                    {
                        SessionID = authResponse.SessionID,
                        NewPassword = newPassword
                    });
                    accessToken = authResponse.AuthenticationResult.AccessToken;
                }
                else if (authResponse.ChallengeName == ChallengeNameType.SMS_MFA)
                {
                    Console.WriteLine("Enter the MFA Code sent to your device:");
                    string mfaCode = Console.ReadLine();

                    AuthFlowResponse mfaResponse = await user.RespondToSmsMfaAuthAsync(new RespondToSmsMfaRequest()
                    {
                        SessionID = authResponse.SessionID,
                        MfaCode = mfaCode

                    }).ConfigureAwait(false);
                    accessToken = authResponse.AuthenticationResult.AccessToken;
                }
                else
                {
                    Console.WriteLine("Unrecognized authentication challenge.");
                    accessToken = "";
                    break;
                }
            }

            if (authResponse.AuthenticationResult != null)
            {
                Console.WriteLine("User successfully authenticated.");
            }
            else
            {
                Console.WriteLine("Error in authentication process.");
            }

            await UpdateAttributes(user);
        }

        public async static Task UpdateAttributes(CognitoUser user)
        {
            try
            {
                Dictionary<string, string> userAttributes = new Dictionary<string, string>();
                userAttributes.Add("custom:testattribute", "0");

                await user.UpdateAttributesAsync(userAttributes);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
    }
}

It works fine if user.UpdateAttributesAsync(userAttributes) is not awaited.

ashishdhingra commented 3 years ago

Hi @PorkWings,

This appears to be fixed in Amazon.Extensions.CognitoAuthentication 2.0.3. I tested using the above code which I shared and it works fine using version 2.0.3 of this package.

Please verify. Feel free to open a new issue in case this does not work for you.

Thanks, Ashish

github-actions[bot] commented 3 years ago

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.