Azure Access Control Services: Creating a Custom Identity Provider
Azure Access Control Services (ACS) allows you to secure an application (i.e. Relying Party, RP), by federating to a variety of Identity Providers (IdPs). Once you set your Relying Party application to use federated security with Azure ACS, you can chose combinations of Facebook, Windows Live ID, Google and Yahoo to secure your application. You can also use a WS-Federation IdP. This is typically Active Directory Federation Services 2.0 (ADFS 2.0), but you can also write your own IdP.
In this post I am going to walk you through the process of creating your own IdP (based on one of the Windows Identity Foundation Visual Studio 2010 templates). I will configure ACS to use this, and build a Relying Party web application that is secured passively by ACS (in turn using my IdP).
Disclaimer: This walkthrough talks you through the key parts of creating a custom Identity Provider (IdP), but there are additional steps you would want to follow in order to build this for a production environment (such as encrypting tokens, using certificates signed by an appropriate certificate authority and restricting the custom Identity Provider to only allow it to be referenced from Azure ACS).
Prerequisites
To create and configure your custom IdP you will need…
- An active Azure subscription
- Visual Studio 2010 (I have not yet tried this with VS 2012)
- IIS
- WIF SDK (WindowsIdentityFoundation-SDK-4.0.msi) https://www.microsoft.com/en-us/download/details.aspx?id=4451
- Visual Studio 2010 Azure SDK https://www.windowsazure.com/en-us/develop/downloads/
In my walkthrough, I will create two web applications on my local machine, one for my Identity Provider, and one for my test Relying Party.
Local URLs used:
- Custom IdP: https://sts.ukmcs.dev
- Relying Party: https://rp.ukmcs.dev
Step 1: Create a self-signed certificate
When building our IdP, we need to sign the security token that it will generate. We will also run our custom IdP over SSL for enhanced security. To do this in a development scenario, we will use MakeCert.exe to generate a self-signed certificate. As mentioned above, on a production environment you should obtain a certificate signed by a trusted certificate authority.
Generating a self-signed certificate
To generate a self-signed cert, first open a Visual Studio Command Prompt (Start –> Microsoft Visual Studio 2010 –> Visual Studio Tools –> Visual Studio Command Prompt (2010)).
Run the following command (replacing the *.mcsuk.dev with the destination url of your IdentityProvider IdP).
MakeCert.exe -r -pe -n "CN=*.mcsuk.dev" -sky exchange -sr localmachine -ss my -len 2048 -e 10/25/2013
Note: in this example, I generated a wildcard certificate. The reason for creating a wildcard cert is that this allows you to enter a host header in iis (otherwise, all HTTPS IIS requests on your local machine would need to use this certificate. NB. Make sure your wildcart cert contains at least two segments (you will receive a certificate error when you browse to your site otherwise, indicating that your website does not match the certificate.)
Locate your certificate and copy
When building for development purposes on your local machine, if you browse to a site over https (that uses your self-signed certificate), you may experience a certificate error as follows:
To avoid such errors, locate and copy the certificate to “Trusted Root Certification Authorities\Certificate”. [Note, if you’ve got a certificate signed by a trusted root authority, as would be required for a production environment, these steps are not required]
- Click start –> run and type “mmc” (then enter).
- Within the console select the file menu and click on Add / Remove snap-ins.
- Select the certificates add-in then press the add button
- Select the “computer account” radio button and click next
- Leave “local computer” checked and click finish.
- Click ok to close the dialog. “Certificates (Local Computer)” will now be added to the left hand pane of your console.
- Expand the “Certificates (Local Computer)” node –> personal –> certificates. You should see your newly created certificate.
- Copy the certificate
- Expand the “Certificates (Local Computer)” node –> Trusted Root Certificate Authorities –> certificates
- Paste your certificate
Export your certificate’s public key (base 64 encoded)
The next step is to export your certificate as a Cer file, in order to obtain the Base-64 encoded public key (this is used by your IdP to sign the tokens that it issues). To do this…
Your certificates public key is used in the FederationMetadata.xml file of the Identity Provider that we will build. This is so that Relying Party applications that are secured using our Identity Provider (in this case Azure ACS) can verify that tokens are signed via a trusted authority. We obtain the Base-64 encoded public key (as a Cer file) for this.
- Right click on the certificate you’ve just created and select “All Tasks” then “Export”
- When the dialog opens, click next
- Select “No, do not export the private key”
- When selecting the export format, choose Base-64 Encoded X.509 (.CER)
- Choose a filename
- Click next and finish
Step 2: Building your custom Identity Provider (IdP)
Adding hosts file entries
So we can easily develop and test our IdP, add the following entry to your host file (changing to reflect the url you intend to use on your local machine for your IdP and RP). Your host file should exist at C:\Windows\System32\Drivers\etc\hosts. Note, if you plan to host production sites publically, you must instead ensure that the DNS for these is correctly set up.
127.0.0.1 sts.mcsuk.dev
127.0.0.1 rp.mcsuk.dev
Create a website to host our IdP
Next we need to create a website to host our IdP. In IIS Manager, right click on the Sites node, and select “Add Web Site”, with the following settings (replacing the URLs as appropriate).
Whilst still in IIS Manager, navigate to the app pool (just created) and select “Advanced Settings”. Ensure that the .NET Framework version is set to 4.0 and Load User Profile is set to true.
Also, change the Identity in the Process Model section to LocalSystem. This is so that the application pool can access the private key of our certificate generated in step one. On a production environment, you would have a specific named account for this.
Navigate back to the newly created website in IIS Manager and click the “Bindings” link. Add a binding as follows (using your newly created certificate).
Creating the IdP
Now to finally create the IdP. In Visual Studio 2010, create a new website using the WIF Visual Studio Template “ASP.NET Secure Token Service Website”.
Optional: Once the solution template has loaded, you can directly launch the site to check that everything so-far has gone to plan. You should see the following, without any certificate errors.
Code Changes
We now need to make a few code changes to get our IdP ready for use by Azure ACS. The WIF Visual Studio Template “ASP.NET Secure Token Service Website” actually provides the majority of the functionality required for this example (albeit rather contrived).
In the AppCode folder, open the CustomSecurityTokenService.cs file and edit the GetOutputClaimsIdentity method. We will simply add an additional custom claim here as follows (to demonstrate how to pass additional information via Azure):
outputIdentity.Claims.Add(new Claim("https://sts.mcsuk.dev/claims/age", "33"));
IMPORTANT: Also in the CustomSecurityTokenService.cs file, change the setting of scope.ReplyToAddress = scope.AppliesToAddress; in the GetScope method. If this is not changed, the incorrect URL will be used when the browser is bounced from our custom Identity Provider to Windows Azure.
scope.ReplyToAddress =
request.ReplyTo
;
On my dev environment, because I’m a using a self-signed certificate, I need to make a couple of changes to make the STS look in the Root Trust store. Firstly, in the CustomSecurityTokenService.cs file I changed the EncryptingCredentials to use StoreName.Root (in the GetScope method).
scope.EncryptingCredentials = new X509EncryptingCredentials( CertificateUtil.GetCertificate(
StoreName.Root
, StoreLocation.LocalMachine, encryptingCertificateName ) );
In the CustomSecurityTokenServiceConfiguration.cs file, I also changed the constructor to also use StoreName.Root
public CustomSecurityTokenServiceConfiguration()
: base( WebConfigurationManager.AppSettings[Common.IssuerName],
new X509SigningCredentials( CertificateUtil.GetCertificate(
StoreName.Root
, StoreLocation.LocalMachine,
WebConfigurationManager.AppSettings[Common.SigningCertificateName] ) ) )
{
this.SecurityTokenService = typeof( CustomSecurityTokenService );
}
Configuration Changes: FederationMetadata.xml
We now need to make changes to the FederationMetadata\2007-06\FederationMetadata.xml file. Format the code (to do this, I select all the xml, copy it, cut and repaste. Visual Studio should format accordingly).
- When generated from WIF template, the FederationMetadata.xml file has a section named “ds:Signature”. This is to digitally sign the xml to protect from tampering. Azure ACS does not require this section, so we can remove it. Note in a production scenario you would want to ensure that the xml file is resigned.
- Note the value of entityID. In my example it is https://sts.mcsuk.dev/. Later, we will need to modify an app setting in the web.config later to match this value. This is important, I experienced errors before these matched.
- Confirm the EndPoint references. These should point to your STS (i.e. https://sts.mcsuk.dev).
- Update the X509certificate to your base 64 encoded .cer public key (as discussed in the above step “Export your certificate’s public key (base 64 encoded)”).
- To do this, open your previously generated Cer file in Notepad.
- Get everything between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- onto one line
- Replace the previous public key in the FederationMetadata.xml with this line from the .cer file.
- Add the additional claim type that we created above to the ClaimTypesOffered section. This is required so Azure ACS can relay the claim.
<auth:ClaimType Uri="https://sts.mcsuk.dev/claims/age" Optional="true" xmlns:auth="https://docs.oasis-open.org/wsfed/authorization/200706">
<auth:DisplayName>Age</auth:DisplayName>
<auth:Description>The age of the subject.</auth:Description>
</auth:ClaimType>
Configuration Changes: Web.Config
Update the appSettings in the web.config. Note that the IssuerName must match the EnitityId in the FederationMetadata.xml file.
<appSettings>
<add key="IssuerName" value="https://sts.mcsuk.dev/"/>
<add key="SigningCertificateName" value="CN=*.mcsuk.dev"/>
<add key="EncryptingCertificateName" value=""/>
</appSettings>
Build the solution.
Step 3: Configuring Azure ACS to use our IdP
To configure Azure to use our STS, you must create a namespace and enable ACS.
- Navigate to https://windows.azure.com/. Select Service Bus, Access Control and Caching.
- Click “Access Control”.
- If required (i.e. if you don’t have an ACS instance set up), do the following:
- Click “New Service Namespace”
Adding the custom IdP
Once created, click into your ACS namespace.
Select Identity Providers and then click “add”
Add a WS-Federation identity provider and click next
Fill in the Identity Provider settings. Note that as your web application (STS) is not visible to Azure, you need to upload your FederationMetadata.xml file from your website as a file from your local machine.
Click save. Your IdP is now registered with Azure.
Add a Relying Party Application
Now we need to register our Relying Party (i.e. our test app against ACS). For this, we just need the local url of where the app will run (i.e. https://rp.mcsuk.dev)
Click the relying party applications link. Fill in the following
- Name: rp.mcsuk.dev
- Enter settings manually
- Realm: https://rp.mcsuk.dev/
- Return Url: https://rp.mcsuk.dev/
- Error Page: (not required)
- Token format: SAML 2.0
- Token Encryption Policy: None
- Token Lifetime: 600
- Identity Providers: MCSUKTestIDP, Google, LiveId etc (make sure to include MCSUKTestIDP)
- Create New Rule Group is checked
- Leave token signing settings as-is. (use service namespace certificate)
Click save.
Setup Rule Group for your Relying Party
This defines the claims that could be passed to the client (depending on which identity provider is selected).
- Click “Rule Groups”
- Select your newly created rule group (e.g. Default Rule Group for rp.mcsuk.dev)
- Click the “Generate” link
- Ensure all checkboxes are select (for each IDP) and click “generate”
- then save to use all rules from IDPs.
Depending on what IdPs you have used, you should see the following
Obtaining the WS-Federation Metadata URL.
Finally, click on the application integration tab and get the WS-Federation Metadata url. You will need this to create a Relying Party.
Step 4: Creating a Relying Party secured to use Azure ACS
To test our IdP, we need to create a new website in IIS as follows (replacing the site url as appropriate).
Navigate to the app pool (just created) and select “Advanced Settings”. Ensure that the .NET Framework version is set to 4.0 and Load User Profile is set to true.
Creating the Relying Party in Visual Studio
In Visual Studio, create a new Claims Aware ASP.NET Web Site at the website just created in IIS.
Once create, in the solution explorer right click on the website and select “Add STS Reference” Walk through the subsequent dialog as follows…
Click next, you will get a warning “ID1007: The application is not hosted on a secure https connection.” As this is not production code, click yes to proceed.
On the next screen, specify to use and existing STS, and paste the FederationMetadata.xml url obtained from ACS.
Click next,
As we are creating a demo, it is safe to disable certificate chain validation. Click next.
We will also not encrypt tokens. On a production environment, you should do this, as well as running the site over https.
Click ok on the confirm screen – note that it does not show all the claims potentially passed through from Identity Providers
Confirm the final screen and click finish
Step 5: Testing
Phew – a lot of steps. The final stage is to test. Launch the relying party website. You should be taken to Azure ACS presenting a list of identity providers.
Select our identity provider (MCSUKTestIDP). Click submit to login.
If it all works, you should get the following. Note the identity provider claim issues by ACS refers to https://sts.mcsuk.dev. Also note that our additional claim (age) is shown.
Phew, that was a lot of steps. I hope it was useful!
Written by Rob Nowik
Footnote: Running IdP and RP in Azure
Note I have tested running the above on Azure. I obtained fully signed certificates in order to do this. Unfortunately, you cannot use the above Visual Studio templates directly when creating a Windows Azure Cloud Service project, but you can copy the code into an ASP.NET Web Role Azure Cloud Service. Note that you must ensure that your certificates are published to Azure.
Comments
Anonymous
March 19, 2013
Rob, great article. I even read it twice :)Anonymous
April 02, 2014
I guess its Azure Access Control Services at the start and not Azure Accenture Control Services :)Anonymous
September 24, 2014
This is just what i need, but for 2014. There is no chance on installing WIF or WIF SDK on windows 8.1 and can't get hold of the template for IdP you used. Can you please give me some guidelines on how to do this today? or better, if you still have it, can you send me the code?. on twitter @davidlaym or email at the same username but on hotmail. Thanks.