예제 #1
0
        /// <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);
        }