/// <summary> /// Invokes the middleware performing authentication. /// </summary> /// <param name="context">The <see cref="HttpContext"/>.</param> public async Task Invoke(HttpContext context) { context.Features.Set <IAuthenticationFeature>(new AuthenticationFeature { OriginalPath = context.Request.Path, OriginalPathBase = context.Request.PathBase }); // Give any IAuthenticationRequestHandler schemes a chance to handle the request var handlers = context.RequestServices.GetRequiredService <IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler; if (handler != null && await handler.HandleRequestAsync()) { return; } } var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); if (defaultAuthenticate != null) { var result = await context.AuthenticateAsync(defaultAuthenticate.Name); if (result?.Principal != null) { context.User = result.Principal; } if (result?.Succeeded ?? false) { var authFeatures = new AuthenticationFeatures(result); context.Features.Set <IHttpAuthenticationFeature>(authFeatures); context.Features.Set <IAuthenticateResultFeature>(authFeatures); } } await _next(context); }
/// <summary> /// Invokes the middleware performing authorization. /// </summary> /// <param name="context">The <see cref="HttpContext"/>.</param> public async Task Invoke(HttpContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var endpoint = context.GetEndpoint(); if (endpoint != null) { // EndpointRoutingMiddleware uses this flag to check if the Authorization middleware processed auth metadata on the endpoint. // The Authorization middleware can only make this claim if it observes an actual endpoint. context.Items[AuthorizationMiddlewareInvokedWithEndpointKey] = AuthorizationMiddlewareWithEndpointInvokedValue; } // IMPORTANT: Changes to authorization logic should be mirrored in MVC's AuthorizeFilter var authorizeData = endpoint?.Metadata.GetOrderedMetadata <IAuthorizeData>() ?? Array.Empty <IAuthorizeData>(); var policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData); if (policy == null) { await _next(context); return; } // Policy evaluator has transient lifetime so it's fetched from request services instead of injecting in constructor var policyEvaluator = context.RequestServices.GetRequiredService <IPolicyEvaluator>(); var authenticateResult = await policyEvaluator.AuthenticateAsync(policy, context); if (authenticateResult?.Succeeded ?? false) { if (context.Features.Get <IAuthenticateResultFeature>() is IAuthenticateResultFeature authenticateResultFeature) { authenticateResultFeature.AuthenticateResult = authenticateResult; } else { var authFeatures = new AuthenticationFeatures(authenticateResult); context.Features.Set <IHttpAuthenticationFeature>(authFeatures); context.Features.Set <IAuthenticateResultFeature>(authFeatures); } } // Allow Anonymous still wants to run authorization to populate the User but skips any failure/challenge handling if (endpoint?.Metadata.GetMetadata <IAllowAnonymous>() != null) { await _next(context); return; } object?resource; if (AppContext.TryGetSwitch(SuppressUseHttpContextAsAuthorizationResource, out var useEndpointAsResource) && useEndpointAsResource) { resource = endpoint; } else { resource = context; } var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult !, context, resource); var authorizationMiddlewareResultHandler = context.RequestServices.GetRequiredService <IAuthorizationMiddlewareResultHandler>(); await authorizationMiddlewareResultHandler.HandleAsync(_next, context, policy, authorizeResult); }