Authenticating to Java web services with C# using basic authentication

Download ProjectMy work uses Flexera’s FlexNet for licensing. They use Java for all their services and it uses SOAP. If you have Flexera installed, you can see all their services here: http://yourserver.hostname.told:port/flexnet/services. According to the ‘FlexNet Operations 12.8 Web Services Guide’ (page 11) I can authentication to these services in one of two ways:

Passing the Web Service User
By default, FlexNet Operations Web services requires a client to provide credentials as BASIC HTTP user
authentication. BASIC authentication encrypts the user ID and password with Base64 encoding and passes it as an
HTTP request header parameter. FlexNet For example:

Authorization: Basic QWxhghwelhijhrcGVuIHNlc2FtZQ==

However, not all Web services client tools offer the ability to pass custom HTTP request header parameters in the
request. Therefore, FlexNet Operations supports an alternative mechanism to pass user credentials as SOAP
header parameters along with the SOAP message. The two case-sensitive parameters are UserId and Password.
The password must be Base64 encoded.

<soapenv:Header xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <flex:UserId soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xmlns:flex="urn:com.macrovision:flexnet/platform">admin
    <flex:UserPassword soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"soapenv:mustUnderstand="0" xmlns:flex="urn:com.macrovision:flexnet/platform">YWRtaW4=
<!--<span class="hiddenSpellError" pre="" data-mce-bogus="1"-->soapenv:Header>

If the user is authenticated in a domain other than the FlexNet domain, the user ID must be passed as
userName##domain. domain is the name specified when the domain was added to FlexNet Operations. This syntax is
also valid for users in the FlexNet domain. For example, admin##FLEXnet.

The question is, how do I do this with SOAP?

Method 1 – Add Basic Authentication to Request

Step 1 – Add the Web References

First, I created old school Web References to my services.

  1. Right-click on References.
  2. Click Add Service Reference…
  3. Click Advanced (bottom left of window)
  4. Click Add Web Reference… (bottom left of window)
  5. Enter the URL: http://hostname.domain.tld:8888/flexnet/services/FlexnetAuthentication?wsdl
  6. Click the Arrow (right of the URL field)
  7. Set the Web Reference name: Flexera.Auth
  8. Click Add Reference
  9. Repeat these steps for:
    • Flexera.Entitlement – http://hostname.domain.tld:8888/flexnet/services/EntitlementOrderService?wsdl
    • Flexera.Organization – http://hostname.domain.tld:8888/flexnet/services/UserOrgHierarchyService?wsdl
    • . . .

Step 3 – Create a WebClientProtocol extension method to set Credentials

Since all services created with the Web Reference inherit from WebClientProtocol, we can add a single method to all our SOAP based services by using this extension method.

using System;
using System.Net;
using System.Web.Services.Protocols;

namespace ConnectToFlexeraExample.Extensions
{
    public static class WebClientProtocolExtensions
    {
        public static void SetNetworkCredentials(this WebClientProtocol client, string username, string password, string customUrl = null)
        {
            client.PreAuthenticate = true;
            var uri = string.IsNullOrWhiteSpace(customUrl) ? new Uri(client.Url) : new Uri(customUrl);
            var netCredential = new NetworkCredential(username, password);
            ICredentials credentials = netCredential.GetCredential(uri, "Basic");
            client.Credentials = credentials;
        }
    }
}

Step 3 – Create a WebRequest extension method to add basic auth

I created the following class. It assumes that the request has already been assigned the credentials (which we will do in the next step).

using System;
using System.Net;
using System.Text;

namespace ConnectToFlexeraExample.Extensions
{
    public static class WebRequestExtensions
    {
        public static WebRequest GetRequestWithBasicAuthorization(this WebRequest request, Uri uri)
        {
            var networkCredentials = request.Credentials.GetCredential(uri, "Basic");
            byte[] credentialBuffer = new UTF8Encoding().GetBytes(networkCredentials.UserName + ":" + networkCredentials.Password);
            request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(credentialBuffer);
            return request;
        }
    }
}

Step 4 – Inherit the Server Clients to override GetWebRequest

We need to override the GetWebRequest so we can return a request using the GetRequestWithBasicAuthorization extension method so let’s create child classes for our services to use. Also, we only want to use GetRequestWithBasicAuthorization if PreAuthenticate is set to true.

using ConnectToFlexeraExample.Extensions;
using ConnectToFlexeraExample.Flexera.Auth;
using System;
using System.Net;

namespace ConnectToFlexeraExample.Clients
{
    public class AuthenticationClient : FlexnetAuthenticationClient
    {
        protected override WebRequest GetWebRequest(Uri uri = null)
        {
            var actualUri = uri ?? new Uri(Url);
            var request = (HttpWebRequest)base.GetWebRequest(actualUri);
            return (PreAuthenticate) ? request.GetRequestWithBasicAuthorization(actualUri) : request;
        }
    }
}
using ConnectToFlexeraExample.Extensions;
using ConnectToFlexeraExample.Flexera.Organization;
using System;
using System.Net;

namespace ConnectToFlexeraExample.Clients
{
    public class OrganizationClient : UserOrgHierarchyService
    {
        protected override WebRequest GetWebRequest(Uri uri = null)
        {
            var actualUri = uri ?? new Uri(Url);
            var request = (HttpWebRequest)base.GetWebRequest(actualUri);
            return (PreAuthenticate) ? request.GetRequestWithBasicAuthorization(actualUri) : request;
        }
    }
}
using ConnectToFlexeraExample.Extensions;
using ConnectToFlexeraExample.Flexera.Entitlement;
using System;
using System.Net;

namespace ConnectToFlexeraExample.Clients
{
    public class EntitlementClient : EntitlementOrderService
    {
        protected override WebRequest GetWebRequest(Uri uri = null)
        {
            var actualUri = uri ?? new Uri(Url);
            var request = (HttpWebRequest)base.GetWebRequest(actualUri);
            return (PreAuthenticate) ? request.GetRequestWithBasicAuthorization(actualUri) : request;
        }
    }
}

Step 5 – Use the new service clients

    static void Main(string[] args)
    {
        string user = args[0];
        string pass = args[1];

        TestAuthenticationClient(user, pass);
        TestOrganizationClient(user, pass);
        TestEntitlementClient(user, pass);
    }

    private static void TestAuthenticationClient(string user, string pass)
    {
        var AuthenticationClientClient = new AuthenticationClient();
        // Basic Auth Method
        AuthenticationClientClient.SetNetworkCredentials(user, pass);
        var userInputType = new AuthenticateUserInputType
        {
            userName = user,
            password = pass,
            domainName = "FLEXnet"
        };
        var result = AuthenticationClientClient.authenticateUser(userInputType);
    }

    // ... other Test methods

You are now authenticating to FlexNet SOAP-based java web services with C#.

Read about Method 2 – SOAP Authentication here: Authenticating to Java web services with C# using Soap authentication (using FlexNet services as examples)

One Comment

  1. I found an easier way to do this by using a custom EndpointBehavior (ClientMessageInspector with BeforeSendRequest).

Leave a Reply

How to post code in comments?