Saturday, September 7, 2019

How do Authentication in WCF?

We discussed how bindings provide confidentiality and integrity security features, out of the box without any additional configuration. In this video we will discuss Authentication and in a later video we will discuss authorization. Out of the box most bindings provide authentication without any additional configuration.

For example, out of the box, both wsHttpBinding and netTcpBinding provides windows authentication. Let's understand this with an example.

Step 1: Create a class library project with name = SimpleService. Delete the autogenerated class1.cs file.

Step 2: Right click on SimpleService project in solution explorer and add a WCF service with name = SimpleService

Step 3: Copy and paste the following code in ISimpleService.cs file
using System.ServiceModel;

namespace SimpleService
{
    [ServiceContract]
    public interface ISimpleService
    {
        [OperationContract]
        string GetUserName();
    }
}

Step 4: Copy and paste the following code in SimpleService.cs file
using System;
using System.ServiceModel;

namespace SimpleService
{
    public class SimpleService : ISimpleService
    {
        public string GetUserName()
        {
            Console.WriteLine("Is Authenticated: " +
                ServiceSecurityContext.Current.PrimaryIdentity.IsAuthenticated);
            Console.WriteLine("Authentication Type: " +
                ServiceSecurityContext.Current.PrimaryIdentity.AuthenticationType);
            Console.WriteLine("Username: " +
                ServiceSecurityContext.Current.PrimaryIdentity.Name);

            return "Authenticated User Name: " +
                ServiceSecurityContext.Current.PrimaryIdentity.Name;
        }
    }
}

Step 5: Right click on SimpleService solution in solution explorer and add a console project with name = Host. We will use this project to host the WCF service.

Step 6: Right click on References folder under Host project and add a reference to SimpleService project and System.ServiceModel assembly.


Step 7:  Right click on Host project and add Application Configuration file. This should add App.config file.

Step 8: Copy and paste the following configuration in App.config file. Notice that at the moment we are using wsHttpBinding, which provides windows authentication by default.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="mexBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="mexBehavior" name="SimpleService.SimpleService">
        <endpoint address="SimpleService"
                  binding="wsHttpBinding"
                  contract="SimpleService.ISimpleService"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080" />
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
</configuration>

Step 9: Copy and paste the following code in Program.cs file in the Host project.
using System;
using System.ServiceModel;

namespace Host
{
    class Program
    {
        public static void Main()
        {
            using (ServiceHost host = new ServiceHost(typeof(SimpleService.SimpleService)))
            {
                host.Open();
                Console.WriteLine("Host started @ " + DateTime.Now.ToString());
                Console.ReadLine();
            }
        }
    }
}

Step 10: Set Host project as the startup project and run the application by pressing CTRL + F5 key. At this point we have the WCF service up and running.

Step 11: Now let's create a client for the WCF service. Create a new windows forms application with name = Client

Step 12: Add a service reference to SimpleService. Right click on References folder and select Add Service Reference. In the Add Service Reference window type Address = http://localhost:8080/ and click GO button. This should bring up the SimpleService. In the Namespace textbox type SimpleService and click OK.

Step 13: Drag and drop a button control on Form1. Set the following properties on button1
Name = btnCallService
Text  = Call Service

Step 14: Double click on the button to generate the "click event handler" method. Copy and paste the following code in Form1.cs file.
using System;
using System.Windows.Forms;

namespace Client
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnCallService_Click(object senderEventArgs e)
        {
            SimpleService.SimpleServiceClient client = new SimpleService.SimpleServiceClient();
            MessageBox.Show(client.GetUserName());
        }
    }
}

Run the WCF service and the client applications. When you click "Call Service" button, you should see the windows logged in username. In the service host console window you should see the following
1. Whether if the client is Is Authenticated
2. Authentication Type 
3. Authenticated user name

Please Note: If you have another windows user configured on the machine and if you run the application as a different user, you should see the user name of that user.

Now change the binding in App.config file from wsHttpBinding to netTcpBinding. Run the wcf service. Update the client service reference and notice that netTcpBinding also provides windows authentication by default.

To customize the security mode for a binding, use mode attribute of security element with in the respective binding
configuring security mode in wcf

To customize the authentication mode for a binding, use clientCredentialType attribute of either the message element or transport element with in the respective binding
configure transport clientcredentialtype in wcf

OR

configure message clientcredentialtype in wcf

No comments:

Post a Comment

Get max value for identity column without a table scan

  You can use   IDENT_CURRENT   to look up the last identity value to be inserted, e.g. IDENT_CURRENT( 'MyTable' ) However, be caut...