-
Notifications
You must be signed in to change notification settings - Fork 67
Options 2.0 changes (named/validation/caching) for Auth 2.0 #161
Comments
@divega Looks like you might get that |
@HaoK cool 😄 |
Looks like we will need to have more advanced cache capabilities with eviction to support multi-tenancy, we should be able to leverage the memory cache. |
@divega updated the PR adding support for named options to After refactoring the code a bit, the options monitor now inherits from OptionsManager and adds on the reload/change notification stuff, and CurrentValue is just an alias for Value (maybe we should take this opportunity to revisit the montior API? |
Desired Auth 2.0 usage pattern: // Validation registered in DI as part services.AddGoogleAuthentication(), and triggered whenever IOptions.Value is created
services.ValidateAll<GoogleOptions>(o => o.Validate()); // Validate throws on errors
services.Validate<GoogleOptions>("Name1", o => o.Validate()); // Named validation target
// RemoteAuth validation
public override void Validate()
{
base.Validate();
if (CallbackPath == null || !CallbackPath.HasValue)
{
throw new ArgumentException(Resources.FormatException_OptionMustBeProvided(nameof(CallbackPath)), nameof(CallbackPath));
}
}
// OAuth validation
public override void Validate()
{
base.Validate();
if (string.IsNullOrEmpty(ClientId))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(ClientId)), nameof(ClientId));
}
if (string.IsNullOrEmpty(ClientSecret))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(ClientSecret)), nameof(ClientSecret));
}
if (string.IsNullOrEmpty(AuthorizationEndpoint))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(AuthorizationEndpoint)), nameof(AuthorizationEndpoint));
}
if (string.IsNullOrEmpty(TokenEndpoint))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(TokenEndpoint)), nameof(TokenEndpoint));
}
if (!CallbackPath.HasValue)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(CallbackPath)), nameof(CallbackPath));
}
// Alternatives to Validate throwing: Validate could return a List<Exception>
// Configuration of all instances
services.ConfigureAll<GoogleOptions>(o => o.SignInScheme = "whatever");
// Configure only name1 instance
services.Configure<GoogleOptions>("Name1", o => o.ClientId = "abcd");
public class GoogleHandler {
public GoogleHandler(IOptions<GoogleOptions> options) { OptionsAccessor = options; }
public virtual Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) {
Options = OptionsAccessor.GetNamed(scheme); // Also validates the scheme at this point
}
} |
At the Auth 2.0 meeting with @Tratcher @Eilon @DamianEdwards @ajcvickers we decided to go ahead and add named options support back to Options since its required functionality for Auth 2.0. This will evolve from the prototype in: aspnet/Security#1144 Basic current shape is: services.Configure<TOption>("name"); // configure single named instance
services.ConfigureAll<TOption>() // configure all instances regardless of name
services.Validate<TOption>("name"); // validation for a single named instance
services.ValidateAll<TOption>() // validates all instances
IOptionsFactory.Get<TOption>("name"); // which will trigger the appropriate Configure and Validates This should be fully backwards compatable with no effect on existing IOptions, we can choose to preserve the current unnamed option as a special Default value (null name?) in the Factory. We can also consider switching to Async Configures at this point which would better enable DbContext driven configuration. |
Initial changes added via bf76cdb to unblock Auth. |
Good to see that named options is becoming a thing. Do you have an estimated timeframe for shipping 2.0? We are considering using this in Orleans: dotnet/orleans#2936 |
@jdom you can see a rough roadmap here: https://github.com/aspnet/Home/wiki/Roadmap
|
See if there's a way to reintroduce named options in a nicer way, such that we can consume it the same way today via IOptions/ISnapshotOptions.Value, where a new
IOptionsNameSelector
service would be the customization point where name(aka tenant) can be selected.High level usage:
The options implementations would use the
IOptionsNameSelector
andNamedInstance
to return the appropriate options instanceHopefully we can do this simply by enhancing the existing implementations of the current interfaces... But its possible we might need to introduce
INamedOptions<MyOptions>
.This would dovetail nicely with the auth changes that could take advantage of this feature via named auth scheme options
cc @divega @glennc
The text was updated successfully, but these errors were encountered: