/// <summary>
        /// Interal method which creates the InitiateAuthRequest for an SRP authentication flow
        /// </summary>
        /// <param name="tupleAa">Tuple containing the A,a pair for SRP authentication</param>
        /// <returns>Returns the InitiateAuthRequest for an SRP authentication flow</returns>
        private InitiateAuthRequest CreateSrpAuthRequest(Tuple <BigInteger, BigInteger> tupleAa)
        {
            InitiateAuthRequest initiateAuthRequest = new InitiateAuthRequest()
            {
                AuthFlow       = AuthFlowType.USER_SRP_AUTH,
                ClientId       = ClientID,
                AuthParameters = new Dictionary <string, string>(StringComparer.Ordinal)
                {
                    { CognitoConstants.ChlgParamUsername, Username },
                    { CognitoConstants.ChlgParamSrpA, tupleAa.Item1.ToString("X") }
                }
            };

            if (!string.IsNullOrEmpty(ClientSecret))
            {
                initiateAuthRequest.AuthParameters.Add(CognitoConstants.ChlgParamSecretHash,
                                                       CognitoAuthHelper.GetUserPoolSecretHash(Username, ClientID, ClientSecret));
            }

            if (Device != null && !string.IsNullOrEmpty(Device.DeviceKey))
            {
                initiateAuthRequest.AuthParameters.Add(CognitoConstants.ChlgParamDeviceKey, Device.DeviceKey);
            }

            return(initiateAuthRequest);
        }
示例#2
0
        public void TestHkdfVector2()
        {
            // Expected Values
            byte[] prkFromSpec = CognitoAuthHelper.StringToByteArray("06a6b88c5853361a06104c9ceb35b45cef760014904671" +
                                                                     "014a193f40c15fc244");
            byte[] okmFromSpec = CognitoAuthHelper.StringToByteArray("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efa" +
                                                                     "d8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71c" +
                                                                     "c30c58179ec3e87c14c01d5c1f3434f1d87");

            byte[] ikmBytes = CognitoAuthHelper.StringToByteArray("000102030405060708090a0b0c0d0e0f101112131" +
                                                                  "415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d" +
                                                                  "3e3f404142434445464748494a4b4c4d4e4f");
            byte[] saltBytes = CognitoAuthHelper.StringToByteArray("606162636465666768696a6b6c6d6e6f70717273" +
                                                                   "7475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9" +
                                                                   "d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf");
            byte[] infoBytes = CognitoAuthHelper.StringToByteArray("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3" +
                                                                   "c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebece" +
                                                                   "deeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
            int length = 82;

            HkdfSha256 hkdfSha256 = new HkdfSha256(saltBytes, ikmBytes);

            byte[] hkdfResult = hkdfSha256.Expand(infoBytes, length);

            Assert.Equal(prkFromSpec, hkdfSha256.Prk);
            Assert.Equal(okmFromSpec, hkdfResult);
        }
        /// <summary>
        /// Internal method to aid in the admin sign up flow for a new user
        /// </summary>
        /// <param name="userID">The userID of the user being created</param>
        /// <param name="userAttributes">The user attributes of the user being created</param>
        /// <param name="validationData">The validation data of the user being created</param>
        /// <returns>Returns the SignUpResponse for the sign up API request using the provided information</returns>
        private AdminCreateUserRequest CreateAdminSignUpRequest(string userID,
                                                                IDictionary <string, string> userAttributes,
                                                                IDictionary <string, string> validationData)
        {
            List <AttributeType> userAttributesList = null;

            if (userAttributes != null)
            {
                userAttributesList = CognitoAuthHelper.CreateAttributeList(userAttributes);
            }
            else
            {
                throw new ArgumentNullException(nameof(userAttributes), "userAttributes cannot be null.");
            }

            var validationDataList =
                validationData != null?CognitoAuthHelper.CreateAttributeList(validationData) : null;

            // Create User registration request
            return(new AdminCreateUserRequest()
            {
                Username = userID,
                UserPoolId = this.PoolID,
                UserAttributes = userAttributesList,
                ValidationData = validationDataList
            });
        }
        /// <summary>
        /// Performs the "Expand" portion of the Hkdf protocol to make
        /// the ouput key material of the desired length
        /// </summary>
        /// <param name="info">Contextual information for the expansion hash</param>
        /// <param name="length">The desired length of the output key material in bytes</param>
        /// <returns>Returns the output key material for the expansion protion of the HKDF protocol</returns>
        internal byte[] Expand(byte[] info, int length)
        {
            if (length > HLen * 255)
            {
                throw new ArgumentException("Length must be <= " + HLen * 255);
            }

            byte[] outputKeyMaterial = new byte[length];
            HmacSha256 = new HMACSHA256(Prk);

            byte currentByte = 1;

            byte[] hashedBlock = new byte[0];
            byte[] currentBlock;
            int    bytesRemaining = length;

            while (bytesRemaining > 0)
            {
                currentBlock = CognitoAuthHelper.CombineBytes(hashedBlock, info, new byte[] { currentByte });
                hashedBlock  = HmacSha256.ComputeHash(currentBlock);

                Buffer.BlockCopy(hashedBlock, 0, outputKeyMaterial, length - bytesRemaining, Math.Min(hashedBlock.Length, bytesRemaining));
                bytesRemaining -= hashedBlock.Length;
                currentByte++;
            }

            return(outputKeyMaterial);
        }
示例#5
0
        private UpdateUserAttributesRequest CreateUpdateUserAttributesRequest(IDictionary <string, string> attributes)
        {
            EnsureUserAuthenticated();

            UpdateUserAttributesRequest updateUserAttributesRequest = new UpdateUserAttributesRequest()
            {
                AccessToken    = SessionTokens.AccessToken,
                UserAttributes = CognitoAuthHelper.CreateAttributeList(attributes)
            };

            return(updateUserAttributesRequest);
        }
示例#6
0
        /// <summary>
        /// Creates an instance of CognitoUser
        /// </summary>
        /// <param name="userID">UserID of the specified user</param>
        /// <param name="clientID">ClientID associated with the user pool</param>
        /// <param name="pool">CognitoUserPool this user is associated with </param>
        /// <param name="provider">IAmazonCognitoIdentityProvider for the specified user pool</param>
        /// <param name="clientSecret">Client secret for the specified client, if exists</param>
        /// <param name="username">Username for user, if different from userID</param>
        public CognitoUser(string userID, string clientID,
                           CognitoUserPool pool,
                           IAmazonCognitoIdentityProvider provider,
                           string clientSecret = null,
                           string status       = null,
                           string username     = null,
                           Dictionary <string, string> attributes = null)
        {
            if (pool.PoolID.Contains("_"))
            {
                this.PoolName = pool.PoolID.Split('_')[1];
            }
            else
            {
                throw new ArgumentException("Pool's poolID malformed, should be of the form <region>_<poolname>.");
            }

            this.ClientSecret = clientSecret;
            if (!string.IsNullOrEmpty(clientSecret))
            {
                this.SecretHash = CognitoAuthHelper.GetUserPoolSecretHash(userID, clientID, clientSecret);
            }

            this.UserID   = userID;
            this.Username = userID;
            if (!string.IsNullOrEmpty(username))
            {
                this.Username = username;
            }
            else
            {
                this.Username = userID;
            }

            this.Status = status;

            this.UserPool      = pool;
            this.ClientID      = clientID;
            this.SessionTokens = null;

            if (attributes != null)
            {
                this.Attributes = attributes;
            }

            this.Provider = provider;

            if (this.Provider is AmazonCognitoIdentityProviderClient eventProvider)
            {
                eventProvider.BeforeRequestEvent += CognitoAuthHelper.ServiceClientBeforeRequestEvent;
            }
        }
        /// <summary>
        /// Internal method which responds to the PASSWORD_VERIFIER challenge in SRP authentication
        /// </summary>
        /// <param name="challenge">Response from the InitiateAuth challenge</param>
        /// <param name="password">Password for the CognitoUser, needed for authentication</param>
        /// <param name="tupleAa">Tuple of BigIntegers containing the A,a pair for the SRP protocol flow</param>
        /// <returns>Returns the RespondToAuthChallengeRequest for an SRP authentication flow</returns>
        private RespondToAuthChallengeRequest CreateSrpPasswordVerifierAuthRequest(InitiateAuthResponse challenge,
                                                                                   string password,
                                                                                   Tuple <BigInteger, BigInteger> tupleAa)
        {
            string     username    = challenge.ChallengeParameters[CognitoConstants.ChlgParamUsername];
            string     poolName    = PoolName;
            string     secretBlock = challenge.ChallengeParameters[CognitoConstants.ChlgParamSecretBlock];
            string     salt        = challenge.ChallengeParameters[CognitoConstants.ChlgParamSalt];
            BigInteger srpb        = BigIntegerExtensions.FromUnsignedLittleEndianHex(challenge.ChallengeParameters[CognitoConstants.ChlgParamSrpB]);

            if ((srpb.TrueMod(AuthenticationHelper.N)).Equals(BigInteger.Zero))
            {
                throw new ArgumentException("SRP error, B mod N cannot be zero.", "challenge");
            }

            DateTime timestamp = DateTime.UtcNow;
            string   timeStr   = timestamp.ToString("ddd MMM d HH:mm:ss \"UTC\" yyyy", CultureInfo.InvariantCulture);

            byte[] claim = AuthenticationHelper.AuthenticateUser(username, password, poolName, tupleAa, salt,
                                                                 challenge.ChallengeParameters[CognitoConstants.ChlgParamSrpB], secretBlock, timeStr);
            string claimBase64 = Convert.ToBase64String(claim);

            Dictionary <string, string> srpAuthResponses = new Dictionary <string, string>(StringComparer.Ordinal)
            {
                { CognitoConstants.ChlgParamPassSecretBlock, secretBlock },
                { CognitoConstants.ChlgParamPassSignature, claimBase64 },
                { CognitoConstants.ChlgParamUsername, username },
                { CognitoConstants.ChlgParamTimestamp, timeStr },
            };

            if (!string.IsNullOrEmpty(ClientSecret))
            {
                SecretHash = CognitoAuthHelper.GetUserPoolSecretHash(Username, ClientID, ClientSecret);
                srpAuthResponses.Add(CognitoConstants.ChlgParamSecretHash, SecretHash);
            }

            if (Device != null && !string.IsNullOrEmpty(Device.DeviceKey))
            {
                srpAuthResponses.Add(CognitoConstants.ChlgParamDeviceKey, Device.DeviceKey);
            }

            RespondToAuthChallengeRequest authChallengeRequest = new RespondToAuthChallengeRequest()
            {
                ChallengeName      = challenge.ChallengeName,
                ClientId           = ClientID,
                Session            = challenge.Session,
                ChallengeResponses = srpAuthResponses
            };

            return(authChallengeRequest);
        }
        /// <summary>
        /// Resets the <paramref name="user"/>'s password to the specified <paramref name="newPassword"/> after
        /// validating the given password reset <paramref name="token"/>.
        /// </summary>
        /// <param name="user">The user whose password should be reset.</param>
        /// <param name="token">The password reset token to verify.</param>
        /// <param name="newPassword">The new password to set if reset token verification succeeds.</param>
        /// <returns>
        /// The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/>
        /// of the operation.
        /// </returns>
        public Task ConfirmForgotPassword(string userID, string token, string newPassword, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var request = new ConfirmForgotPasswordRequest
            {
                Username         = userID,
                ClientId         = ClientID,
                ConfirmationCode = token,
                Password         = newPassword,
            };

            if (!string.IsNullOrEmpty(ClientSecret))
            {
                request.SecretHash = CognitoAuthHelper.GetUserPoolSecretHash(userID, ClientID, ClientSecret);
            }

            return(Provider.ConfirmForgotPasswordAsync(request, cancellationToken));
        }
        public void TestHkdfVector3()
        {
            // Expected Values
            var prkFromSpec = CognitoAuthHelper.StringToByteArray("19ef24a32c717b167f33a91d6f648bdf96596776afdb6" +
                                                                  "377ac434c1c293ccb04");
            var okmFromSpec = CognitoAuthHelper.StringToByteArray("8da4e775a563c18f715f802a063c5a31b8a11f5c5ee18" +
                                                                  "79ec3454e5f3c738d2d9d201395faa4b61a96c8");

            var ikmBytes  = CognitoAuthHelper.StringToByteArray("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
            var saltBytes = CognitoAuthHelper.StringToByteArray("");
            var infoBytes = CognitoAuthHelper.StringToByteArray("");
            var length    = 42;

            var hkdfSha256 = new HkdfSha256(saltBytes, ikmBytes);
            var hkdfResult = hkdfSha256.Expand(infoBytes, length);

            Assert.Equal(prkFromSpec, hkdfSha256.Prk);
            Assert.Equal(okmFromSpec, hkdfResult);
        }
        public void TestHkdfVector1()
        {
            // Expected Values
            var prkFromSepc = CognitoAuthHelper.StringToByteArray("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3" +
                                                                  "122ec844ad7c2b3e5");
            var okmFromSpec = CognitoAuthHelper.StringToByteArray("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4" +
                                                                  "c5db02d56ecc4c5bf34007208d5b887185865");

            var ikmBytes  = CognitoAuthHelper.StringToByteArray("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
            var saltBytes = CognitoAuthHelper.StringToByteArray("000102030405060708090a0b0c");
            var infoBytes = CognitoAuthHelper.StringToByteArray("f0f1f2f3f4f5f6f7f8f9");
            var length    = 42;

            var hkdfSha256 = new HkdfSha256(saltBytes, ikmBytes);
            var hkdfResult = hkdfSha256.Expand(infoBytes, length);

            Assert.Equal(prkFromSepc, hkdfSha256.Prk);
            Assert.Equal(okmFromSpec, hkdfResult);
        }
        /// <summary>
        /// Internal mehtod which updates CognitoUser's username, secret hash, and device key from challege parameters
        /// </summary>
        /// <param name="challengeParameters">Dictionary containing the key-value pairs for challenge parameters</param>
        private void UpdateUsernameAndSecretHash(IDictionary <string, string> challengeParameters)
        {
            bool canSetUsername           = string.IsNullOrEmpty(Username) || string.Equals(UserID, Username, StringComparison.Ordinal);
            bool challengeParamIsUsername = challengeParameters != null && challengeParameters.ContainsKey(CognitoConstants.ChlgParamUsername);
            bool shouldUpdate             = canSetUsername || challengeParamIsUsername;

            if (!shouldUpdate)
            {
                return;
            }

            if (challengeParameters.ContainsKey(CognitoConstants.ChlgParamUsername))
            {
                Username = challengeParameters[CognitoConstants.ChlgParamUsername];
            }

            if (!string.IsNullOrEmpty(ClientSecret))
            {
                SecretHash = CognitoAuthHelper.GetUserPoolSecretHash(Username, ClientID, ClientSecret);
            }
        }
示例#12
0
        /// <summary>
        /// Internal method which responds to the DEVICE_SRP_AUTH challenge in SRP authentication
        /// </summary>
        /// <param name="challenge">The response from the PASSWORD_VERIFIER challenge</param>
        /// <param name="tupleAa">Tuple of BigIntegers containing the A,a pair for the SRP protocol flow</param>
        /// <returns></returns>
        private RespondToAuthChallengeRequest CreateDeviceSrpAuthRequest(RespondToAuthChallengeResponse challenge, Tuple <BigInteger, BigInteger> tupleAa)
        {
            RespondToAuthChallengeRequest authChallengeRequest = new RespondToAuthChallengeRequest()
            {
                ChallengeName      = "DEVICE_SRP_AUTH",
                ClientId           = ClientID,
                Session            = challenge.Session,
                ChallengeResponses = new Dictionary <string, string>
                {
                    { CognitoConstants.ChlgParamUsername, Username },
                    { CognitoConstants.ChlgParamDeviceKey, Device.DeviceKey },
                    { CognitoConstants.ChlgParamSrpA, tupleAa.Item1.ToString("X") },
                }
            };

            if (!string.IsNullOrEmpty(ClientSecret))
            {
                SecretHash = CognitoAuthHelper.GetUserPoolSecretHash(Username, ClientID, ClientSecret);
                authChallengeRequest.ChallengeResponses.Add(CognitoConstants.ChlgParamSecretHash, SecretHash);
            }
            return(authChallengeRequest);
        }
示例#13
0
        /// <summary>
        /// Performs the "Expand" portion of the Hkdf protocol to make
        /// the ouput key material of the desired length
        /// </summary>
        /// <param name="info">Contextual information for the expansion hash</param>
        /// <param name="length">The desired length of the output key material in bytes</param>
        /// <returns>Returns the output key material for the expansion protion of the HKDF protocol</returns>
        internal byte[] Expand(byte[] info, int length)
        {
            byte[] outputKeyMaterial = new byte[length];
            HmacSha256 = new HMACSHA256(Prk);

            byte currentByte;

            byte[] hashedBlock = new byte[0];
            byte[] currentBlock;
            int    bytesRemaining = length;

            for (int i = 0; bytesRemaining > 0; i++)
            {
                currentByte  = Convert.ToByte(i + 1);
                currentBlock = CognitoAuthHelper.CombineBytes(new byte[][] { hashedBlock, info, new byte[] { currentByte } });
                hashedBlock  = HmacSha256.ComputeHash(currentBlock);

                Buffer.BlockCopy(hashedBlock, 0, outputKeyMaterial, length - bytesRemaining, Math.Min(hashedBlock.Length, bytesRemaining));
                bytesRemaining -= hashedBlock.Length;
            }

            return(outputKeyMaterial);
        }
        /// <summary>
        /// Internal method to aid in the sign up flow for a new user
        /// </summary>
        /// <param name="userID">The userID of the user being created</param>
        /// <param name="password">The password of the user being created</param>
        /// <param name="userAttributes">The user attributes of the user being created</param>
        /// <param name="validationData">The validation data of the user being created</param>
        /// <returns>Returns the SignUpResponse for the sign up API request using the provided information</returns>
        private SignUpRequest CreateSignUpRequest(string userID,
                                                  string password,
                                                  IDictionary <string, string> userAttributes,
                                                  IDictionary <string, string> validationData)
        {
            List <AttributeType> userAttributesList = null;

            if (userAttributes != null)
            {
                userAttributesList = CognitoAuthHelper.CreateAttributeList(userAttributes);
            }
            else
            {
                throw new ArgumentNullException("userAttributes", "userAttributes cannot be null.");
            }

            var validationDataList =
                validationData != null?CognitoAuthHelper.CreateAttributeList(validationData) : null;

            // Create User registration request
            var signUpUserRequest = new SignUpRequest()
            {
                Username       = userID,
                Password       = password,
                ClientId       = ClientID,
                UserAttributes = userAttributesList,
                ValidationData = validationDataList
            };

            if (!string.IsNullOrEmpty(ClientSecret))
            {
                signUpUserRequest.SecretHash = CognitoAuthHelper.GetUserPoolSecretHash(userID, ClientID, ClientSecret);
            }

            return(signUpUserRequest);
        }
示例#15
0
        public void TestSecretHash()
        {
            string hash = CognitoAuthHelper.GetUserPoolSecretHash("Mess", "age", "secret");

            Assert.Equal("qnR8UCqJggD55PohusaBNviGoOJ67HC6Btry4qXLVZc=", hash);
        }
示例#16
0
        /// <summary>
        /// Create request for DEVICE_SRP_AUTH.
        /// </summary>
        /// <param name="challenge">Current auth challange response</param>
        /// <param name="AaTuple">Use for generate request</param>
        /// <returns>DEVICE_SRP_AUTH request</returns>
        private RespondToAuthChallengeRequest CreateDeviceSrpAuthRequest(RespondToAuthChallengeResponse challenge,
                                                                         Tuple <BigInteger, BigInteger> AaTuple)
        {
            var usernameInternal = challenge.ChallengeParameters[CognitoConstants.ChlgParamUsername];

            BigInteger srpB;

            if (challenge.ChallengeParameters.TryGetValue(CognitoConstants.ChlgParamSrpB, out var srpBBytes))
            {
                srpB = BigIntegerExtensions.FromHexPositive(srpBBytes);
            }
            else
            {
                throw new Exception($"Missing {CognitoConstants.ChlgParamSrpB}");
            }

            if (srpB.TrueMod(AuthenticationHelper.N).IsZero)
            {
                throw new Exception("SRP error, B cannot be zero");
            }

            var salt = BigIntegerExtensions.FromHexPositive(challenge.ChallengeParameters[CognitoConstants.ChlgParamSalt]);
            var key  = AuthenticationHelper.GetPasswordAuthenticationKey(Device.DeviceKey, Device.DeviceSecret, Device.GroupDeviceKey, AaTuple, srpB, salt);

            string hmac;
            var    dateString = CognitoAuthHelper.UtcNow;
            {
                var hmacSha256 = new HMACSHA256(key);
                var bytes      = CognitoAuthHelper.CombineBytes(new[] {
                    Encoding.UTF8.GetBytes(Device.GroupDeviceKey),
                    Encoding.UTF8.GetBytes(Device.DeviceKey),
                    Convert.FromBase64String(challenge.ChallengeParameters[CognitoConstants.ChlgParamSecretBlock]),
                    Encoding.UTF8.GetBytes(dateString)
                });
                hmac = Convert.ToBase64String(hmacSha256.ComputeHash(bytes));
            }

            string secretHash;
            {
                var hmacSha256 = new HMACSHA256(Encoding.UTF8.GetBytes(ClientSecret));
                var hash       = hmacSha256.ComputeHash(CognitoAuthHelper.CombineBytes(new[] {
                    Encoding.UTF8.GetBytes(usernameInternal),
                    Encoding.UTF8.GetBytes(ClientID),
                }));
                secretHash = Convert.ToBase64String(hash);
            }

            var challengeResponses = new Dictionary <string, string> {
                { CognitoConstants.ChlgParamPassSecretBlock, challenge.ChallengeParameters[CognitoConstants.ChlgParamSecretBlock] },
                { CognitoConstants.ChlgParamPassSignature, hmac },
                { CognitoConstants.ChlgParamTimestamp, dateString },
                { CognitoConstants.ChlgParamUsername, usernameInternal },
                { CognitoConstants.ChlgParamDeviceKey, Device.DeviceKey },
                { CognitoConstants.ChlgParamSecretHash, secretHash }
            };

            return(new RespondToAuthChallengeRequest
            {
                ChallengeName = challenge.ChallengeName,
                ClientId = ClientID,
                Session = challenge.Session,
                ChallengeResponses = challengeResponses
            });
        }