protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            try
            {
                this.Logger.LogInformation("{LogKey:l} easyauth handle", LogKeys.Authentication);

                if (this.Request.Host.Host.SafeEquals("localhost") && this.Options.IgnoreLocal)
                {
                    // ignore for localhost
                    var identity = new ClaimsIdentity(
                        this.Options.Claims.Safe().Select(c => new Claim(c.Key, c.Value))
                        .Insert(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationKeys.EasyAuthScheme))
                        .Insert(new Claim(ClaimTypes.Name, ClaimsIdentity.DefaultIssuer))
                        .DistinctBy(c => c.Type),
                        this.Scheme.Name);
                    var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), this.Scheme.Name);
                    this.Logger.LogInformation($"{{LogKey:l}} easyauth authenticated (name={identity.Name})", LogKeys.Authentication);

                    return(AuthenticateResult.Success(ticket));
                }

                var isEnabled = string.Equals(Environment.GetEnvironmentVariable("WEBSITE_AUTH_ENABLED", EnvironmentVariableTarget.Process), "True", StringComparison.OrdinalIgnoreCase);
                if (!isEnabled)
                {
                    return(AuthenticateResult.NoResult());
                }

                var provider         = this.Context.Request.Headers["X-MS-CLIENT-PRINCIPAL-IDP"].FirstOrDefault();
                var principalEncoded = this.Context.Request.Headers["X-MS-CLIENT-PRINCIPAL"].FirstOrDefault();
                if (principalEncoded.IsNullOrEmpty())
                {
                    return(AuthenticateResult.NoResult());
                }

                var principalBytes   = Convert.FromBase64String(principalEncoded);
                var principalDecoded = System.Text.Encoding.Default.GetString(principalBytes);
                var clientPrincipal  = JsonConvert.DeserializeObject <ClientPrincipal>(principalDecoded);

                var principal = new ClaimsPrincipal();
                var claims    = clientPrincipal.Claims.Select(c => new Claim(c.Type, c.Value));
                principal.AddIdentity(
                    new ClaimsIdentity(claims, clientPrincipal.AuthenticationType, clientPrincipal.NameType, clientPrincipal.RoleType));

                this.Logger.LogInformation($"{{LogKey:l}} easyauth authenticated (name={principal.Identity.Name})", LogKeys.Authentication);

                return(AuthenticateResult.Success(new AuthenticationTicket(principal, provider)));
            }
            catch (Exception ex)
            {
                this.Logger.LogError(ex, $"{{LogKey:l}} {ex.Message}", LogKeys.Authentication);
                var context = new ErrorContext(this.Context, this.Scheme, this.Options)
                {
                    Exception = ex
                };
                if (this.Events != null)
                {
                    await this.Events.Error(context).AnyContext();

                    if (context.Result != null)
                    {
                        return(context.Result);
                    }
                }

                throw;
            }
        }
Exemple #2
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            try
            {
                this.Logger.LogInformation("{LogKey:l} basic handle", LogKeys.Authentication);

                if (this.Request.Host.Host.SafeEquals("localhost") && this.Options.IgnoreLocal)
                {
                    // ignore for localhost
                    var identity = new ClaimsIdentity(
                        this.Options.Claims.Safe().Select(c => new Claim(c.Key, c.Value))
                        .Insert(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationKeys.ApiKeyScheme))
                        .Insert(new Claim(ClaimTypes.Name, ClaimsIdentity.DefaultIssuer))
                        .DistinctBy(c => c.Type),
                        this.Scheme.Name);
                    var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), this.Scheme.Name);
                    this.Logger.LogInformation($"{{LogKey:l}} basic authenticated (name={identity.Name})", LogKeys.Authentication);

                    return(AuthenticateResult.Success(ticket));
                }

                string value;
                if (this.Request.Query.TryGetValue("basic", out var queryValue))
                {
                    // also allow the auth header to be sent in the querystring (for easy dashboard usage)
                    value = queryValue.ToString();
                }
                else
                {
                    if (!this.Request.Headers.ContainsKey(AuthenticationKeys.AuthorizationHeaderName))
                    {
                        return(AuthenticateResult.NoResult()); //Authorization header not in request
                    }

                    if (!AuthenticationHeaderValue.TryParse(this.Request.Headers[AuthenticationKeys.AuthorizationHeaderName], out var headerValue))
                    {
                        return(AuthenticateResult.NoResult()); //Invalid Authorization header
                    }
                    else
                    {
                        value = headerValue.Parameter;
                    }

                    if (!AuthenticationKeys.BasicScheme.Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase))
                    {
                        return(AuthenticateResult.NoResult()); //Not a basic authentication header
                    }
                }

                if (value.IsNullOrEmpty())
                {
                    return(AuthenticateResult.NoResult()); //No apikey authentication value in header or query
                }

                //var context = new ApiKeyValidationContext(this.Context, this.Scheme, this.Options) { ApiKey = headerValue.Parameter };
                //await this.Events.OnValidation(context);
                //if (context.Result != null)
                //{
                //    return context.Result;
                //}

#pragma warning disable SA1008 // Opening parenthesis must be spaced correctly
                var(authenticated, claims) = this.service.Validate(value);
#pragma warning restore SA1008 // Opening parenthesis must be spaced correctly
                if (authenticated)
                {
                    var identity = new ClaimsIdentity(
                        this.Options.Claims.Safe().Select(c => new Claim(c.Key, c.Value)).Concat(claims.Safe())
                        .Insert(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationKeys.ApiKeyScheme)).DistinctBy(c => c.Type),
                        this.Scheme.Name);
                    var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), this.Scheme.Name);
                    this.Logger.LogInformation($"{{LogKey:l}} basic authenticated (name={identity.Name})", LogKeys.Authentication);

                    return(AuthenticateResult.Success(ticket));
                }

                this.Logger.LogWarning("{LogKey:l} basic not authenticated", LogKeys.Authentication);
                return(AuthenticateResult.NoResult());
            }
            catch (Exception ex)
            {
                this.Logger.LogError(ex, $"{{LogKey:l}} {ex.Message}", LogKeys.Authentication);
                var context = new ErrorContext(this.Context, this.Scheme, this.Options)
                {
                    Exception = ex
                };
                if (this.Events != null)
                {
                    await this.Events.Error(context).AnyContext();

                    if (context.Result != null)
                    {
                        return(context.Result);
                    }
                }

                throw;
            }
        }