/* * 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.AspNetCore.Identity.Cognito; using Amazon.AspNetCore.Identity.Cognito.Exceptions; using Amazon.AspNetCore.Identity.Cognito.Extensions; using Amazon.CognitoIdentityProvider; using Amazon.Extensions.CognitoAuthentication; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Configuration; using System; using System.Linq; using System.Reflection; namespace Microsoft.Extensions.DependencyInjection { public static class CognitoServiceCollectionExtensions { public static IServiceCollection AddCognitoIdentity(this IServiceCollection services, Action identityOptions = null, string prefix = null) { services.InjectCognitoUser(identityOptions); services.TryAddAWSService(); services.TryAddCognitoUserPool(); return services; } private static IServiceCollection InjectCognitoUser(this IServiceCollection services, Action identityOptions = null) where TUser : CognitoUser { if (identityOptions != null) { services.Configure(identityOptions); services.AddIdentity() .AddDefaultTokenProviders() .AddPasswordValidator(); } else { services.AddIdentity() .AddDefaultTokenProviders() .AddPasswordValidator(); var passwordValidators = services.Where(s => s.ServiceType.Equals(typeof(IPasswordValidator))); foreach (var validator in passwordValidators.ToArray()) { if (Equals(validator.ImplementationType, typeof(PasswordValidator))) { services.Remove(validator); } } } // Overrides the managers/stores with Cognito specific ones. services.AddScoped, CognitoUserManager>(); services.AddScoped, CognitoSignInManager>(); services.AddScoped, CognitoUserStore>(); services.AddScoped, CognitoRoleStore>(); services.AddScoped, CognitoUserStore>(); services.AddScoped, CognitoUserClaimsPrincipalFactory>(); services.AddSingleton(); services.AddSingleton(); services.AddHttpContextAccessor(); return services; } private static IServiceCollection TryAddCognitoUserPool(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Singleton) { if (!services.Any(x => x.ServiceType == typeof(CognitoUserPool))) { Func factory = CognitoUserPoolFactory.CreateUserPoolClient; var descriptor = new ServiceDescriptor(typeof(CognitoUserPool), factory, lifetime); services.Add(descriptor); } return services; } } internal static class CognitoUserPoolFactory { private const string MissingConfigurationExceptionMessage = "No IConfiguration object instance was found in the service collection. Could not instanciate a CognitoUserPool object."; private const string UserAgentHeader = "User-Agent"; private static string _assemblyFileVersion = "Unknown"; public static CognitoUserPool CreateUserPoolClient(IServiceProvider provider) { // Checks if AWSCognitoClientOptions are already set up var options = provider.GetService(); if (options == null) { var configuration = provider.GetService(); if (configuration != null) { options = configuration.GetAWSCognitoClientOptions(); } else { throw new CognitoConfigurationException(MissingConfigurationExceptionMessage); } } _assemblyFileVersion = GetAssemblyFileVersion(); var cognitoClient = provider.GetService(); if (cognitoClient is AmazonCognitoIdentityProviderClient eventProvider) { eventProvider.BeforeRequestEvent += ServiceClientBeforeRequestEvent; } var cognitoPool = new CognitoUserPool(options.UserPoolId, options.UserPoolClientId, cognitoClient, options.UserPoolClientSecret); return cognitoPool; } private static void ServiceClientBeforeRequestEvent(object sender, Amazon.Runtime.RequestEventArgs e) { Amazon.Runtime.WebServiceRequestEventArgs args = e as Amazon.Runtime.WebServiceRequestEventArgs; if (args == null || !args.Headers.ContainsKey(UserAgentHeader)) return; args.Headers[UserAgentHeader] = args.Headers[UserAgentHeader] + " CognitoASPNETCoreIdentityProvider/" + _assemblyFileVersion; } private static string GetAssemblyFileVersion() { var assembly = typeof(CognitoServiceCollectionExtensions).GetTypeInfo().Assembly; AssemblyFileVersionAttribute attribute = assembly.GetCustomAttribute(typeof(AssemblyFileVersionAttribute)) as AssemblyFileVersionAttribute; return attribute == null ? "Unknown" : attribute.Version; } } }