Question adding Bearer Token to BasicAuthentication?

raysefo

Well-known member
Joined
Feb 22, 2019
Messages
361
Programming Experience
10+
Hi,

I have an ASP.Net Web API 2 with BasicAuthenticationAttribute that is working as expected. In my application, there are different controllers and I want to add bearer token-based authentication to one of my controllers. I added those NuGet packages:

NuGet:
Microsoft.AspNet.WebApi.Owin
Microsoft.Owin.Host.SystemWeb
Microsoft.Owin.Security.OAuth

There is no problem with the web API config.

WebApiConfig:
public static class WebApiConfig
    {
       public static void Register(HttpConfiguration config)
       {
                    
           config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        config.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling =
        DateTimeZoneHandling.Local;
                
        config.MapHttpAttributeRoutes();
      
        config.Routes.MapHttpRoute(
            "DefaultApi",
            "api/{controller}/{id}",
            new {id = RouteParameter.Optional}
        );
        
                          
       config.MessageHandlers.Add(new RequestResponseHandler());
                    
       config.Filters.Add(new CustomExceptionFilter());
        
       var resolver = config.DependencyResolver;
       var basicAuth = resolver.GetService(typeof(BasicAuthenticationAttribute)) as BasicAuthenticationAttribute;
       config.Filters.Add(basicAuth);
   }
}

Here is Owin startup
Owin Startup:
public class Startup
     {
         public void Configuration(IAppBuilder app)
         {
             var configuration = new HttpConfiguration();
             Configure(app);
    
             WebApiConfig.Register(configuration);
             app.UseWebApi(configuration);
         }
    
         private static void Configure(IAppBuilder app)
         {
             var options = new OAuthAuthorizationServerOptions()
             {
                 TokenEndpointPath = new Microsoft.Owin.PathString("/token"),
                 AccessTokenExpireTimeSpan = TimeSpan.FromHours(1),
                 AllowInsecureHttp = true,
                 Provider = new AuthorizationServerProvider()
             };
    
             app.UseOAuthAuthorizationServer(options);
             app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
         }
     }

In the configuration of Owin startup, the program flow goes back to the web API config file.
C#:
WebApiConfig.Register(configuration);

And finally, it gets a null exception for basic authentication.
C#:
config.Filters.Add(basicAuth);

How can I solve this and use both basic authentication attribute and token-based authentication in my web API?

Best Regards.
 
Solution
After long googling, here is how I managed to use both basic authentication and bearer authentication for my different controllers.


In Custom basic authentication Attribute I used dependency and requestScope.GetService.
Custom Basic Authentication:
public class CustomBasicAuthenticationAttribute : AuthorizationFilterAttribute
    {
        [Dependency] public static IUserValidate authentication { get; set; }

        private const string Realm = "My Realm";
        

        public override void OnAuthorization(HttpActionContext actionContext)
        {
            var requestScope = actionContext.Request.GetDependencyScope();

            //If the Authorization header is empty or null
            //then return Unauthorized
            if...
How can I use OverrideAuthenticationand my basic authentication attribute?

Basic Authentication Attribute:
public class BasicAuthenticationAttribute : AuthorizationFilterAttribute
    {
        private const string Realm = "My Realm";
        private readonly Func<IUserValidate> _factory;

        public BasicAuthenticationAttribute(Func<IUserValidate> factory)
        {
            _factory = factory;
        }
        ...
 
Last edited by a moderator:
After long googling, here is how I managed to use both basic authentication and bearer authentication for my different controllers.


In Custom basic authentication Attribute I used dependency and requestScope.GetService.
Custom Basic Authentication:
public class CustomBasicAuthenticationAttribute : AuthorizationFilterAttribute
    {
        [Dependency] public static IUserValidate authentication { get; set; }

        private const string Realm = "My Realm";
        

        public override void OnAuthorization(HttpActionContext actionContext)
        {
            var requestScope = actionContext.Request.GetDependencyScope();

            //If the Authorization header is empty or null
            //then return Unauthorized
            if (actionContext.Request.Headers.Authorization == null)
            {
                actionContext.Response = actionContext.Request
                    .CreateResponse(HttpStatusCode.Unauthorized);
                // If the request was unauthorized, add the WWW-Authenticate header
                // to the response which indicates that it require basic authentication
                if (actionContext.Response.StatusCode == HttpStatusCode.Unauthorized)
                    actionContext.Response.Headers.Add("WWW-Authenticate",
                        $"Basic realm=\"{Realm}\"");
            }
            else
            {
                //Get the authentication token from the request header
                var authenticationToken = actionContext.Request.Headers
                    .Authorization.Parameter;
                try
                {
                    //Decode the string
                    var decodedAuthenticationToken = Encoding.UTF8.GetString(
                        Convert.FromBase64String(authenticationToken));
                    //Convert the string into an string array
                    var usernamePasswordArray = decodedAuthenticationToken.Split(':');
                    //First element of the array is the username
                    var username = usernamePasswordArray[0];
                    //Second element of the array is the password
                    var password = usernamePasswordArray[1];

                    authentication = requestScope.GetService(typeof(IUserValidate)) as IUserValidate;

                    if (authentication != null && authentication.Login(username, password))
                    {
                        var identity = new GenericIdentity(username);
                        IPrincipal principal = new GenericPrincipal(identity, null);
                        Thread.CurrentPrincipal = principal;
                        if (HttpContext.Current != null) HttpContext.Current.User = principal;
                    }
                    else
                    {
                        actionContext.Response = actionContext.Request
                            .CreateResponse(HttpStatusCode.Unauthorized);
                    }
                }
                catch
                {
                    actionContext.Response = actionContext.Request
                        .CreateResponse(HttpStatusCode.Unauthorized);
                }
            }
        }
    }

In one of my controller, I added those attributes
Controller:
[OverrideAuthentication]
        [CustomBasicAuthentication]

        [HttpPost, Route("purchase")]
        public async Task<IHttpActionResult> PurchaseGame(RequestDto game)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
...
Now I can use bearer token authentication for ...api/v2/game/abc101/purchase and basic authentication for ...api/v2/game/purchase.

Hope this solution helps for others.
 
Solution
How important is that OverrideAuthentication attribute to the overall solution? Is the CustomBasicAuthentication ignored without it?
 
The vital part is the dependency and actionContext.Request.GetDependencyScope();. Without OverrideAuthentication it is working as expected.
 
Back
Top Bottom