Creating your Own Authentication Scheme Provider
Enabling a new authentication scheme to be loaded dynamically requires the following steps:
-
Registering the
IAuthenticationHandler
toAuthenticationSchemeOptions
mapping -
Registering any required JSON serializers for storing
AuthenticationSchemeOptions
(optional)
Adding Cookies as a Dynamic Authentication Scheme
Using ASP.NET Core's cookie authentication as an example, you can add your own dynamic authentication provider by first adding all required dependencies (in this case ISystemClock
and IPostConfigureOptions<CookieAuthenticationOptions>
), and then adding a mapping between the handler type and the options type. Knowledge of these types are required by the internal ASP.NET Core authentication libraries.
services.AddAuthenticationCore();
services.TryAddSingleton<ISystemClock, SystemClock>();
services.TryAddEnumerable(ServiceDescriptor.Singleton<
IPostConfigureOptions<CookieAuthenticationOptions>,
PostConfigureCookieAuthenticationOptions>());
services.AddDynamicProviders(options =>
{
// ... Existing config ...
// Custom authentiation provider
options.HandlerMap.Add(typeof(CookieAuthenticationHandler), typeof(CookieAuthenticationOptions));
// Optional custom JSON serialization
options.SerializerSettings.Converters.Add(new CookieOptionsConverter());
})
Optionally, you can also add your own mappings for the authentication options, allowing you customize how you store options for that authentication type.
Adding a JSON parser for custom provider
public class CookieAuthenticationOptionsConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => typeof(CookieAuthenticationOptions) == objectType;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var optionsLite = new CookieAuthenticationOptionsLite(value as CookieAuthenticationOptions);
serializer.Serialize(writer, optionsLite);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var optionsLite = serializer.Deserialize<CookieAuthenticationOptionsLite>(reader);
return optionsLite.ToOptions();
}
}
public class CookieAuthenticationOptionsLite : AuthenticationSchemeOptionsLite
{
public CookieAuthenticationOptionsLite() { }
public CookieAuthenticationOptionsLite(CookieAuthenticationOptions options) : base(options)
{
SlidingExpiration = options.SlidingExpiration;
LoginPath = options.LoginPath;
LogoutPath = options.LogoutPath;
AccessDeniedPath = options.AccessDeniedPath;
ReturnUrlParameter = options.ReturnUrlParameter;
ExpireTimeSpan = options.ExpireTimeSpan;
}
public bool? SlidingExpiration { get; set; }
public PathString? LoginPath { get; set; }
public PathString? LogoutPath { get; set; }
public PathString? AccessDeniedPath { get; set; }
public string ReturnUrlParameter { get; set; }
public TimeSpan? ExpireTimeSpan { get; set; }
public CookieAuthenticationOptions ToOptions()
{
var options = new CookieAuthenticationOptions();
base.ToOptions(options);
options.SlidingExpiration = SlidingExpiration ?? options.SlidingExpiration;
options.LoginPath = LoginPath ?? options.LoginPath;
options.LogoutPath = LogoutPath ?? options.LogoutPath;
options.AccessDeniedPath = AccessDeniedPath ?? options.AccessDeniedPath;
options.ReturnUrlParameter = ReturnUrlParameter ?? options.ReturnUrlParameter;
options.ExpireTimeSpan = ExpireTimeSpan ?? options.ExpireTimeSpan;
return options;
}
}
JSON ready implementations of AuthenticationSchemeOptions
and RemoteAuthenticationOptions
are ready in the form of AuthenticationSchemeOptionsLite
and RemoteAuthenticationOptionsLite
respectively.