Asp.Net Web API – Bearer Token Authentication Problem with BasicAuthenticationAttribute

Cenk 956 Reputation points
2022-02-05T05:25:10.017+00:00

Hello,

I have an ASP.net Web API that is working with BasicAuthenticationAttribute. I want to add bearer token-based authentication to one of my controllers. I added those NuGet packages:

  • Microsoft.AspNet.WebApi.Owin
  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.Owin.Security.OAuth

When API starts, there is no problem with the web API config.

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);
        }
    }

Then Owin startup starts to work.

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());
        }
    }

At this line below flow goes back to the web API config file.

WebApiConfig.Register(configuration);

And finally, it gets a null exception for basic authentication.

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.

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,306 questions
ASP.NET API
ASP.NET API
ASP.NET: A set of technologies in the .NET Framework for building web applications and XML web services.API: A software intermediary that allows two applications to interact with each other.
302 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Cenk 956 Reputation points
    2022-02-05T15:44:55.44+00:00

    Here is 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;
            }
    
    
            public override void OnAuthorization(HttpActionContext actionContext)
            {
                //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];
                        //call the login method to check the username and password
                        var uv = _factory();
                        if (uv.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);
                    }
                }
            }
        }
    

  2. Cenk 956 Reputation points
    2022-02-05T16:11:33.93+00:00

    I changed Owin startup as follows but this time I am not getting null, however not getting 401 Authorization has been denied for this request either.

    public void Configuration(IAppBuilder app)
            {
                var configuration = GlobalConfiguration.Configuration;
    
                //WebApiConfig.Register(configuration);
                app.UseWebApi(configuration);
    
                Configure(app);
            }
    
    0 comments No comments