Search code examples
c#wcfc#-4.0request-headersbasichttpbinding

Authentication for BasicHttpBinding using Request Hearder


I have a BasicHttpBinding WCF service. I want to get user name and password in request header. I searched in in the internet for this but I see just WSHttpBinding. I want to have something like this:

 //WCF client call
 WCFTestService.ServiceClient myService = new
 WCFTestService.ServiceClient();
 myService.ClientCredentials.UserName.UserName = "username";
 myService.ClientCredentials.UserName.Password = "p@ssw0rd";
 MessageBox.Show(myService.GetData(123));
 myService.Close();

but I don't know what should I write for server side?

Thanks


Solution

  • You could create a custom Authorization Class by inheriting the ServiceAuthorizationManager class and pull out the credentials from the request header.

    Your code could be similar to the following:

    public class CustomAuthorizationManager : ServiceAuthorizationManager
    {
        protected override bool CheckAccessCore(OperationContext operationContext)
        {
            //Extract the Authorization header, and parse out the credentials converting the Base64 string:  
            var authHeader = WebOperationContext.Current.IncomingRequest.Headers["Authorization"];
            if ((authHeader != null) && (authHeader != string.Empty))
            {
                var svcCredentials = System.Text.Encoding.ASCII
                    .GetString(Convert.FromBase64String(authHeader.Substring(6)))
                    .Split(':');
                var user = new
                {
                    Name = svcCredentials[0],
                    Password = svcCredentials[1]
                };
                if ((user.Name == "username" && user.Password == "p@ssw0rd"))
                {
                    //User is authorized and originating call will proceed  
                    return true;
                }
                else
                {
                    //not authorized  
                    return false;
                }
            }
            else
            {
                //No authorization header was provided, so challenge the client to provide before proceeding:  
                WebOperationContext.Current.OutgoingResponse.Headers.Add("WWW-Authenticate: Basic realm=\"YourNameSpace\"");
                //Throw an exception with the associated HTTP status code equivalent to HTTP status 401  
                throw new WebFaultException(HttpStatusCode.Unauthorized);
            }
        }
    }
    

    In addition to that, you need to set the serviceAuthorizationManagerType attribute of the serviceAuthorization element to your custom class in the web.config file.

    Something similar to this:

    <serviceAuthorization serviceAuthorizationManagerType="YourNameSpace.CustomAuthorizationManager, YourAssemblyName"/>
    

    In the client side, you also need to add the credentials to the request headers.

    HttpRequestMessageProperty httpReqProp = new HttpRequestMessageProperty();
    httpReqProp.Headers[HttpRequestHeader.Authorization] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("username"+ ":" + "p@ssw0rd"));
    

    Security note:

    Keep in mind that in Basic Authentication, the username and password will be sent as non-encrypted text in the request header. You should only implement this with SSL.