OData / OData/AspNetCoreOData

Querying Metadata Basic Auth Handler never called

Open
#703 4 comments 0 reactions 1 assignee View on GitHub

@habbes is already working on this.

Since Sep 27, 2022.

investigating
Dominant language
C#
Stars
505
Forks
186
PR merge metrics
No merged PRs in 30d

Description

I am enabling basic authentication and JwtBearer authentication mechanism. When querying metadata JwtBearer validation works but Basic Auth handler is never called.
How to authenticate a user using basic authentication when querying metadata?

Remark: Querying controller with [Authorised] attribute trigger HandleAuthenticateAsync

Startup.cs

//Add Authentication
           services.AddAuthentication()
               .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, (o) =>
               {
                   o.TokenValidationParameters = new TokenValidationParameters()
                   {
                       IssuerSigningKey = TokenAuthOption.Key,
                       ValidAudience = TokenAuthOption.Audience,
                       ValidIssuer = TokenAuthOption.Issuer,
                       ValidateIssuerSigningKey = true,
                       ValidateLifetime = true,
                       ValidateIssuer = true,
                       ValidateAudience = true,
                       ClockSkew = TimeSpan.FromMinutes(0)
                   };
               })
               .AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("Basic", null);

           //Add Authorization
           services.AddAuthorization((o) =>
           {
               // define Basic and Bearer default auth
               o.DefaultPolicy = new AuthorizationPolicyBuilder(new string[] { JwtBearerDefaults.AuthenticationScheme, "Basic" })
               .RequireAuthenticatedUser()
               .Build();

               //Only JwtBearer
               var onlyJwtBearerSchemePolicyBuilder = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme);
               o.AddPolicy(JwtBearerDefaults.AuthenticationScheme, onlyJwtBearerSchemePolicyBuilder
                   .RequireAuthenticatedUser()
                   .Build());

               //Only Basic
               var onlyBasicSchemePolicyBuilder = new AuthorizationPolicyBuilder("Basic");
               o.AddPolicy("Basic", onlyBasicSchemePolicyBuilder
                   .RequireAuthenticatedUser()
                   .Build());
           });

BasicAuthenticationHandler.cs

public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
    {
        public BasicAuthenticationHandler(
           IOptionsMonitor<AuthenticationSchemeOptions> options,
           ILoggerFactory logger,
           UrlEncoder encoder,
           ISystemClock clock
           ) : base(options, logger, encoder, clock)
        {
        }

        protected override Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            var authHeader = Request.Headers["Authorization"].ToString();
            if (authHeader != null && authHeader.StartsWith("basic", StringComparison.OrdinalIgnoreCase))
            {
                var token = authHeader.Substring("Basic ".Length).Trim();
                var credentialstring = Encoding.UTF8.GetString(Convert.FromBase64String(token));
                var credentials = credentialstring.Split(':');
                if (credentials[0] == "admin" && credentials[1] == "admin")
                {
                    //Build Claims
                    //var Claims = new List<Claim>();
                    //Claims.Add(new Claim(ClaimTypes.NameIdentifier, UserId.ToString()));
                    //Claims.Add(new Claim(ClaimTypes.Name, Username));
                    //Claims.Add(new Claim(ClaimTypes.Email, UserEmail));
                    //foreach (var userRole in UserRoles)
                    //    Claims.Add(new Claim(ClaimTypes.Role, userRole));

                    var claims = new[] { new Claim("name", credentials[0]), new Claim(ClaimTypes.Role, "Admin") };
                    var identity = new ClaimsIdentity(claims, "Basic");
                    var claimsPrincipal = new ClaimsPrincipal(identity);
                    return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, Scheme.Name)));
                }

                Response.StatusCode = 401;
                Response.Headers.Add("WWW-Authenticate", "Basic realm=\"ami.com\"");
                return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
            }
            else
            {
                Response.StatusCode = 401;
                Response.Headers.Add("WWW-Authenticate", "Basic realm=\"ami.com\"");
                return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
            }
        }
    }

`

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.