Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Basic Authentication on WCF Service

I've been fighting trying to get custom basic authentication working on a WCF service for a while now and I've searched the internet trying to get a good answer with no luck.

I've tried using a custom userNameAuthentication and also a custom serviceAuthorizationManager.

What I am running into is that is that I get stuck in a "loop" of it asking for credentials and it never seems to get to my custom authentication. From my research, it would appear to be because IIS is hijacking the authentication and checking for local users.

From web config, I have transport security turned on with Basic authentication:

<webHttpBinding>
    <binding name="SecureBinding">
      <security mode="Transport">
        <transport clientCredentialType="Basic" />
      </security>
    </binding>
  </webHttpBinding>

Related service behaviors: (I have one of the things I tried commented out)

<serviceBehaviors>
    <behavior name="AuthenticatedWCF.CustomServiceBehavior">
      <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceAuthorization serviceAuthorizationManagerType="AuthenticatedWCF.Classes.Helpers.AuthenticationManager, AuthenticatedWCF" />
      <!--<serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="AuthenticatedWCF.Classes.Helpers.AuthenticationManager, AuthenticatedWCF" />
      </serviceCredentials>-->
    </behavior>
  </serviceBehaviors>

The authorization class (that never gets called):

public class AuthenticationManager : 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))
        {
            return true;
            /*var svcCredentials = System.Text.ASCIIEncoding.ASCII
                    .GetString(Convert.FromBase64String(authHeader.Substring(6)))
                    .Split(':');

            throw new Exception(authHeader);

            var user = new { Name = svcCredentials[0], Password = svcCredentials[1] };
            if ((user.Name == "user1" && user.Password == "test"))
            {
                //User is authrized 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=AuthenticatedWCF");
            //Throw an exception with the associated HTTP status code equivalent to HTTP status 401
            //throw new WebFaultException("Please provide a username and password", HttpStatusCode.Unauthorized);
            throw new WebFaultException(HttpStatusCode.Unauthorized);
            //return false;
        }
    }
}

I guess the question would be, how do I get around IIS being a jerk?

If you need more details, let me know and I'd be happy to share answers to any questions you may have.

like image 877
Andrew McGivery Avatar asked Nov 24 '22 07:11

Andrew McGivery


1 Answers

You must turn off basic authentication in the web config for this class to get called. Basic authentication is handled by IIS prior to your application even being made aware of it.

like image 126
Jason Coyne Avatar answered Nov 25 '22 22:11

Jason Coyne