The authenticationScheme parameter was not specified, and DefaultChallengeScheme was not detected with default authentication and user authorization

I have a net core 2.0 application and an authorization problem. I want to use custom authorization using special request.header and standard default authentication. First, I add the configuration to 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 the wrong request.header in AuthTokenPolicy, I see this. But in the logs I see an error:

System.InvalidOperationException: no authenticationScheme specification specified, and DefaultChallengeScheme. \ R \ n was not found in Microsoft.AspNetCore.Authentication.AuthenticationService.d__11.MoveNext () \ r \ n --- End of stack trace from previous where exception was thrown - - \ r \ n in System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (task task) \ r \ n in Microsoft.AspNetCore.Mvc.ChallengeRult .MoveNext () \ r \ n --- The end of the stack trace from the previous place where the exception was thrown - \ r \ n in System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n in System.Runtime.CompilerServices. TaskAwaiter.HandleNonSuccessAndDebuggerNotification (task task) \ r \ n in Microsoft.AspNetCore.Mv c.Internal.ResourceInvoker.d__19.MoveNext () \ r \ n --- The end of the stack trace from the previous place where the exception was thrown --- \ r \ n in System.Runtime.ExceptionServices.ExceptionDispatc hInfo.Throw () \ r \ n in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (task task) \ r \ n in Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext () \ r \ n --- End stack trace from previous place where the exception was thrown - \ r \ n in System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task of the task) \ r \ n in Microsoft.AspNetCore. .Internal.ResourceInvoker.d__15.MoveNext () \ r \ n --- The end of the stack trace from the previous place where I selected ix - \ r \ n in System.Runtime.ExceptionServices. ExceptionDispatchInfo.Throw () \ r \ n in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (task task) \ r \ n in Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext () \ r \ n --- End the stack from the previous place where the exception was thrown - \ r \ n in System.Runtime.ExceptionServices.ExceptionDispatchInfo.Thr ow () \ r \ n in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (task task) \ r \ n in Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.d__3.MoveNext () \ r \ n --- The end of the stack trace from the previous location where the exception was thrown --- \ r \ n in System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task of the task) \ r \ n with reagent .AspNet.BabelFileMiddleware.d__5.MoveNext () \ r \ n --- The end of the stack trace from the previous place where the exception was thrown - \ r \ n in System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (task task) \ r \ n in Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext () \ r \ n --- The end of the stack trace from the previous place where the exception was thrown - where the exception was thrown - \ r \ n in System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () \ r \ n in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (task task) \ r \ n on core.common.Middleware.LoggingMiddle .MoveNext () in D: \ Dev \ microservicePDP \ Template \ core.common \ Middleware \ LoggingMiddleware.cs: line 72

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

Quote from the article:

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

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

In ConfigureServices, I added AuthenticationScheme and DefaultChallengeScheme. It did not help, same error here. I tried using app.UseAuthentication (); there are no results in Configure in StartUp.cs. Can someone explain how to use custom authentication without authentication?

+27
source share
5 answers

Okay The correct answer: do not use authorization instead of authentication. I have to get full access to the service of all clients with a headline. Work code:

 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 { ...} 

Now I can not find TokenAuthenticationOptions, but it was empty. I found the same PhoneNumberAuthenticationOptions class:

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

You should define a static class SchemesNamesConst Something like:

 namespace Common.Const{ public static class SchemesNamesConst { public const string TokenAuthenticationDefaultScheme = "TokenAuthenticationScheme"; }} 
+15
source

it worked for me

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

When I used the policy before I installed the default authentication scheme in it too. I changed the DefaultPolicy so it was a little different. However, the same should work for adding policies.

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

Note that by default, the AuthenticationSchemes property uses a read-only list. I think it would be better to implement this instead of a list.

+4
source

Your initial statement in the noted decision is not entirely true. Although your new solution may achieve your original goal, it is still possible to get around the original error by retaining the AuthorizationHandler logic - provided that you have handlers for the basic authentication scheme, even if they are functionally skeletons.

Generally speaking, the handlers and authentication schemes are designed to establish + identity verification, which makes them necessary for the work of authorization handlers / policies, since they work on the assumption that the identity is already established.

ASP.NET Dev Haok summarizes this best here: "Authentication today does not know about authorization at all, it only cares about creating a ClaimsPrincipal for each scheme. Authorization should be somewhat aware of authentication, so AuthenticationSchemes in a policy is a mechanism for you to associate a policy with the schemes used to build an efficient application principal for authorization (or it just uses the default httpContext.User for a request that relies on DefaultAuthenticateScheme). " https://github.com/aspnet/Security/issues/1469

In my case, the solution I'm working on provided my own implicit identity concept, so we didn't need authentication schemes / handlers - just header markers for authorization. Thus, until our concepts of identity change, our header token authorization handlers that apply policies can be bound to the skeletons of scheme 1 to 1.

Endpoint Tags:

 [Authorize(AuthenticationSchemes = "AuthenticatedUserSchemeName", Policy = "AuthorizedUserPolicyName")] 

Startup.cs:

  services.AddAuthentication(options => { options.DefaultAuthenticateScheme = "AuthenticatedUserSchemeName"; }).AddScheme<ValidTokenAuthenticationSchemeOptions, ValidTokenAuthenticationHandler>("AuthenticatedUserSchemeName", _ => { }); services.AddAuthorization(options => { options.AddPolicy("AuthorizedUserPolicyName", policy => { //policy.RequireClaim(ClaimTypes.Sid,"authToken"); policy.AddAuthenticationSchemes("AuthenticatedUserSchemeName"); policy.AddRequirements(new ValidTokenAuthorizationRequirement()); }); services.AddSingleton<IAuthorizationHandler, ValidTokenAuthorizationHandler>(); 

Both the empty authentication handler and the authorization handler are called (similar to the setting for the corresponding OP messages), but the authorization handler still enforces our authorization policies.

+1
source

If you do this in Visual Studio with the main Asp.Net project, and suddenly your application does not start with the error message described below, the β€œEnable browser link” canceled for me

uncheck this box

error:

 Conversion> [13:31:10 ERR] Connection id "0HLJ153E20LDJ", Request id "0HLJ153E20LDJ:00000003": An unhandled exception was thrown by the application. Conversion> System.ObjectDisposedException: The response has been aborted due to an unhandled application exception. ---> System.FormatException: Invalid ETag name 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.<ExecuteWithFilter>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> --- End of inner exception stack trace --- 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.<<CreateResponseHandler>b__0>d.MoveNext() Conversion> --- End of stack trace from previous location where exception was thrown --- 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) 
0
source

Source: https://habr.com/ru/post/1273420/


All Articles