4

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 ???

1

3 Answers 3

11

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{.......}
Sign up to request clarification or add additional context in comments.

4 Comments

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
Edited answer @acostela
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?
I have all of this set but yet a request with no authorization header returns with 200, what can i possibly be missing?
1

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

    // ...
}

3 Comments

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).
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.
@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.
0

You should be able to send User name and encrypted Password as part of GET api URL.

/api/application/Get?user=''&pw=''

Your AuthorizationFilter should be able to parse them from RequestUri but of course you never want to do that, instead you might need to implement OAuth Token style access token send along with your API. Basically your user will use login panel and POST through https the login details and receive a token and then every time he or she makes request will send the access token along with that api like this:

/api/application/Get?access_token=""

This access token might expire after certain period of time or rate limitation. You can find an implementation here:

http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.