How use AuthorizationFilterAttribute in WebApi with WebClient Library?

27,485

Solution 1

As described on c# corner:

Add BasicAuthenticationAttribute.cs class in your solution.

With following code

public class BasicAuthenticationAttribute : AuthorizationFilterAttribute
{
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        try
        {
            if (actionContext.Request.Headers.Authorization == null)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            }
            else
            {
                // Gets header parameters  
                string authenticationString = actionContext.Request.Headers.Authorization.Parameter;
                string originalString = Encoding.UTF8.GetString(Convert.FromBase64String(authenticationString));

                // Gets username and password  
                string usrename = originalString.Split(':')[0];
                string password = originalString.Split(':')[1];

                AuthsController auth = new AuthsController();
                // Validate username and password  
                if (!auth.ValidateUser(usrename, password))
                {
                    // returns unauthorized error  
                    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                }
            }

            base.OnAuthorization(actionContext);
        }
        // Handling Authorize: Basic <base64(username:password)> format.
        catch(Exception e)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
        }
    }
}

In AuthsController.cs(Entity Framework)

Add

[NonAction]
    public bool ValidateUser(string userName, string password)
    {
        // Check if it is valid credential  
        var queryable = db.Auths
                        .Where(x => x.Name == userName)
                        .Where(x => x.Password == password);
        if (queryable != null)
        { 
            return true;
        }
        else
        {
            return false;
        }
    }

In WebApiConfig.cs

Add

config.Filters.Add(new BasicAuthenticationAttribute());

In Your controller that requires Basic Authorization.

Add

[BasicAuthentication]
public class YourController : ApiController{.......}

Solution 2

Basic authentication requires Authorization header to be set:

using (var client = new WebClient())
{    
    var credential = String.Format("{0}:{1}", userName, password);
    var encodedCredential = Convert.ToBase64String(Encoding.UTF8.GetBytes(credential))    
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encodedCredential);

    // ...
}
Share:
27,485
Hamed F
Author by

Hamed F

Updated on October 04, 2020

Comments

  • Hamed F
    Hamed F over 3 years

    I use the following code for Authorization (I found it in internet and change it for my use)

    when i call my url seems authorization works enter image description here

        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
        public class ClientAuthorizationAttribute : AuthorizationFilterAttribute
        {
            private bool _active = true;
    
            public ClientAuthorizationAttribute()
            {
    
            }
    
            public ClientAuthorizationAttribute(bool active)
            {
                _active = active;
            }
    
            public override void OnAuthorization(HttpActionContext actionContext)
            {
                if (_active)
                {
                    var identity = ParseAuthorizationHeader(actionContext);
                    if (identity == null)
                    {
                        Challenge(actionContext);
                        return;
                    }
    
    
                    if (!OnAuthorizeUser(identity.Name, identity.Password, actionContext))
                    {
                        Challenge(actionContext);
                        return;
                    }
    
                    var principal = new GenericPrincipal(identity, null);
    
                    Thread.CurrentPrincipal = principal;
                    base.OnAuthorization(actionContext);
                }
            }
    
            protected virtual bool OnAuthorizeUser(string clientId, string authId, HttpActionContext actionContext)
            {
                return false;
            }
            protected virtual ClientAuthenticationIdentity ParseAuthorizationHeader(HttpActionContext actionContext)
            {
                string authHeader = null;
                var auth = actionContext.Request.Headers.Authorization;
                if (auth != null && auth.Scheme == "Basic")
                    authHeader = auth.Parameter;
    
                if (string.IsNullOrEmpty(authHeader))
                    return null;
    
                authHeader = Encoding.UTF8.GetString(Convert.FromBase64String(authHeader));
    
                var tokens = authHeader.Split(':');
                if (tokens.Length < 2)
                    return null;
    
                return new ClientAuthenticationIdentity(tokens[0], tokens[1]);
            }
    
            void Challenge(HttpActionContext actionContext)
            {
                var host = actionContext.Request.RequestUri.DnsSafeHost;
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                actionContext.Response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", host));
            }
        }
    
        public class ClientAuthenticationIdentity : GenericIdentity
        {
            public ClientAuthenticationIdentity(string name, string password)
                : base(name, "Basic")
            {
                Password = password;
            }
            public string Password { get; set; }
        }
    
        public class BasicAuthorizationAttribute : ClientAuthorizationAttribute
        {
    
            public BasicAuthorizationAttribute()
            { }
    
            public BasicAuthorizationAttribute(bool active)
                : base(active)
            { }
    
    
            protected override bool OnAuthorizeUser(string clientId, string authId, HttpActionContext actionContext)
            {
                var businness = new WebServiceAuthBusiness();
                return businness.Count(x => x.ClientID == clientId && x.AuthenticateID == authId) > 0;
            }
        }
    }
    

    in Client I use WebClient for Get application data (Does not work)

        [BasicAuthorization]
        public IList<Application> Get()
        {
            using (var client = new WebClient())
            {
    
                client.BaseAddress = _baseAddress;
                client.Encoding = Encoding.UTF8;
                client.UseDefaultCredentials = true; ???
                client.Credentials = new NetworkCredential(clientId, authId); ???
                var str = client.DownloadString("api/application/get");
                return JsonConvert.DeserializeObject<List<Application>>(str);
            }
        }
    

    How i can send username and password with webClient for AuthorizationFilter ???

  • The Dag
    The Dag over 9 years
    What is the point of encoding a string as base64? It adds zero security but takes 33% more space (any ASCII char requires one byte in UTF-8, but four characters are needed to represent three bytes as base64).
  • akava
    akava over 9 years
    base64 encoding is a requirement of BASIC authentication protocol: ietf.org/rfc/rfc2617.txt To receive authorization, the client sends the userid and password, separated by a single colon (":") character, within a base64 [7] encoded string in the credentials.
  • Jon49
    Jon49 over 8 years
    @TheDag, If you haven't figured it out yet. Base64 makes it so characters that normally can't be sent over HTTP can be sent by encoding them in the base characters which are allowed.
  • acostela
    acostela almost 7 years
    As an external link can provide a valid answer, please add here the main code of the post. If in the future that link is broken this answer will be useless for the rest of the users. Thank you
  • user8024555
    user8024555 almost 7 years
    Edited answer @acostela
  • Ram Kishore K
    Ram Kishore K over 5 years
    Isn't it sufficient to add either config.Filters.Add(new BasicAuthenticationAttribute()); in the global config or decorate your controller with BasicAuthentication Attribute. Why both?
  • fay
    fay over 5 years
    I have all of this set but yet a request with no authorization header returns with 200, what can i possibly be missing?