aws / aws-aspnet-cognito-identity-provider

ASP.NET Core Identity Provider for Amazon Cognito
https://aws.amazon.com/developer/language/net/
Apache License 2.0
213 stars 89 forks source link

Unable to retrieve UserPoolClientId and UserPoolClientSecret form AWS Parameter Store #209

Closed IgorPietraszko closed 2 years ago

IgorPietraszko commented 2 years ago

Description

I am running ASP.NET Core .NET 3.1 Lambdas which use Cognito. Everything works fine if the UserPoolClientId and UserPoolClientSecret (along with UserPoolId) are in Lambda's Environment Variables (prefixed with AWS -> e.g. AWSUserPoolClientId). But I can't get it to work when I put these (the same way or without AWS__ prefix) into the AWS Parameter Store. Note that other configuration parameters are retrieved fine form the parameter store - the only problem is Cognito configuration.

Reproduction Steps

Have a .NET 3.1 Lambda consuming Cognito (using the he ASP.NET Core Identity Provider for Amazon Cognito (Amazon.Extensions.CognitoAuthentication v2.2.2)). Put the PoolId, ClientId and ClientSecret into AWS Parameter Store.

Logs

[Error] Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware: [UnhandledException]: An unhandled exception has occurred while executing the request. Amazon.AspNetCore.Identity.Cognito.Exceptions.CognitoConfigurationException: The UserPoolClientId key/value pair is missing or empty in the IConfiguration instance at Microsoft.Extensions.Configuration.ConfigurationExtensions.GetConfigurationValue(IConfiguration section, String configurationKey, Boolean isOptional) at Microsoft.Extensions.Configuration.ConfigurationExtensions.GetAWSCognitoClientOptions(IConfiguration config, String configSection) at Microsoft.Extensions.Configuration.ConfigurationExtensions.GetAWSCognitoClientOptions(IConfiguration config) at Microsoft.Extensions.DependencyInjection.CognitoUserPoolFactory.CreateUserPoolClient(IServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>cDisplayClass1_0.b__0(ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType) at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired) at lambda_method(Closure , IServiceProvider , Object[] ) at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>cDisplayClass4_0.b0(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>cDisplayClass5_0.gCreateController|0(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.gAwaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.gLogged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Amazon.XRay.Recorder.Handlers.AspNetCore.Internal.AWSXRayMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.gAwaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)

Environment

Resolution


This is a :bug: bug-report

IgorPietraszko commented 2 years ago

As soon as I put these back into Environment variables (while keeping those and others in Parameter Store), the problem goes away. I also updated Cognito NuGet to 3.0.0 - same issue.

ashishdhingra commented 2 years ago

Hi @IgorPietraszko,

Good morning.

As mentioned in the Readme, the environment variable configuration values are automatically read using the feature provided using through IConfiguration's environment variable support. The article Externalizing Configurations to AWS SSM Parameter Store and using in ASP.NET Core API provides good guidance on how to use AWS SSM Parameter Store with ASP.NET Core applications (kindly note that it makes use of Amazon.Extensions.Configuration.SystemsManager package).

For testing, using the Sample app in this repository,

namespace Samples { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            }).ConfigureAppConfiguration((builder) =>
            {
                builder.AddSystemsManager("/myparams", new AWSOptions
                {
                    Region = RegionEndpoint.USEast2
                });
            });
}

}


- Commented the AWS section in `appsettings.Development.json`.
- Debugged the code.

**RESULT:** Cognito configuration values were successfully read from AWS Systems Manager Parameter Store:

<img width="1235" alt="Screen Shot 2022-01-18 at 10 08 40 AM" src="https://user-images.githubusercontent.com/67916761/149994147-47c44874-c9c0-4351-bec8-111f79292032.png">

Kindly note that as mentioned at https://github.com/aws/aws-dotnet-extensions-configuration#parameter-store, the AWS credentials used must have access to `appconfig:GetConfiguration` service operation. 

Hope this helps.

Thanks,
Ashish
github-actions[bot] commented 2 years ago

This issue has not received a response in 5 days. If you want to keep this issue open, please just leave a comment below and auto-close will be canceled.

IgorPietraszko commented 2 years ago

Sorry for not responding on time. You are correct, putting the parameters in as /myapplication/AWS/myparameter as opposed to AWS_ fixed the problem. Thanks.