/* * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ using System; using System.Threading.Tasks; using System.Collections.Generic; using Amazon.CognitoIdentityProvider; using Amazon.CognitoIdentityProvider.Model; using System.Linq; using Amazon.Extensions.CognitoAuthentication.Util; using System.Threading; namespace Amazon.Extensions.CognitoAuthentication { public partial class CognitoUserPool { /// /// The poolID associated with the user pool. PoolID can only be configured /// through the constructor, and once set it cannot be changed. /// public string PoolID { get; private set; } /// /// The clientID associated with the user pool. ClientID can only be configured /// through the constructor, and once set it cannot be changed. /// public string ClientID { get; private set; } /// /// The ClientConfiguration associated with the user pool and the ClientID. /// private CognitoUserPoolClientConfiguration ClientConfiguration { get; set; } internal IAmazonCognitoIdentityProvider Provider { get; set; } private string ClientSecret { get; set; } /// /// Create an instance of CognitoUserPool /// /// PoolID of the associated user pool /// ClientID for the associated user pool /// IAmazonCognitoIdentityProvider for the specified user pool /// Client secret for the corresponding clientID, if exists public CognitoUserPool(string poolID, string clientID, IAmazonCognitoIdentityProvider provider, string clientSecret = null) { if(!poolID.Contains("_")) { throw new ArgumentException("PoolID should be of the form _.", "poolID"); } this.PoolID = poolID; this.ClientID = clientID; this.ClientSecret = clientSecret; this.Provider = provider; if (this.Provider is AmazonCognitoIdentityProviderClient eventProvider) { eventProvider.BeforeRequestEvent += CognitoAuthHelper.ServiceClientBeforeRequestEvent; } } /// /// Signs up the user with the specified parameters using an asynchronous call /// /// The userID of the user being created /// The password of the user being created /// The user attributes of the user being created /// The validation data of the user being created /// Returns the delivery details for the sign up request public Task SignUpAsync(string userID, string password, IDictionary userAttributes, IDictionary validationData) { return SignUpAsync(userID, password, userAttributes, validationData, default); } /// /// Signs up the user with the specified parameters using an asynchronous call /// /// The userID of the user being created /// The password of the user being created /// The user attributes of the user being created /// The validation data of the user being created /// A cancellation token that can be used by other objects or threads to receive notice of cancellation /// Returns the delivery details for the sign up request public Task SignUpAsync(string userID, string password, IDictionary userAttributes, IDictionary validationData, CancellationToken cancellationToken) { SignUpRequest signUpUserRequest = CreateSignUpRequest(userID, password, userAttributes, validationData); return Provider.SignUpAsync(signUpUserRequest, cancellationToken); } /// /// Internal method to aid in the sign up flow for a new user /// /// The userID of the user being created /// The password of the user being created /// The user attributes of the user being created /// The validation data of the user being created /// Returns the SignUpResponse for the sign up API request using the provided information private SignUpRequest CreateSignUpRequest(string userID, string password, IDictionary userAttributes, IDictionary validationData) { List userAttributesList = null; if (userAttributes != null) { userAttributesList = CognitoAuthHelper.CreateAttributeList(userAttributes); } else { throw new ArgumentNullException("userAttributes", "userAttributes cannot be null."); } List validationDataList = validationData != null ? CognitoAuthHelper.CreateAttributeList(validationData) : null; // Create User registration request SignUpRequest 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; } /// /// Gets a CognitoUser with no userID set /// /// Returns a user with no userID set public virtual CognitoUser GetUser() { return new CognitoUser(null, ClientID, this, Provider, ClientSecret); } /// /// Gets a CognitoUser with the corresponding userID /// /// The userID of the corresponding user /// Returns a CognitoUser with the corresponding userID public virtual CognitoUser GetUser(string userID) { if (string.IsNullOrEmpty(userID)) { return GetUser(); } return new CognitoUser(userID, ClientID, this, Provider, ClientSecret); } /// /// Gets a CognitoUser with the corresponding userID, status and attributes /// /// The userID of the corresponding user /// The status of the corresponding user /// The attributes of the corresponding user /// Returns a CognitoUser with the corresponding userID public virtual CognitoUser GetUser(string userID, string status, Dictionary attributes) { if (string.IsNullOrEmpty(userID)) { return GetUser(); } return new CognitoUser(userID, ClientID, this, Provider, ClientSecret, status, userID, attributes); } /// /// Queries Cognito and returns the CognitoUser with the corresponding userID /// /// The userID of the corresponding user /// The that represents the asynchronous operation, containing a CognitoUser with the corresponding userID, with the Status and Attributes retrieved from Cognito. public virtual async Task FindByIdAsync(string userID) { return await FindByIdAsync(userID, default); } /// /// Queries Cognito and returns the CognitoUser with the corresponding userID /// /// The userID of the corresponding user /// A cancellation token that can be used by other objects or threads to receive notice of cancellation /// The that represents the asynchronous operation, containing a CognitoUser with the corresponding userID, with the Status and Attributes retrieved from Cognito. public virtual async Task FindByIdAsync(string userID, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(userID)) throw new ArgumentException(nameof(userID)); try { var response = await Provider.AdminGetUserAsync(new AdminGetUserRequest { Username = userID, UserPoolId = this.PoolID }, cancellationToken).ConfigureAwait(false); return new CognitoUser(response.Username, ClientID, this, Provider, ClientSecret, response.UserStatus.Value, response.Username, response.UserAttributes.ToDictionary(attribute => attribute.Name, attribute => attribute.Value)); } catch (UserNotFoundException) { return null; } } /// /// Queries Cognito and returns the PasswordPolicyType associated with the pool. /// /// The that represents the asynchronous operation, containing the PasswordPolicyType of the pool. public async Task GetPasswordPolicyTypeAsync() { return await GetPasswordPolicyTypeAsync(default); } /// /// Queries Cognito and returns the PasswordPolicyType associated with the pool. /// /// A cancellation token that can be used by other objects or threads to receive notice of cancellation /// The that represents the asynchronous operation, containing the PasswordPolicyType of the pool. public async Task GetPasswordPolicyTypeAsync(CancellationToken cancellationToken) { var response = await Provider.DescribeUserPoolAsync(new DescribeUserPoolRequest { UserPoolId = this.PoolID }, cancellationToken).ConfigureAwait(false); return response.UserPool.Policies.PasswordPolicy; } /// /// Queries Cognito and returns the CognitoUserPoolClientConfiguration associated with the current pool client. /// Caches the value in the ClientConfiguration private property. /// /// The that represents the asynchronous operation, containing the PasswordPolicyType of the pool. public async Task GetUserPoolClientConfiguration() { return await GetUserPoolClientConfiguration(default); } /// /// Queries Cognito and returns the CognitoUserPoolClientConfiguration associated with the current pool client. /// Caches the value in the ClientConfiguration private property. /// /// A cancellation token that can be used by other objects or threads to receive notice of cancellation /// The that represents the asynchronous operation, containing the PasswordPolicyType of the pool. public async Task GetUserPoolClientConfiguration(CancellationToken cancellationToken) { if (ClientConfiguration == null) { var response = await Provider.DescribeUserPoolClientAsync(new DescribeUserPoolClientRequest { ClientId = this.ClientID, UserPoolId = this.PoolID }, cancellationToken).ConfigureAwait(false); ClientConfiguration = new CognitoUserPoolClientConfiguration(response.UserPoolClient.ReadAttributes, response.UserPoolClient.WriteAttributes); } return ClientConfiguration; } /// /// Signs up the user with the specified parameters using an asynchronous call end triggers a temporary password sms or email message. /// /// The userID of the user being created /// The user attributes of the user being created /// The validation data of the user being created /// Returns the delivery details for the sign up request public Task AdminSignupAsync(string userID, IDictionary userAttributes, IDictionary validationData) { return AdminSignupAsync(userID, userAttributes, validationData, default); } /// /// Signs up the user with the specified parameters using an asynchronous call end triggers a temporary password sms or email message. /// /// The userID of the user being created /// The user attributes of the user being created /// The validation data of the user being created /// A cancellation token that can be used by other objects or threads to receive notice of cancellation /// Returns the delivery details for the sign up request public Task AdminSignupAsync(string userID, IDictionary userAttributes, IDictionary validationData, CancellationToken cancellationToken) { AdminCreateUserRequest signUpUserRequest = CreateAdminSignUpRequest(userID, userAttributes, validationData); return Provider.AdminCreateUserAsync(signUpUserRequest, cancellationToken); } /// /// Internal method to aid in the admin sign up flow for a new user /// /// The userID of the user being created /// The user attributes of the user being created /// The validation data of the user being created /// Returns the SignUpResponse for the sign up API request using the provided information private AdminCreateUserRequest CreateAdminSignUpRequest(string userID, IDictionary userAttributes, IDictionary validationData) { List userAttributesList = null; if (userAttributes != null) { userAttributesList = CognitoAuthHelper.CreateAttributeList(userAttributes); } else { throw new ArgumentNullException(nameof(userAttributes), "userAttributes cannot be null."); } List validationDataList = validationData != null ? CognitoAuthHelper.CreateAttributeList(validationData) : null; // Create User registration request return new AdminCreateUserRequest() { Username = userID, UserPoolId = this.PoolID, UserAttributes = userAttributesList, ValidationData = validationDataList }; } /// /// Resets the 's password to the specified after /// validating the given password reset . /// /// The user whose password should be reset. /// The password reset token to verify. /// The new password to set if reset token verification succeeds. /// /// The that represents the asynchronous operation, containing the /// of the operation. /// 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); } } }