No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization

匿名 (未验证) 提交于 2019-12-03 08:36:05

问题:

I have a net core 2.0 app and a problem with authorization. I want to use custom authorization with special request.header and standart default authentication. First, I add configuration in startup.cs :

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

and AuthTokenPolicy.cs

public class AuthTokenPolicy : AuthorizationHandler<TokenAuthRequirement> {        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;     } } 

and in HomeController.cs

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

If I use wrong request.header in AuthTokenPolicy I see it. But in logs I see Error :

System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found.\r\n at Microsoft.AspNetCore.Authentication.AuthenticationService.d__11.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\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--- End of stack trace from previous location where exception was thrown ---\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--- End of stack trace from previous location where exception was thrown ---\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--- End of stack trace from previous location where exception was thrown ---\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--- End of stack trace from previous location where exception was thrown ---\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--- End of stack trace from previous location where exception was thrown ---\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--- End of stack trace from previous location where exception was thrown ---\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--- End of stack trace from previous location where exception was thrown ---\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--- End of stack trace from previous location where exception was thrown ---\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

After reading Migrating Authentication and Identity to ASP.NET Core 2.0 I've added this code in startup.cs

Quotation from the article :

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

Define a default scheme in 2.0 if one of the following conditions is true: You want the user to be automatically signed in You use the [Authorize] attribute or authorization policies without specifying schemes

I added AuthenticationScheme and DefaultChallengeScheme in ConfigureServices. It wasn't help, the same error here. I've tryed used app.UseAuthentication(); in Configure in StartUp.cs, no results. Can somebody explain how to use custom authorization without authentication ?

回答1:

Okey. The correct answer is: do not use authorization instead of authentification. I should get hole access to service all clients with header. The working code is :

public class TokenAuthenticationHandler : AuthenticationHandler<TokenAuthenticationOptions>  {     public IServiceProvider ServiceProvider { get; set; }      public TokenAuthenticationHandler (IOptionsMonitor<TokenAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IServiceProvider serviceProvider)          : base (options, logger, encoder, clock)      {         ServiceProvider = serviceProvider;     }      protected override Task<AuthenticateResult> HandleAuthenticateAsync ()      {         var headers = Request.Headers;         var token = "X-Auth-Token".GetHeaderOrCookieValue (Request);          if (string.IsNullOrEmpty (token)) {             return Task.FromResult (AuthenticateResult.Fail ("Token is null"));         }                     bool isValidToken = false; // check token here          if (!isValidToken) {             return Task.FromResult (AuthenticateResult.Fail ($"Balancer not authorize token : for token={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<TokenAuthenticationOptions, TokenAuthenticationHandler> (SchemesNamesConst.TokenAuthenticationDefaultScheme, o => { }); #endregion 

And mycontroller.cs

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


回答2:

When I used policy before I set the default authentication scheme into it as well. I had modified the DefaultPolicy so it was slightly different. However the same should work for add policy as well.

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

Do take into consideration that by Default AuthenticationSchemes property uses a read only list. I think it would be better to implement that instead of List as well.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!