Is it possible to have Oauth in WCF Webservice?

104 Views Asked by At

I currently have webservice calls that create a proxy interface for a URL. I have a requirement to update the application to accept Oauth 2.0. Is it possible to use Oauth 2.0 with WCF Webservice calls?

This is my proxy interface initialization. I use it just like a regular class initialization.

 var client = ServiceClient.CreateProxyInterface<MyWebServiceClass>(WebServiceUrl);

inside the proxy interface I do some authorization checks and create an instance of the requested object and return it back to the client

public static TInterface CreateProxyInterface<TInterface>(string ServiceUrl) where TInterface : class
    {
       var UseClientCertificate = true;
      
      if (ServiceClient.IsUnsecuredHttpService(ServiceUrl, UseClientCertificate))
        ServiceUrl = new UriBuilder(ServiceUrl)
        {
          Scheme = Uri.UriSchemeHttps,
          Port = -1
        }.Uri.ToString();
     
     var key =  TInterface.ToString() + ServiceUrl + UseClientCertificate.ToString();
     ChannelFactory myChannelFactory = ServiceClient.FactoryCache[key];
     proxy = ((ChannelFactory<TInterface>) mlifChannelFactory1.Factory).CreateChannel();
     
     return proxyInterface;
    }

the client can then call a method within that class

 var address = client.GetAddress(personId);
1

There are 1 best solutions below

0
Theobald Du On

On the server side, you can customize a class to inherit ServiceAuthorizationManager, and then override the CheckAccessCore method in ServiceAuthorizationManager to implement it. Below is an example I found from previous answers:OAuth and WCF SOAP service. After my attempts, his example is effective, so I think it should help you.

 public class OAuthAuthorizationManager : ServiceAuthorizationManager
    {
        protected override bool CheckAccessCore(OperationContext operationContext)
        {
            // Extract the action URI from the OperationContext. Match this against the claims 
            // in the AuthorizationContext. 
            string action = operationContext.RequestContext.RequestMessage.Headers.Action;
    
            try
            {
                //get the message
                var message = operationContext.RequestContext.RequestMessage;
    
                //get the http headers
                var httpHeaders = ((System.ServiceModel.Channels.HttpRequestMessageProperty)message.Properties.Values.ElementAt(message.Properties.Keys.ToList().IndexOf("httpRequest"))).Headers;
    
    
            //get authorization header
            var authHeader = httpHeaders.GetValues("Authorization");

            if (authHeader != null)
            {
                var parts = authHeader[0].Split(' ');

                if (parts[0] == "Bearer")
                {
                    var tokenClaims = ValidateJwt(parts[1]);
                    foreach (System.Security.Claims.Claim c in tokenClaims.Where(c => c.Type == "http://www.contoso.com/claims/allowedoperation"))
                    {
                        var authorized = true;
                        //other claims authorization logic etc....
                        if(authorized)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;

        }
        catch (Exception)
        {
            throw;
        }

    }

    private static IEnumerable<System.Security.Claims.Claim> ValidateJwt(string jwt)
    {
        var handler = new JwtSecurityTokenHandler();
        var validationParameters = new TokenValidationParameters()
        {
            ValidAudience = "urn://your.audience",
            IssuerSigningKey = new InMemorySymmetricSecurityKey(Convert.FromBase64String("base64encoded symmetric key")),
            ValidIssuer = "urn://your.issuer",
            CertificateValidator = X509CertificateValidator.None,
            RequireExpirationTime = true
        };

        try
        {
            SecurityToken validatedToken;
            var principal = handler.ValidateToken(jwt, validationParameters, out validatedToken);

            return  principal.Claims;

        }
        catch (Exception e)
        {
            return new List<System.Security.Claims.Claim>();
        }

    }
}