Friday, April 26, 2013

ADFS : WCF web service

 

Been playing with ADFS and WCF. There’s tons of stuff about the passive scenario but very little useful information about the active one. Actually, that’s not true . There is lots on the active profile – sadly, most of it is rubbish.

I read Dominick’s posts a few times – starting with WIF, ADFS 2 and WCF–Part 1: Overview. There’s six parts. Some of my code comes from there. There’s a link to all the code at the end of Part 2.

This is what I did in VS 2010 / WIF 1.0.

Create a WCF service in WCF – the standard IService1 / Service1.

Add a ViewClaim class:

using System.Runtime.Serialization;

namespace ADFSWcfServiceLibrary
{
[DataContract]
public class ViewClaim
{
[DataMember]
public string ClaimType { get; set; }

[DataMember]
public string Value { get; set; }

[DataMember]
public string Issuer { get; set; }

[DataMember]
public string OriginalIssuer { get; set; }
}
}

The usual contracts:

 [OperationContract]
List<ViewClaim> GetClaims();
public List<ViewClaim> GetClaims()
{
var id = Thread.CurrentPrincipal.Identity as IClaimsIdentity;

return (from c in id.Claims
select new ViewClaim
{
ClaimType = c.ClaimType,
Value = c.Value,
Issuer = c.Issuer,
OriginalIssuer = c.OriginalIssuer
}).ToList();
}


 



Run it up with F5. It starts up the test tool – you’'ll get a null object because there aren’t any claims.


Publish this to IIS 7.5. (IIS needs SSL). Use the file option and stick it somewhere. If you look in the directory where you published it, you’ll see a .svc file. If you navigate to the .svc file via the browser you’ll get the standard:


“You have created a service.


To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:”.

I use IIS 7.5 because Cassini (the internal VS web server) is rubbish with https which ADFS relies on.


Now run FedUtil. Point to the web.config in the directory where you published it and use the .svc address for the website. Use http for the address. Use your ADFS as the existing STS.


At this point, you can’t use the WCF test tool any more. You need to create a client.


What I do now is use something like WinMerge to compare my project with the directory where the project was published.


I copy all the FederationMetadata back and copy the file web.config to the project app.config.


Now I have an updated project.


Add the published web service to ADFS as an RP. You should be able just to point to the metadata using https. Configure some claims.


Now add a command line project to your solution. Make it the Startup Project.


Add the web service as a service reference.

Add something like this to Program.cs

try
{
ServiceClient sc = new ServiceClient();
if (sc.ClientCredentials != null)
{
sc.ClientCredentials.SupportInteractive = false;


sc.ClientCredentials.UserName.UserName = "user";
sc.ClientCredentials.UserName.Password = "password";
}


ViewClaim[] vc = sc.GetClaims();


foreach (var viewClaim in vc)
{
Console.WriteLine(viewClaim.ClaimType = " " + viewClaim.Value);
}
}

catch (Exception ex)
{
Console.WriteLine(ex.Message + " Inner = " + ex.InnerException);
}


Console.ReadKey();


The sc.ClientCredentials.SupportInteractive = false; is to get rid of CardSpace.


Look at the app.config for the command line program. You’ll see a whole lot of commented out services e.g.


<issuedTokenParameters>
    <issuer address=https://xxx/adfs/services/trust/2005/usernamemixed bindingConfiguration=https://xxx/adfs/services/trust/2005/usernamemixed
    binding="wsHttpBinding" />


By default, it’s set up to use services/trust/2005/certificatemixed under the WS2007FederationHttpBinding_IService binding.


Choose the binding you want and overwrite the certificatemixed entry with the one you want.


For the above code, I selected services/trust/2005/usernamemixed.


Run it – you should get the claims for the user you hard coded in sc.ClientCredentials.


Enjoy!

No comments: