Search code examples
c#wcf

Unable to define user/password for WCF service


I have a WCF web service working with basic authentification.

I want to define a user/password for this service. So I wrote my web.config to user basic authentification :

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="UsernameWithTransportCredentialOnly">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Basic"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>

    <behaviors>
        <serviceBehaviors>
            <behavior name="ServiceWithMetaData">
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
                <serviceAuthorization serviceAuthorizationManagerType="InterfaceWS.CredentialsChecker,App_Code.CredentialsChecker"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>

    <services>
        <service behaviorConfiguration="ServiceWithMetaData" name="InterfaceWS.MyService" >
            <endpoint
                address="https://localhost:44336/MyService.svc"
                binding="basicHttpBinding"
                bindingConfiguration="UsernameWithTransportCredentialOnly"
                name="BasicEndpoint"
                contract="InterfaceWS.IErpService">
            </endpoint>
        </service>
    </services>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
        multipleSiteBindingsEnabled="false" />
</system.serviceModel>

I created a class inherited from ServiceAuthorizationManager :

namespace InterfaceWS
{
    public class CredentialsChecker : 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.ASCIIEncoding.ASCII
                    .GetString(Convert.FromBase64String(authHeader.Substring(6)))
                    .Split(':');
                var user = new
                {
                    Name = svcCredentials[0],
                    Password = svcCredentials[1]
                };
                if ((user.Name == "testuser" && user.Password == "testpassword"))
                {
                    //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=\"MyWCFService\"");
                //Throw an exception with the associated HTTP status code equivalent to HTTP status 401  
                throw new WebFaultException(HttpStatusCode.Unauthorized);
            }
        }

        public override bool CheckAccess(OperationContext operationContext)
        {
            return false;
        }
    }
}

But the CheckAccessCore is never reached and i'm unable to connect to my Service. What did I do wrong ?


Solution

  • serviceAuthorization is about granting access to particular resources based on user credentials. You want authentication. You can use serviceCredentials/userNameAuthentication tags in the configuration. Example of configuration is given here: https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/membership-and-role-provider