73 votes

Aucun authenticationScheme n'a été spécifié et aucun DefaultChallengeScheme avec authentification par défaut et autorisation personnalisée n'a été trouvé.

J'ai une application .NET Core 2.0 et j'ai un problème d'authentification. Je veux utiliser une autorisation personnalisée avec des requêtes spéciales. En-tête et authentification standard par défaut. Tout d'abord, j'ajoute la configuration dans Startup.cs:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddAuthorization(options =>
    {
        options.AddPolicy(DefaultAuthorizedPolicy, policy =>
        {
            policy.Requirements.Add(new TokenAuthRequirement());
        });
    });
    services.AddSingleton();
    // ...
}

AuthTokenPolicy.cs:

public class AuthTokenPolicy : AuthorizationHandler
{   
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TokenAuthRequirement requirement)
    {
        var filterContext = context.Resource as AuthorizationFilterContext;
        var response = filterContext.HttpContext.Response;
        try
        {
            // some validation code

            var isValidToken = isValidTokenTask.Result;
            if (!isValidToken)
            {
                response.StatusCode = 401;
                return Task.CompletedTask;
            }

            response.StatusCode = 200;
            context.Succeed(requirement);
        }
        catch (Exception)
        {
            return Task.CompletedTask;
        }
        return Task.CompletedTask;
    }
}

et dans HomeController.cs:

[Authorize(Policy = Startup.DefaultAuthorizedPolicy)]
public async Task IsVisible()

Si j'utilise le mauvais request.header dans AuthTokenPolicy je le vois, mais dans les journaux je vois cette erreur :

System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found.\r\n at Microsoft.AspNetCore.Authentication.AuthenticationService.d__11.MoveNext()\r\n--- Fin de la trace de la pile à l'emplacement précédent où l'exception a été levée ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.ChallengeResult.d__14.MoveNext()\r\n--- Fin de la trace de la pile à l'emplacement précédent où l'exception a été levée ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__19.MoveNext()\r\n--- Fin de la trace de la pile à l'emplacement précédent où l'exception a été levée ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()\r\n--- Fin de la trace de la pile à l'emplacement précédent où l'exception a été levée ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext()\r\n--- Fin de la trace de la pile à l'emplacement précédent où l'exception a été levée ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()\r\n--- Fin de la trace de la pile à l'emplacement précédent où l'exception a été levée ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.d__3.MoveNext()\r\n--- Fin de la trace de la pile à l'emplacement précédent où l'exception a été levée ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at React.AspNet.BabelFileMiddleware.d__5.MoveNext()\r\n--- Fin de la trace de la pile à l'emplacement précédent où l'exception a été levée ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()\r\n--- Fin de la trace de la pile à l'emplacement précédent où l'exception a été levée ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at core.common.Middleware.LoggingMiddleware.d__3.MoveNext() in D:\Dev\microservicePDP\Template\core.common\Middleware\LoggingMiddleware.cs:line 72

Après avoir lu Migration de l'authentification et de l'identité vers ASP.NET Core 2.0 j'ai ajouté ce code dans startup.cs

Citation de l'article :

services.AddAuthentication(options => 
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});

Définissez un schéma par défaut en 2.0 si l'une des conditions suivantes est vraie : Vous voulez que l'utilisateur soit automatiquement connecté Vous utilisez l'attribut [Authorize] ou des stratégies d'autorisation sans spécifier de schémas

J'ai ajouté AuthenticationScheme et DefaultChallengeScheme dans ConfigureServices(). Cela n'a pas aidé, la même erreur ici. J'ai essayé d'utiliser app.UseAuthentication(); dans la méthode Startup.Configure(), sans résultat.

Comment puis-je utiliser une autorisation personnalisée sans authentification ?

1 votes

Donc après avoir utilisé AddAuthentication, avez-vous à nouveau utilisé [Authorize(Policy = Startup.DefaultAuthorizedPolicy)] ?

0 votes

Oui. N'est-ce pas juste?

0 votes

Je confirmais simplement ce que vous aviez écrit. Je suppose que DefaultChallengeScheme est défini uniquement pour la stratégie d'autorisation par défaut... dans tous les cas, essayez ma réponse

39voto

Galina Points 420

Ne pas utiliser d'autorisation à la place de l'authentification. Je devrais obtenir un accès complet au service pour tous les clients avec l'en-tête. Le code fonctionnel est :

public class TokenAuthenticationHandler : AuthenticationHandler 
{
    public IServiceProvider ServiceProvider { get; set; }

    public TokenAuthenticationHandler (IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IServiceProvider serviceProvider) 
        : base (options, logger, encoder, clock) 
    {
        ServiceProvider = serviceProvider;
    }

    protected override Task HandleAuthenticateAsync () 
    {
        var headers = Request.Headers;
        var token = "X-Auth-Token".GetHeaderOrCookieValue (Request);

        if (string.IsNullOrEmpty (token)) {
            return Task.FromResult (AuthenticateResult.Fail ("Le jeton est nul"));
        }           

        bool isValidToken = false; // vérifier le jeton ici

        if (!isValidToken) {
            return Task.FromResult (AuthenticateResult.Fail ($"L'équilibreur n'autorise pas le jeton : pour le jeton={token}"));
        }

        var claims = new [] { new Claim ("token", token) };
        var identity = new ClaimsIdentity (claims, nameof (TokenAuthenticationHandler));
        var ticket = new AuthenticationTicket (new ClaimsPrincipal (identity), this.Scheme.Name);
        return Task.FromResult (AuthenticateResult.Success (ticket));
    }
}

Startup.cs :

#region Authentication
services.AddAuthentication (o => {
    o.DefaultScheme = SchemesNamesConst.TokenAuthenticationDefaultScheme;
})
.AddScheme (SchemesNamesConst.TokenAuthenticationDefaultScheme, o => { });
#endregion

Et moncontroller.cs

[Authorize(AuthenticationSchemes = SchemesNamesConst.TokenAuthenticationDefaultScheme)]
public class MainController : BaseController
{ ... }

Je ne trouve pas maintenant TokenAuthenticationOptions, mais il était vide. J'ai trouvé la même classe PhoneNumberAuthenticationOptions :

public class PhoneNumberAuthenticationOptions : AuthenticationSchemeOptions
{
    public Regex PhoneMask { get; set; }// = new Regex("7\\d{10}");
}

Vous devriez définir une classe statique SchemesNamesConst. Quelque chose comme:

public static class SchemesNamesConst
{
    public const string TokenAuthenticationDefaultScheme = "TokenAuthenticationScheme";
}

4 votes

Où se trouve la classe TokenAuthenticationOptions ? L'avez-vous définie vous-même ou provient-elle d'une bibliothèque ?

0 votes

Bonjour. Je ne peux pas trouver TokenAuthenticationOptions maintenant, mais il était vide. J'ai trouvé la même classe PhoneNumberAuthenticationOptions et l'ai ajoutée au premier commentaire.

1 votes

Où est défini SchemesNamesConst?

37voto

ali zarei Points 469

Cela a fonctionné pour moi

// using Microsoft.AspNetCore.Authentication.Cookies;
// using Microsoft.AspNetCore.Http;

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
        options =>
        {
            options.LoginPath = new PathString("/auth/login");
            options.AccessDeniedPath = new PathString("/auth/denied");
        });

0 votes

Oui, celui-ci est la solution la plus simple.

4voto

Neville Nazerane Points 2328

Lorsque j'ai utilisé la politique avant, j'ai également défini le schéma d'authentification par défaut. J'avais modifié la DefaultPolicy donc c'était légèrement différent. Cependant, cela devrait fonctionner de la même manière pour ajouter une politique également.

services.AddAuthorization(options =>
{
    options.AddPolicy(DefaultAuthorizedPolicy, policy =>
    {
        policy.Requirements.Add(new TokenAuthRequirement());
        policy.AuthenticationSchemes = new List()
        {
            CookieAuthenticationDefaults.AuthenticationScheme
        }
    });
});

Prenez en compte qu'en général, la propriété AuthenticationSchemes utilise une liste en lecture seule. Je pense qu'il serait préférable de l'implémenter plutôt avec ReadOnlyList.

0 votes

Juste essayé, l'exception est difficile : "Aucun gestionnaire d'authentification n'est configuré pour authentifier par le schéma : Cookies". Je préfère ne pas écrire d'authentification par cookie personnalisée et ne peux rien trouver d'utile pour la nouvelle exception.

3 votes

Oui. vous devez ajouter des cookies AddAuthentication().AddCookie()

0 votes

Bonjour. J'ai ajouté AddAuthentication().AddCookie() et policy.AuthenticationSchemes et ensuite j'ai un statut 200 Ok avec le bon jeton et 404 avec le mauvais jeton. J'ai débogué le code et vu status=401 dans la méthode TokenAuthPolicy.HandleRequirementAsync mais le client a reçu 404. Avez-vous une idée où Net Core change le statut de 401 à 404 ?

3voto

Dagan Danevic Points 1

Votre déclaration initiale dans la solution marquée n'est pas entièrement vraie. Bien que votre nouvelle solution puisse atteindre votre objectif initial, il est encore possible de contourner l'erreur initiale tout en préservant votre logique AuthorizationHandler--à condition que vous ayez des gestionnaires de schémas d'authentification de base en place, même s'ils sont fonctionnellement des squelettes.

De manière générale, les gestionnaires et schémas d'authentification sont destinés à établir et valider l'identité, ce qui les rend nécessaires pour que les gestionnaires/politiques d'autorisation fonctionnent--car ils supposent qu'une identité a déjà été établie.

ASP.NET Dev Haok résume cela le mieux ici : "Aujourd'hui, l'authentification n'est pas du tout consciente de l'autorisation, elle se contente de produire un ClaimsPrincipal par schéma. L'autorisation doit être quelque peu consciente de l'authentification, donc les AuthenticationSchemes dans la politique sont un mécanisme pour associer la politique aux schémas utilisés pour construire le ClaimsPrincipal effectif pour l'autorisation (ou il utilise simplement DefaultAuthenticateScheme dans httpContext.User pour la demande, qui repose sur DefaultAuthenticateScheme)." https://github.com/aspnet/Security/issues/1469

Dans mon cas, la solution sur laquelle je travaille fournissait sa propre concept implicite d'identité, donc nous n'avions pas besoin de schémas/gestionnaires d'authentification--juste des jetons d'en-tête pour l'autorisation. Donc, jusqu'à ce que nos concepts d'identité changent, nos gestionnaires d'autorisation de jetons d'en-tête qui appliquent les politiques peuvent être liés à des squelettes de schéma 1-à-1.

Tags sur les points de terminaison :

[Authorize(AuthenticationSchemes = "NomDuSchémaUtilisateurAuthentifié", Policy = "NomDePolitiqueUtilisateurAutorisé")]

Startup.cs :

services.AddAuthentication(options =>
{
  options.DefaultAuthenticateScheme = "NomDuSchémaUtilisateurAuthentifié";
}).AddScheme("NomDuSchémaUtilisateurAuthentifié", _ => { });

services.AddAuthorization(options =>
{
  options.AddPolicy("NomDePolitiqueUtilisateurAutorisé", policy =>
  {
    //policy.RequireClaim(ClaimTypes.Sid,"authToken");
    policy.AddAuthenticationSchemes("NomDuSchémaUtilisateurAuthentifié");
    policy.AddRequirements(new ValidTokenAuthorizationRequirement());
  });
  services.AddSingleton();

Le gestionnaire d'authentification vide et le gestionnaire d'autorisation sont appelés (similaire à la configuration des publications respectives de l'OP), mais le gestionnaire d'autorisation fait toujours respecter nos politiques d'autorisation.

0 votes

Où puis-je obtenir cela ? ValidTokenAuthenticationSchemeOptions, ValidTokenAuthenticationHandler, ValidTokenAuthorizationRequirement ? Ce n'est pas partie de Microsoft.AspNetCore.Authorization et je n'ai pas pu trouver facilement sur Google.

0voto

Si vous faites cela sur Visual Studio avec un projet Asp.Net core, et que soudainement votre application ne démarre pas avec le type de message d'erreur indiqué ci-dessous, ce qui a fonctionné pour moi était de décocher "Activer le lien du navigateur"

décocher cette option

erreur :

Conversion> [13:31:10 ERR] Identifiant de connexion "0HLJ153E20LDJ", identifiant de requête "0HLJ153E20LDJ:00000003" : Une exception non gérée a été levée par l'application.
Conversion> System.ObjectDisposedException: La réponse a été annulée en raison d'une exception d'application non gérée. ---> System.FormatException: Nom de ETag invalide
Conversion>    at Microsoft.Net.Http.Headers.EntityTagHeaderValue..ctor(StringSegment tag, Boolean isWeak)
Conversion>    at Microsoft.Net.Http.Headers.EntityTagHeaderValue..ctor(StringSegment tag)
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleWareUtil.AddToETag(ResponseHeaders responseHeader, Int32 port)
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleware.<>c__DisplayClass7_0.b__0()
Conversion>    at Microsoft.AspNetCore.Http.HttpResponse.<>c.<.cctor>b__30_0(Object callback)
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.FireOnStartingMayAwait(Stack`1 onStarting)
Conversion>    --- Fin de la trace de la pile de l'exception interne ---
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAbortedException()
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.InitializeResponseAsync(Int32 firstWriteByteCount)
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.WriteAsync(ReadOnlyMemory`1 data, CancellationToken cancellationToken)
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
Conversion>    at System.IO.Stream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count)
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.ScriptInjectionFilterStream.<>c__DisplayClass37_0.<b__0>d.MoveNext()
Conversion> --- Fin de la trace de la pile de l'exception provenant de l'emplacement précédent où l'exception a été levée ---
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.SocketReader.ReadBytesIntoResponseHandler(Int64 totalBytesToRead, ResponseHandler handler, CancellationToken cancellationToken)
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.HttpSocketAdapter.ResponseReader.ReadBytesIntoResponse(Int64 bytesToRead)
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.HttpSocketAdapter.ResponseReader.ReadChunkedContent()
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.HttpSocketAdapter.ResponseReader.ReadResponse()
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.DelayConnectingHttpSocketAdapter.Microsoft.VisualStudio.Web.BrowserLink.IHttpSocketAdapter.WaitForResponseComplete()
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.ScriptInjectionFilterStream.WaitForFilterComplete()
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleware.ExecuteWithFilter(IHttpSocketAdapter injectScriptSocket, String requestId, HttpContext httpContext)
Conversion>    at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Conversion>    at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Conversion>    at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext)
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X