/* * 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 Amazon.Extensions.CognitoAuthentication; using Microsoft.AspNetCore.Identity; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Amazon.AspNetCore.Identity.Cognito { public class CognitoPasswordValidator : IPasswordValidator<CognitoUser> { // This is the list of what is considered to be a special characters by Cognito // See: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-policies.html private static readonly char[] CognitoSymbols = { '^', '$', '*', '.', '[', ']', '{', '}', '(', ')', '?', '-', '"', '!', '@', '#', '%', '&', '/', '\\', ',', '>', '<', '\'', ':', ';', '|', '_', '~', '`' }; /// <summary> /// Validates a password based on a Cognito user pool password policy as an asynchronous operation. /// </summary> /// <param name="manager">The <see cref="UserManager{CognitoUser}"/> to retrieve the <paramref name="user"/> properties from.</param> /// <param name="user">The user whose password should be validated.</param> /// <param name="password">The password supplied for validation</param> /// <returns>The task object representing the asynchronous operation, containing the <see cref="IdentityResult"/> /// of the operation. public async Task<IdentityResult> ValidateAsync(UserManager<CognitoUser> manager, CognitoUser user, string password) { // Retrieve the password policy set by the user's user pool var passwordPolicy = await user.UserPool.GetPasswordPolicyTypeAsync().ConfigureAwait(false); var errorDescriber = new IdentityErrorDescriber(); var errors = new List<IdentityError>(); if (password.Length < passwordPolicy.MinimumLength) { errors.Add(errorDescriber.PasswordTooShort(passwordPolicy.MinimumLength)); } if (!password.Any(char.IsLower) && passwordPolicy.RequireLowercase) { errors.Add(errorDescriber.PasswordRequiresLower()); } if (!password.Any(char.IsUpper) && passwordPolicy.RequireUppercase) { errors.Add(errorDescriber.PasswordRequiresUpper()); } if (!password.Any(char.IsNumber) && passwordPolicy.RequireNumbers) { errors.Add(errorDescriber.PasswordRequiresDigit()); } var passwordContainsASymbol = password.IndexOfAny(CognitoSymbols) >= 0; if (!passwordContainsASymbol && passwordPolicy.RequireSymbols) { errors.Add(errorDescriber.PasswordRequiresNonAlphanumeric()); } if (errors.Count > 0) { return IdentityResult.Failed(errors.ToArray()); } else { return IdentityResult.Success; } } } }