Ainsi, après une longue journée à essayer de résoudre ce problème, j'ai enfin compris comment Microsoft veut que nous créions des gestionnaires d'authentification personnalisés pour leur nouvelle configuration de middleware unique dans le noyau 2.0.
Après avoir parcouru une partie de la documentation sur MSDN, j'ai trouvé une classe appelée AuthenticationHandler<TOption>
qui implémente l' IAuthenticationHandler
interface.
À partir de là, j'ai trouvé une base de code entière avec les schémas d'authentification existants situés à https://github.com/aspnet/Security
À l'intérieur de l'un d'entre eux, il montre comment Microsoft implémente le schéma d'authentification JwtBearer. ( https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer )
J'ai copié la plupart de ce code dans un nouveau dossier et effacé tout ce qui s'y rapporte JwtBearer
.
Dans la JwtBearerHandler
classe (qui s'étend AuthenticationHandler<>
), il y a un remplacement pourTask<AuthenticateResult> HandleAuthenticateAsync()
J'ai ajouté notre ancien middleware pour la configuration des revendications via un serveur de jetons personnalisé, et je rencontrais toujours des problèmes avec les autorisations, crachant simplement un 200 OK
au lieu d'un 401 Unauthorized
lorsqu'un jeton était invalide et qu'aucune revendication n'était configurée.
J'ai réalisé que j'avais remplacé Task HandleChallengeAsync(AuthenticationProperties properties)
ce qui, pour une raison quelconque, est utilisé pour définir les autorisations via [Authorize(Roles="")]
un contrôleur.
Après avoir supprimé ce remplacement, le code avait fonctionné et avait réussi à lancer un 401
lorsque les autorisations ne correspondaient pas.
Le principal à retenir est que vous ne pouvez plus utiliser d'intergiciel personnalisé, vous devez l'implémenter via AuthenticationHandler<>
et vous devez définir le DefaultAuthenticateScheme
et DefaultChallengeScheme
lors de l'utilisation services.AddAuthentication(...)
.
Voici un exemple de ce à quoi tout cela devrait ressembler:
Dans Startup.cs / ConfigureServices (), ajoutez:
services.AddAuthentication(options =>
{
// the scheme name has to match the value we're going to use in AuthenticationBuilder.AddScheme(...)
options.DefaultAuthenticateScheme = "Custom Scheme";
options.DefaultChallengeScheme = "Custom Scheme";
})
.AddCustomAuth(o => { });
Dans Startup.cs / Configure (), ajoutez:
app.UseAuthentication();
Créer un nouveau fichier CustomAuthExtensions.cs
public static class CustomAuthExtensions
{
public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthOptions> configureOptions)
{
return builder.AddScheme<CustomAuthOptions, CustomAuthHandler>("Custom Scheme", "Custom Auth", configureOptions);
}
}
Créer un nouveau fichier CustomAuthOptions.cs
public class CustomAuthOptions: AuthenticationSchemeOptions
{
public CustomAuthOptions()
{
}
}
Créer un nouveau fichier CustomAuthHandler.cs
internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions>
{
public CustomAuthHandler(IOptionsMonitor<CustomAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
// store custom services here...
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
// build the claims and put them in "Context"; you need to import the Microsoft.AspNetCore.Authentication package
return AuthenticateResult.NoResult();
}
}