/// <summary>Processes the HTTP request authentication.</summary> /// <param name="context">The context.</param> /// <returns></returns> /// <exception cref="Exception">No auth factory established for authenticated route /// or /// No auth providers established for authenticated route</exception> internal static async Task <bool> ProcessHttpRequestAuthentication(this ApiRequestContext context) { if (!context.RequestAborted.IsCancellationRequested) { if (!(context.Configuration?.AllowAnonymous ?? false)) { // log // ---------------------------------------------------------------------------- context.Log($"{nameof(ProcessHttpRequestAuthentication)} Not anonymous"); var authenticationComponents = context.Configuration?.AuthenticationProviders ?? new List <IAuthenticationComponent>(); // log // ---------------------------------------------------------------------------- context.Log($"{nameof(ProcessHttpRequestAuthentication)} authenticationComponents: {authenticationComponents.Count}"); var contextResolver = context?.RequestServices?.GetService <IApiRequestContextResolver>(); var providers = authenticationComponents .Where(a => a != null) .Select(a => a.Activate(contextResolver)) .Where(a => a != null) .ToList(); // log // ---------------------------------------------------------------------------- context.Log($"{nameof(ProcessHttpRequestAuthentication)} providers: {providers.Count}"); var authProvider = providers .FirstOrDefault(p => p.CanHandleAuthScheme(context.Request.ClientAuthenticationInfo?.AuthScheme)); // log // ---------------------------------------------------------------------------- context.Log($"{nameof(ProcessHttpRequestAuthentication)} authProvider: {authProvider?.GetType()?.Name}"); if (authProvider != null) { if (context.Request.ClientAuthenticationInfo == null) { context.Request.ClientAuthenticationInfo = new ClientAuthentication { AuthenticatedBy = AuthenticationType.Provider }; } else { context.Request.ClientAuthenticationInfo.AuthenticatedBy = AuthenticationType.Provider; } context.Request.ClientAuthenticationInfo.AuthResult = await authProvider.Authenticate(contextResolver).ConfigureAwait(false); } else { if (context.Request.ClientAuthenticationInfo == null) { context.Request.ClientAuthenticationInfo = new ClientAuthentication { AuthenticatedBy = AuthenticationType.None }; } else { context.Request.ClientAuthenticationInfo.AuthenticatedBy = AuthenticationType.None; } } context.Request.ClientAuthenticationInfo.AuthResult = context.Request.ClientAuthenticationInfo.AuthResult ?? new AuthenticationResult(false); context.Request.ClientAuthenticationInfo.Principal = context.Request.ClientAuthenticationInfo.AuthResult.Principal; var result = context.Request.ClientAuthenticationInfo.AuthResult; if (!result?.IsAuthenticated ?? false) { var challenges = new List <string>(); foreach (var p in providers) { if (!challenges.Contains($"{p.Scheme} realm=\"{p.Realm}\"")) { challenges.Add($"{p.Scheme} realm=\"{p.Realm}\""); } } ; context.Response.StatusCode = 401; challenges.ForEach(c => { context.Response.AddHeader( name: "WWW-Authenticate", value: c, append: false, allowMultiple: true); }); return(false); } } else { if (context.Request.ClientAuthenticationInfo == null) { context.Request.ClientAuthenticationInfo = new ClientAuthentication { AuthenticatedBy = AuthenticationType.Anonymous, AuthResult = new AuthenticationResult(true) }; } else { context.Request.ClientAuthenticationInfo.AuthenticatedBy = AuthenticationType.Anonymous; context.Request.ClientAuthenticationInfo.AuthResult = new AuthenticationResult(true); } } return(true); } return(false); }