/*
* 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);
}
}
}