IdentityServer / IdentityServer4.AccessTokenValidation

IdentityServer Access Token Validation for ASP.NET Core
Apache License 2.0
544 stars 214 forks source link

IConfigureOptions<IdentityServerAuthenticationOptions>.Configure() isn't automatically called. #114

Closed Poltergeisen closed 5 years ago

Poltergeisen commented 5 years ago

I accidentally created this issue in the wrong repo: https://github.com/IdentityServer/IdentityServer4/issues/3081

Issue

Create a class that implements IConfigureOptions<IdentityServerAuthenticationOptions>

Add to dependency injection: services.AddSingleton<IConfigureOptions<IdentityServerAuthenticationOptions>, ConfigureIdentityServerAuthenticationOptions>();

The Configure method is never called when using services.AddAuthentication().AddIdentityServerAuthentication()

I needed to access my configuration variables from a settings class. I'd like to keep the configuration settings separate from the startup class.

I'll include an example below

This is the IOptions pattern that Microsoft is pushing with .net core I think.

Example (pseudo code):

Settings.cs

public class Settings{
  public string ClientSecretEncrypted {get; set;}
  public string Environment {get; set;}
  public bool IsLocal => Environment.ToUpper() == "LOCAL"
}
services.Configure<Settings>(options => 
{
  options.ClientSecretEncrypted = Configuration["IdentityServer:ClientSecret"];
  options.Environment = Configuration["Environment"];
});

Then if that all worked correctly I'd make a configuration class for Identity server that implements IConfigureOptions that could automatically configure what I want:

    public class
        ConfigureIdentityServerAuthenticationOptions :
            IConfigureOptions<IdentityServerAuthenticationOptions>
    {
        private readonly IOptions<Settings> options;

        public ConfigureIdentityServerAuthenticationOptions(
            IOptions<Settings> options)
        {
            this.options = options;
        }

        public void Configure(IdentityServerAuthenticationOptions identityServerAuthenticationOptions)
        {
            ...
            identityServerAuthenticationOptions.RequireHttpsMetadata = !options.Value.IsLocal;
            identityServerAuthenticationOptions.ApiName = "name";
            identityServerAuthenticationOptions.ApiSecret = clientSecretDecrypted;
            identityServerAuthenticationOptions.Authority = options.Value.IdentityServerAuthority;
        }
    }
brockallen commented 5 years ago

We don't use the IOptions framework.

Oh sorry -- your initial comment about the wrong repo confused me and I thought this was being asked in the IS repo. Ignore my comment above :)

leastprivilege commented 5 years ago

We don't do anything special. So this should work.

Poltergeisen commented 5 years ago

Do you think that it isn't working because this library is using an AuthenticationBuilder instead of IServiceCollection?

I set this up successfully with swashbuckle so it seems that the pattern should work, but they are using IServiceCollection.

leastprivilege commented 5 years ago

We are using the standard pattern for authentication handlers.

Poltergeisen commented 5 years ago

I think I mistakenly thought that the options could be configured similar to services. If you know of a way for me to still use IConfigureOptions interface when configuring identity server I would love to hear it.

Otherwise if you think that isn't possible I think you can close this ticket. It doesn't seem to be an issue in this library, rather it seems that it is an issue in my own implementation or lack of understanding of the .net core options pattern.

stevendarby commented 5 years ago

@Poltergeisen Try implementing IConfigureNamedOptions instead - you will need to implement another Configure method that takes a name.

Now pass a name into AddAuthentication in your startup. Typically you would use IdentityServerAuthenticationDefaults.AuthenticationScheme (“Bearer”)

You can still add your class to dependency injection as IConfigureOptions

I was doing a similar thing to you, except I was already day passing the name in, and my IConfigureOptions.Configure method wasn’t being called until I implemented IConfigureNamedOptions instead. Good luck!

DominusFlevit commented 5 years ago

@snappyfoo Can you post a code example? I cannot get this to work either.

UPDATE No example needed, I got it. The class has to implement both interfaces