ADFS Environment Buildup with WCF Utilization – Part 3

Welcome back! This is part 3, and we are going to jump right in by configuring the security certificates on our identity server for the ADFS and IIS roles. If you’ve been following along as I’ve been publishing this multi-part article, I apologize for the delay between part 2 and 3, I had a hardware failure that delayed my writing.

 

Create a Certificate

If you are following along using a local network and VM machines then creating your own self-signed security certificates is likely going to be sufficient. This is what I will be doing for this tutorial.

However, for a production system you will likely want to use professionally created and signed certificates for your domain and server. Now is the time to get them and install them.

So we start by creating a certificate. Open up Powershell ISE once again and run the following script with your domain information.

New-SelfSignedCertificate -DnsName fs.martialdeveloper.local -CertStoreLocation Cert:\LocalMachine\My

The Thumbprint and the Subject will be displayed for you on the console after creation. Make a note of these two fields for future reference. Shown below.

create new cert

 

Bind the Certificate

Now we are going to hope over to IIS Manager by opening the server manger window, right clicking on the Tools menu and selecting “Internet Information Services (IIS) Manager” as shown below.

iis manager selection

Once the IIS Manager window comes up, we will navigate to the Default Wed Site, right click, and select the “Edit Bindings” option, as shown below.

IIS edit binding default website

On the window that pops up select “Add”, and configure the new binding for HTTPS and the security certificate you just created, like shown.

https binding

 

Create the ADFS Service

Now we are going to set up the ADFS service. Go to the Server Manager window, right click Tools, and select “AD FS Management”.

ADFS Manager selection

When the ADFS Management window comes up, click the configuration wizard link.

ADFS config wizard

Click “Next” on the first screen that appears, then select the “Stand-alone federation server” as shown below.

ADFS stand alone

For large production environments you may want to create a federation server farm, but for this tutorial we only need one.

Click next then verify the certificate that is auto populated is the one you created earlier, and then click Next three more times.

 

Create the Application Server Security Certificate

Now we have to jump back over to our application server and configure it for use.

Lets start by creating a security certificate for it. You have two options, either use the same PowerShell ISE command string as you did on the identity server(with application server specific substitutes), or navigate to the IIS Manager and create the certificate through the IIS GUI.  I’m going to show the IIS Manager approach since the PowerShell command has already been demonstrated.

Open the IIS Manager through the Tools menu of the Server Manager on the Application server.

IIS Manager Open

Now navigate the the local server and click the “Server Certificates” icon at the bottom of the list of options in the center of the GUI.

Server Certificates

Now we are going to create a self signed security certificate by clicking the link on the right side of the Server Certificates panel in the IIS Manager.

Create Self-Signed Cert

Now type in a friendly name for the security certificate. I use a similar name to the one created for the identity server.

Certificate Name

Click next and the certificate will appear in the security certificates list on the previous screen. Next right click on the newly created certificate and select the view option.

View Certificate

On the screen that pops up navigate to the Details tab and click the Copy to File button towards the bottom right.

Export Certificate

Now, on the screen that pops up click Next three times, then give the exported certificate file an easy to use and remember name and export location. Then click next.

Certificate Export Name

Click Next, Finish and Okay to complete the certificate export. You can now close the IIS Manager. Now we are going to copy the newly exported certificate to the identity server. Once this is done, we will use it to configure a relying part with the ADFS server.

In Part 4 we will continue by configuring the Identity server’s DNS roll with resource records to allow IPv4 lookups for our two servers, and then the we will configure the Identity server’s ADFS roll with a relying part pointing to our application server.

If you have any questions or comments about the above article please comment below!

 

References:

See references from Part 2.

 

ADFS Environment Buildup with WCF Utilization – Part 2

In Part 2 we will continue configuring the Identity server starting with installing the Active Directory Domain Services role.

 

Active Directory Domain Services

Begin by opening the Server Manager panel if it is not already. Click on Manage -> Add Roles and Features.

Continue through the wizard until you get to the role selection window and select the Active Directory Domain Services role shown below.

ADDS role selection

Add the additional features that automatically pop up and click “Next”. Continue clicking next until you reach the “Install” page, select the “Restart the Destination server automatically if required” check box, and click “Install”.

 

Static IP

Before continuing configure your Identity Server with a static IPv4 address, and disable IPv6. Since I am on a local network, my static IP is an internal IP only, but this is sufficient for this tutorial.

 

DNS Server and Domain Controller

 

The next things we are going to do are to, promote the identity server to a domain controller, install the DNS Server role onto the identity server, and to create a forest on the DNS Server with forward and reverse lookup zones for our local domain that we will be using for this tutorial. This next step is one good reason to use Virtual Machines if you are performing these configurations strictly as a learning exercise since you would have to have a dedicated domain if the machines were not on a private network.

Start by clicking the notification icon that has appeared since ADDS was added, shown below.

Promote domian controller notification

Next click the “Promote this server to a domain controller” link in the notifications drop down.

promote to DC link

In the wizard that comes up select the “Add a new forest” radio button shown below. Then type in the domain that you will be using.

add new forest domain name

Click next, then select the forest functional levels you want. I leave these at Server 2012 since I don’t plan on interacting with older DNS servers. Then enter a password for the DSRM, I use the admin password for this so it’s easy to remember for the demo but you will likely want a unique password for a production system.

Add new forest

Click “Next”. You will be warned about DNS Delegation options. For this demo on a local network this is not important, for a production environment, creating this delegation should be your next step.

Delegation to parent DNS server

Click OK and Next. Then on the next page click Install. Wait till the installation has finished to proceed.

Once the Identity server has completed it will then be a Domain Controller for martialdeveloper.local, and have the DNS Server role installed and integrated with Active Directory for the domain we created.

Application server IIS

While you are waiting for the Identity server to finish this installation you can start installing IIS on the Application server. Refer back to Part 1 of this series of articles if you forgot how to do this.

 

Configure Active Directory

We will continue by creating Organizational Units in Active Directory. We will be doing this in PowerShell. Please see Stefan Severin’s blog in the references section for the source of these commands. I am very happy to have found them on his blog!

Start by running Powershell ISE in administrative mode, and setting the execution policy to RemoteSigned.

Set-ExecutionPolicy RemoteSigned

Now run the following script to set the Organizational Units. Making sure to replace the first line with one appropriate for the domain you are using.

$domain = "dc=martialdeveloper,dc=local"; 
$ouAdmin = "ou=Adfs Administration"; 
$ouServiceAccounts = "ou=Service Accounts"; 
$ldapConnection = [ADSI] "LDAP://$domain"; 
$newAdminOu = $ldapConnection.Create("OrganizationalUnit", $ouAdmin); 
$newAdminOu.SetInfo(); 
Set-ADOrganizationalUnit "$ouAdmin,$domain" -ProtectedFromAccidentalDeletion $True; 
$ouAdminPath = [ADSI]($newAdminOu.path) 
$newAccountOu = $ouAdminPath.Create("OrganizationalUnit", $ouServiceAccounts); 
$newAccountOu.SetInfo(); 
Set-ADOrganizationalUnit "$ouServiceAccounts,$ouAdmin,$domain" -ProtectedFromAccidentalDeletion $True;

Now create the service account for the ADFS farm. Make sure to enter your domain specifics on line 4. Also, since this is a domain controller the strong password requirements are enabled, so get creative unless you want to have to recreate the account a few times when it fails on the password strength.

$dnsRoot = (Get-ADDomain).dnsroot 
$pwd = read-host "Enter strong password" -AsSecureString 
$upn = "SVC-ADFS" + "@" + $dnsRoot 
New-ADUser –Name "SVC-ADFS" –SamAccountName SVC-ADFS –DisplayName SVC-ADFS -Description "Service account for ADFS farm" -userprincipalname $upn -Path "OU=Service Accounts,OU=ADFS Administration,DC=martialdeveloper,DC=local" –Enabled $true –ChangePasswordAtLogon $False -PasswordNeverExpires $true -AccountPassword $pwd

Configure the SPN (Service Principle Name) for the ADFS service account. Making sure to remember to replace the hostname, and domain information for your environment.

setspn -S host/WIN-924FNOTSB0B.martialdeveloper.local martialdeveloper.local\svc-adfs

Now we install the ADFS Feature onto our identity server machine.

Install-WindowsFeature AD-Federation-Services

We now have ADFS installed, our domain is configured, and we have Active Directory setup. When we continue in Part 3, we will begin by configuring our security certificates for ADFS and IIS.

 

References:

As always, please have a look at my references for further information on the topics discussed above.

Adding Additional Domain Controller (Windows Server 2012)

http://blogs.msdn.com/b/stseverin/archive/2012/12/29/deploying-adfs-2-1-on-windows-server-2012-using-powershell.aspx

ADFS Environment Buildup with WCF Utilization – Part 1

Before I get into it, I wanted to give a little back ground about what this series of articles is, and what caused them to be written.

A while back I had a project come up that needed to use some WCF services for data sharing across multiple device types, and multiple domains.  Given that there were going to be potentially dozens of different corporate domains needing to access these services I thought ADFS or Active Directory Federation Services would be an ideal fit.

Ultimately we used far fewer of the ADFS features than originally thought but regardless, I struggled so much to understand the whole end to end process of building the servers and hosting up from scratch to deploy my services to, that I decided that I needed to document that learning experience in case any developer in the future who, like me, has to build a custom environment from the ground up needs some guidance.

For this tutorial you will need to have at least two Server 2012 machines to work with. You can accomplish this a number of ways, Hyper-V VMs, VMware VMs, two separate physical boxes, Amazon EC2 Instances, etc.. For this tutorial I will be using a single Server 2012 machine running VMs on Hyper-V, but the steps in this guide can be applied to a number of different computing environments. However, I would suggest using VMs on a private network if you are doing this strictly as a learning exercise. In later steps we will have to promote the Identity server to a Domain Controller.

In this tutorial I will be providing a concrete example of creating and configuring a custom application domain and implementing an ADFS server to handle token distribution.

I’m not entirely sure how many parts this series of articles will contain as there is a substantial amount of work and understanding involved here.

 

Before We Begin

Before we can get started, we need to have our first two machines up and running. Creating the VMs that you will be using or building the physical boxes is an exercise for the reader since there are so many ways of going about this.

Okay, so go ahead, get your machines set up, I’ll wait… done yet? No… Now? Okay good! Let’s move on!

 

First Steps

Our first several tasks are going to involve configuring the Identity server for all the various tasks it will be performing in the near future.  The Application server has much less configuration required but we will get to that later.

We are going to start by installing the IIS Role on the identity server. Log into your identity machine, the Server Manager panel should launch automatically. On the Server Manager panel click Manage->Add Roles and Features.

Add Roles

When the Roles and Features wizard comes up, you can click “Next” through the first three screens until you come to the roles selection screen shown below.

IIS role selection

Check the “Web Server (IIS)” box. There will be an automatic pop up asking to install the IIS management tools with the IIS role. Click the “Add Features” button shown below.

Add Feature confirmation

Then click “Next”. You will now be presented with the “Features Selection” screen. Strictly speaking, nothing should be absolutely necessary on this page but I like to add a few things as a personal preference, mostly for backwards compatibility. The three additional options I select are shown below.

Features selection

The HTTP Activation feature will require additional dependencies. Once your features are selected, click “Next” twice.

Now you’re presented with the Role Services selection window. A lot of the choices here are going to be based on your needs, but I have a set of capabilities that I like or need in most IIS installations that I will show below in the next three images.

IIS services 1 IIS Services 2 IIS Services 3

Most of the selections I make here are not strictly necessary but the two categories you need to think about the most are the Security and Logging options.  Additional Security services will allow you the freedom of choosing to authenticate your WCF services/users in more ways, and the additional logging options are extremely handy when you’re getting a very generic authentication failure error message and can’t figure out why.

Now click “Next” and on the following page make sure to select the automatic restart check box as shown below.

Restart and install

Then click “Install”. A progress bar screen will be displayed, and the server will automatically restart during the installation process if necessary.

In Part 2 we will continue configuring the Identity server with the additional roles and services that it needs to act as an identity server, starting with ADDS(Active Directory Domain Services).

Now that you have been through the process of adding a Role, the next section will not have as much detail about how to do this, unless an important configuration needs to be pointed out during the role installation.

UDP Discovery Tutorial – Part 2

In Part 1 of this article I showed how one might use UDP datagrams to discover a client or server on a connected system over an IPv4 network. In Part 2 I am going to add a subsequent TCP connection and briefly explain how it is done.

 

Now we add a TCP connection.

There is more than one way to approach adding a TCP connection to this example.  One of the simpler to understand approaches would be to use UDP to broadcast the listener’s IP back to the broadcaster after the listener received the broadcaster’s IP, and then create a TCP connection between the two specific IPs.

I am not using the above described method however. It seems to me to be a more usable approach to have the broadcaster asynchronously wait for an incoming TCP connection from any source, and once the connection is made authentication can be performed, but as with Part 1, I leave authentication and error handling up to the reader to implement.

Since we are using an asynchronous model for the TCP connection and communications, the pattern that all operations will follow is:

  1. Operation
  2. Callback
  3. Wait on Callback

We will also be using custom events to implement our waiting operations. These are created on lines 28 of the UDPBroacaster project and lines 27-29 of the UDPListener project.

 

Resolve the TCP address to an Endpoint

The first step we perform here is to resolve the TCP address that we are using to an endpoint object for the TCP client object to initialize itself with.

For the listener this is done using the IP received in the UDP datagram:

IPEndPoint remoteEP = new IPEndPoint(tcpAddress, tcpPort);

For the broadcaster this is done using it’s own host IP since we are accepting connections from any other address.

IPEndPoint localEndPoint = new IPEndPoint(localIP, tcpPort);

 

Connect to the Broadcaster

Once we have the endpoints we now attempt a connection to the UDPBroadcast application from the UDPListener application:

            // Connect to the remote endpoint
            client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();  // Without these waits other processing could continue
            listView.Items.Add("TCP Connection Established with UDPBroadcaster");

 

Asynchronously wait for connection

Now we listen for an incoming connection request from anyone within the UDPBroadcast application:

            // Bind the socket to the local endpoint and listen for incoming connections
            //  This logic will parrot back any message received
            listener.Bind(localEndPoint);
            listener.Listen(100);

            // Start an asynchronous socket to listen for connections
            listener.BeginAccept(
                new AsyncCallback(AcceptCallback),
                listener);

            // Wait until a connection is made before continuing
            allDone.WaitOne();
            listView.Items.Add("TCP Connection has been Established, and message received and returned");

The above listening logic for the UDPBroadcast application will asynchronously listen for a TCP connection, and once established, will wait for a message, read the message and return the same message back to the sender.  You can see all the logic for the above within the AcceptCallback() method which you can view by downloading the example projects for this tutorial.

 

Send some test data

Now that we have a connection established, we can send some data to make sure everything is connected up correctly.  We send a test message from within the UDPListener application:

            // Send test data to the remote device
            Send(client, "Hello, this is UDPListener!<EOF>");
            sendDone.WaitOne();
            listView.Items.Add("Message sent to UDPBroadcast");

In a real application this initial message would likely be where you authenticate the connection between the two applications.

 

Wait for responce

Since the UDPBroadcast application is designed to parrot back any message it receives we can immediately wait for a response within the UDPListener application:

            // Receive the response from the remote device
            Receive(client);
            receiveDone.WaitOne();
            listView.Items.Add("Received the following responce from UDPBroadcast: "+response);

 

Close the Connection

Now that we have connected, sent, and received back data from the UDPBroadcast application we can close the TCP connection and release the socket:

            // Release the socket
            client.Shutdown(SocketShutdown.Both);
            client.Close();
            listView.Items.Add("Connection to UDPBroadcast application has been closed.");

 

Final Comments

The above is a very basic example, and as mentioned before error handling and proper authentication is necessary for using this in any real application.  Much of the described logic is encapsulated within the callback methods that can be viewed by downloading the completed example projects linked at the bottom of this article.

I hope this has been helpful to those that have come here to read it. And as always if you have suggestions for improvements to this article, or comments about anything that I’ve done wrong, please leave a comment below.

UDPListenerPart2.zip

UDPBroadcasterPart2.zip

 

References:

As always please refer to my references for further detail.  Much of the code has been compiled from the linked references. For the UDP references see Part 1 of this series.

https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx

UDP Discovery Tutorial – Part 1

I recently had a reason to look into this so I thought I’d post a short basic example of how to use UDP to implement client/server discovery over a local network in C#.  As this is a basic example, I am not going to cover security or negotiation minutia. At least not in these short tutorials. As a note to the reader, all error handling has been omitted for the sake of clarity.

Find the Broadcast IP of your Network

A special “Broadcast Address” must be used when using UDP for the purpose of sending a datagram to all machines connected to a given network.  For example, the typical home network host/gateway of 192.168.0.1 has a broadcast address of 192.168.0.255.  If your network differs from this you can use an IPv4 broadcast address calculator like the one found here http://jodies.de/ipcalc.  We don’t want to have to figure out the broadcast IP by hand every time so we’d like to calculate it programatically.

The below example code shows one possible way of how to calculate the broadcast address for your local network adapter.  Depending on your needs, there is also a special definition for the 255.255.255.255 broadcast address which is the broadcast IP for the 0.0.0.0 network.  This special broadcast address is more limited by definition in that packets sent to it are not forwarded to the routers connecting the local network to other networks.

The below code is a fully encapsulated method to return the broadcast address of the machine that it is running on. The return is a object of the IPAddress type.

        public IPAddress calculateUdpBroadcastAddress()
        {
            //Get the local IP address of the network adapter
            IPHostEntry host;
            host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (IPAddress ip in host.AddressList)
            {
                if (ip.AddressFamily.ToString() == "InterNetwork")
                {
                    localIP = ip;
                }
            }

            //Get the SubnetMask of the Local Network Adapter
            foreach (NetworkInterface adapter in NetworkInterface.GetAllNetworkInterfaces())
            {
                foreach (UnicastIPAddressInformation unicastIPAddressInformation in adapter.GetIPProperties().UnicastAddresses)
                {
                    if (unicastIPAddressInformation.Address.AddressFamily == AddressFamily.InterNetwork)
                    {
                        if (localIP.Equals(unicastIPAddressInformation.Address))
                        {
                            localSubnetMask = unicastIPAddressInformation.IPv4Mask;
                        }
                    }
                }
            }

            //Get the SubnetMask bytes before finding the complement
            IPAddress complimentIP = new IPAddress(localSubnetMask.Address);
            byte[] addressBytes = complimentIP.GetAddressBytes();
            byte[] complimentBytes = new byte[4];

            //Get the compliment of the SubnetMask
            for (int i = 0; i < addressBytes.Length; i++)
            {
                complimentBytes[i] = (byte)~addressBytes[i];
            }

            //bitwise OR the compliment of the Subnet Mask and the host IP
            byte[] localBytes = localIP.GetAddressBytes();
            byte[] broadcastBytes = new byte[4];
            for (int i = 0; i < localBytes.Length; i++)
            {
                broadcastBytes[i] = (byte)(complimentBytes[i] | localBytes[i]);
            }

            //Return the calculated broadcast address
            return new IPAddress(broadcastBytes);
        }

With the above code we can find the broadcast IP that we need to broadcast on to find our clients or server.

Select a Listening/Broadcasting Port

Any free port on both your client and server is acceptable for this purpose. MSDN uses port 11000 for their udp example. Personally I like utilizing ports in the 10k to 11k range for me projects as there is a fair amount of free ports in that range.

The port you’ve selected will be used in the following code example, for this example I am using port 11000.

Code to Implement the Listener

            //Update the UI and listen for a datagram until we get the right one
            bool done = false;
            while (!done)
            {
                byte[] bytes = udpListen();  //Blocking method call until a datagram is received

                //Validate the message
                string udpMessage = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
                string[] udpDatagramParts = udpMessage.Split(' ');
                if (!udpDatagramParts[0].Equals("UDPBroadcasterIP:"))
                {
                    //The UDP message we received is not the right one
                    listView.Items.Add("The received datagram was incorrect ... continue listening");
                }
                else
                {
                    //The udp message is the right one
                    listView.Items.Add("Received a correct datagram ... attempting a TCP connection ... ");
                    //Save the IP for the TCP connection
                    connectionIP = udpDatagramParts[1];
                    done = true;
                }
            }

Note: The third parameter to Console.WriteLine, “Encoding.ASCII…” represents the string value sent over UDP in the datagram packet. This contains the desired negotiation information for a discovery situation, such as the IP address of the client or server you wish to connect to.

The above code is performing a blocking listen operation until a UDP datagram has been received. The UdpListen() method can be seen in its entirety in the available visual studio projects listed at the bottom of this article.

Code to Implement the Broadcaster

            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            //The sendBuf contains the message we are sending to the UDPListener, so here is where the application specific validation
            // information and the TCP connection information will be provided to the listener
            byte[] sendbuf = Encoding.ASCII.GetBytes("UDPBroadcasterIP: " + localIP.ToString());
            IPEndPoint ep = new IPEndPoint(broadcastAddress, udpPort);

            for (int i = 0; i < 100; i++)
            {
                s.SendTo(sendbuf, ep);
                Thread.Sleep(10);
            }

This is a very simple example. The broadcaster is rebroadcasting for a period of time to make sure the Listener receives it. In this example I send the datagram every 10 milliseconds for 1 second. Even after the UDP datagram is sent/received there will need to be some negotiation to ensure a more permanent connection is made between the client and server.

In Part 2 of this tutorial I will implement a TCP connection between the Broadcaster and the Listener.  Once Part 2 is published I will also update the below code projects to show the TCP connection as well.

A full implementation of this tutorial is available for download at the link below. This is still a simplified version of what you will likely need for your project but should be more complete than the above code snippets.

UDPListener.zip

UDPBroadcaster.zip