Monday, April 29, 2013

WCF : Different flavours of ADFS


Playing around with the active profile in ADFS – quite a different beast to the passive one!

There are essentially two WCF flavours viz.

1) A simple WCF connection protected by ADFS with hard-coded credentials e.g.

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

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

In this case, the claim will always have the same information; the configured attributes for the hard coded user.

2) Using the WCF web service in a an “ActAs” scenario.

There are examples of this in the Training Kit and the WIF SDK (note we are talking WIF 1.0 here). These invariably use the CreateChannelActingAs method.

Dominick has a slightly different approach – refer Requesting Delegation (ActAs) Tokens using WSTrustChannel (as opposed to Configuration Madness).

Here the WCF claim will have the attributes of the logged-in user i.e.

The application is protected by ADFS using the passive profile. The user logins to the application in the normal manner. The application calls a WCF web service using the active profile using ActAs.

This possibly offers another level of security.

Assume the web service is:

DoSomething (string userName).

With the first flavour, you have to pass the user name since the claim is of no use. However, with the second flavour, you can simply call:

DoSomething ()

and get the userName from the claim.

Of course, that does somewhat muddy the water if you want to call the web service from something like Java but that’s another story.

Enjoy!

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!

Monday, April 15, 2013

ADFS : SAML configuration parameters

 

Having done this too many times and pulled out too much hair in frustration …

When you are asked to configure SAML access to application xxx owned by company yyy via ADFS v2.0, you need the following information.

If their SAML stack is a well-known product e.g. Ping, OpenAM, Oracle, simpleSAMLPHP … your life is suddenly orders of magnitude easier. You can follow the normal metadata (idp.xml, sp.xml) exchange.

If the words “home brewed” / “custom” / “proprietary” etc. are used, prepare for a load of pain.

The questions:

SAML 1.1 or SAML 2.0?

IdP or SP initiated?

HTTP POST, Redirect or Artefact?

What SAML stack implementation do you use?

Is there an installation document?

If no document, what is …

  • SP entity ID?
  • https SAML endpoint?
  • SAML subject NameID format e.g. UPN, email?
  • What attribute do you expect to use for NameID e.g. UPN, email?
  • What AD attribute is used to populate this?

Do you have the normal SAML metadata exchange protocol file?

Is the SP token required to be encrypted? Certificate?

Are AuthnRequests and Assertions expected to be signed? Certificate?

Single Logout (SLO) required?

SHA 1 or SHA 256?

The above can be configured via the normal ADFS screens.

There are others that require the AD FS 2.0 Cmdlets in Windows PowerShell. These are normally figured out by trial and error. In my experience, asking these types of questions just results in blank looks. You have to “suck it and see” as they say in Kiwiland!

e.g. if ADFS is the RP, then SamlResponseSignature may need to be changed.

This specifies the response signatures that the relying party expects. Valid values are AssertionOnly, MessageAndAssertion, and MessageOnly.

The default is AssertionOnly.

Enjoy.

Tuesday, April 09, 2013

AD : Using a filter for UAC bits and null attributes

 

There’s a lot of functionality in the AD API’s and there are neat API’s to enable / disable users but what if you want to search for them e.g. find all users in an OU that are currently disabled.

You could just search for all the users in an OU and then enumerate through all of them where:

user.Enabled = false;

but that’s a pain.

Enter RFC2254.

Or look here: Search Filter Syntax

What you will find is the matching rule OIDs.

e.g.

1.2.840.113556.1.4.803 = A match is found only if all bits from the attribute match the value. This rule is equivalent to a bitwise AND operator.

UAC is described here: Attributes for AD Users : userAccountControl.

Note that: Const ADS_UF_ACCOUNT_DISABLE = 2.

So now that we have laid the framework, back to the original question.

To search for disabled users, the filter would be:

(userAccountControl:1.2.840.113556.1.4.803:=2)

One of the problems with AD is “null” attributes i.e. attributes that in ADUC display as “not set”.

To search for these e.g. for email, use the filter:

(!(email=*))

* is the AD wildcard so this searches for users who don’t have an email address.

So to search for disabled users who don’t currently have an email address, use:

(&(userAccountControl:1.2.840.113556.1.4.803:=2)(!(email=*)))

This stuff does your head in!

Enjoy!

Wednesday, April 03, 2013

ADFS : ID4175: The issuer of the security token was not recognized by the IssuerNameRegistry

 

The full error is:

ID4175: The issuer of the security token was not recognized by the IssuerNameRegistry. To accept security tokens from this issuer, configure the IssuerNameRegistry to return a valid name for this issuer.

So there I was happily using my claims-enabled application until one fine autumn morning – WHAM – I get the above error.

WTF?

This error means (to quote Common Windows Identity Foundation WS-Federation Exceptions Explained) that:

“Security tokens are signed by the issuer (the IP-STS). This issuer is validated by the relying party so that the RP can be sure the tokens have been issued from a trusted source. The relying party’s WIF configuration contains an <issuerNameRegistry> element where the settings for the issuer’s signature are stored. This exception means that the configuration contained under the issuer name registry does not match the signature of the security token.”

Then I noticed that my ADFS has certificate rollover enabled and yes – you guessed it – my certificates had rolled over over the weekend.

The section in the web.config looks like:

<issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<trustedIssuers>
<add thumbprint="xxx" name="http://yyy/adfs/services/trust"/>
</trustedIssuers>
</issuerNameRegistry>



So you need to get the thumbprint of the new ADFS token-signing primary certificate and update the web-config with it.



Enjoy!

Monday, March 25, 2013

WIF : Claims Aware Web Service exception

 

This is with the “Identity and Access Tool” / VS 2012.

When you run the sample and hit Enter, get:

Security negotiation failed because the remote party did not send back a reply in a timely manner. This may be because the underlying transport connection was aborted.

Server stack trace:
   at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)

When you click on ClaimsAwareWebService.svc in the Directory Listing, you get:

The service cannot be activated because it does not support ASP.NET compatibility. ASP.NET compatibility is enabled for this application. Turn off ASP.NET compatibility mode in the web.config or add the AspNetCompatibilityRequirements attribute to the service type with RequirementsMode setting as 'Allowed' or 'Required'.

So in the web.config, set this to “false”:

serviceHostingEnvironment aspNetCompatibilityEnabled="true"

All good!

Enjoy!

WIF : Identity and Access Tool

 

This happened a while back but there still seems to be confusion.

This only runs on VS 2012.

Also there have been a lot of changes from WIF 1.0 (3.5) to 4.5. The templates, custom STS, FedUtil etc. are no more. Goodbye to the FederatedPassiveSignInControl and FederatedPassiveSignInStatus controls.

Good summary: What's New in Windows Identity Foundation 4.5

Overview: Windows Identity Foundation Tools for Visual Studio 2012 RTM

Details: Windows Identity Foundation in the .NET Framework 4.5 Beta: Tools, Samples, Claims Everywhere

The Identity Training Kit is no more. Examples are spread across separate samples. The full list is in the third link above.

Enjoy!

Friday, March 22, 2013

ADFS: Certificate Sharing Container

 

If you are wondering where this is in AD (and you are not alone in asking that question), it’s to be found under:

Program Data / Microsoft / ADFS

And I believe that this is only used when you enable AutoRollover.

Enjoy!

Misc: .NET 4.5 / Windows Identity Foundation should include SAMLP support

 

Damn fine idea – 100% agree.

We need full SAML support – ala the old WIF 3.5 CTP.

Vote here: .NET 4.5 / Windows Identity Foundation should include SAMLP support.

And yes – I voted.

Enjoy!

Wednesday, March 20, 2013

Rant: If you are already in a hole ..

 

Well – YAC – Yet Another Category!

The actual quote is “If you are already in a hole, stop digging”.

I see this every day. We go to a customer, talk about claims-enabled applications. talk about WIF and ADFS, SAML, SSO etc. and the customer is happy.

Then they ask “Actually we’ve got this open-source gateway product that we use. Can ADFS work with it?”. This gateway product is a “sort-of” AM ala TMG, UAG, OpenAM etc.

The correct response is “Sorry, we can’t be experts in every product in the known universe. You probably need to go back to the vendor. We might be able to help but it’s on a ‘best endeavour’ basis – no guarantees”.

The incorrect response is “OK no problem, we’ll check it out”. The customer interprets this as “OK – now it’s your problem”.

Two months later – one pissed-off customer – the guy who wrote the product is somewhere in Siberia – doesn’t answer emails – and we keep on digging the hole deeper.

Tell the customer up front – we are IDENTITY people NOT network people. If they want to get pissed off, well and good – they can find someone else to sort it out!

Enjoy!

Thursday, March 14, 2013

ADFS : Using the SAML NameID to map IdP / SP claims

 

Imagine two companies: Fabrikam and Contuso. Fabrikam has a SaaS application in the cloud that Contuso wants to use. Fabrikam supports SAML authentication and is a SP. Contuso uses ADFS as an IP.

So all the pieces are in place and it should just work no problem. Dream on.

There needs to be a “primary key” that links the two companies together for a session.

Assume Contuso has an employee – the ubiquitous Joe Bloggs - and Joe needs access to the application.

So Contuso has to send Fabrikam a table of users – among which is Joe Bloggs. This table can be sent as XML, xls, text or whatever.

Fabrikam imports these users into the Contuso section of their database.

They also have to agree on what attribute of each user is the primary key e.g. sAMAcountName, email address, AD GUID …

Assume they choose email – this is the NameID.

So when Fabrikam get an AuthNResponse from Contuso, they extract the NameID and use that as the key into their table.

There is one further complication. The SAML spec. allows the NameID to be sent in a number of formats e.g. Unspecified, Email, X509 Subject Name…

This is important. If one side expects the email format e.g. joe.bloggs@contuso.com and the other side is expecting X509 Subject Name e.g. CN=joebloggs@contuso.com, OU=Dev,O=Contuso,C=NZ, you can predict that there will be problems.

So they both have to agree. Assume they choose email address.

To configure this in ADFS:

Configure the email address as the normal “Send LDAP Attributes as Claims”.

Then configure a “Transform an Incoming Claim” rule which takes “Incoming Claim Type” of email and maps it to “Outgoing Claim Type” of NameID which has an “Outgoing NameID Format” of email.

Problem solved!

Enjoy!

Friday, February 22, 2013

ADFS : Getting the domain name as a claim

 

There are a number of ways of doing this.

You can get the domain name via ADFS : Sending groups as claims.

Also there was a thread on the forum that I contributed to viz. Custom Claim Rules - How to write domain name into outgoing claim?.

As I said, you could map msDS-PrincipalName to http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname and then use some regex to split out the domain name.

But further down:

“You don't need to use any mapping/edit LDAP rules and stuff. The windowsaccountname claim is there by default after installing adfs.

Just check it for yourself:

-Open the ADFS 2 console

-Open Trust Relationships

-Open Claims Provider Trusts

-Right mouse click on the AD trust and click "Edit claim rules"

-Note the first rule: Pass through all Windows account name claims.

You can just use the "Pass through or filter an incoming claim option" in the relying party claims configuration and select the windows account name or use a custom transform rule to transform it to the desired outgoing claim.”

Very neat!

Enjoy!