|
A new CTP was released for .NET Services in March and as I update my Access Control Service (ACS) samples to reflect changes I thought I might post the relevant changes here to save all 5 of you devoted blog readers some time. First off, the ACS has a new certificate, which means your web sites and WCF services that rely on ACS tokens must update their configuration to reflect the new thumbprint. The old thumbprint was 416e6fa5d982b096931fbf42c4a3dcd608856c95, and the new thumbprint is 6DE1689A739D548A5690DBC3894B953EF6123D93. So, if you provide trusted issuers in configuration, your <microsoft.identityModel> configuration must be updated to reflect this: <microsoft.identityModel> <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry"> <trustedIssuers> <add name=http://{yoursolutionname}.accesscontrol.windows.net thumbprint="6DE1689A739D548A5690DBC3894B953EF6123D93"/> </trustedIssuers> </issuerNameRegistry> ...more settings </microsoft.identityModel> If your trusted issuers are handled with a custom IssuerNameRegistry component, you might do something like this: <issuerNameRegistry type="TrustedIssuerNameRegistry"/> and the component: public class TrustedIssuerNameRegistry : IssuerNameRegistry { public override string GetIssuerName(SecurityToken securityToken) { X509SecurityToken x509Token = securityToken as X509SecurityToken; if (x509Token != null) { if (String.Equals(x509Token.Certificate.Thumbprint, "6DE1689A739D548A5690DBC3894B953EF6123D93")) { return x509Token.Certificate.SubjectName.Name; } } throw new SecurityTokenException("Untrusted issuer."); } } Another change is the issuer URI format for your hosted STS. What used to be: http://accesscontrol.windows.net/{yoursolutionname} is now http://{yoursolutionname}.accesscontrol.windows.net. Although this may not be an exhaustive list since likely every place you use your solution URI you will have to update this...here are some things I had to update related to the ACS: 1. Declarative trusted issuer entries (this value is used when the ClaimsPrincipal is generated, as the issuer for those claims): <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry"> <trustedIssuers> <add name=http://{yoursolutionname}.accesscontrol.windows.net thumbprint="6DE1689A739D548A5690DBC3894B953EF6123D93"/> </trustedIssuers> </issuerNameRegistry> 2. Addressing your passive STS URI, which in this example is the URI for passive federation with Live ID (I am told this will later change to Federation.aspx for all passive federation URI): <microsoft.identityModel> <federatedAuthentication enabled="true"> <wsFederation passiveRedirectEnabled="true" issuer=https://{yoursolutionname}.accesscontrol.windows.net/passivests/LiveFederation.aspx realm="http://localhost/PassiveACSWebSite" reply="http://localhost/PassiveACSWebSite/Default.aspx" ></wsFederation> </federatedAuthentication> </microsoft.identityModel> 3. I have a custom Saml11SecurityTokenHandler that validates that any ACS tokens are from MY solution and not other solutions signed with the same private key. You do this by checking the token's Issuer property as shown in my custom type. Below is the configuration to add the custom token handler and the implementation. <microsoft.identityModel> <securityTokenHandlers> <remove type="Microsoft.IdentityModel.Tokens.Saml11.Saml11SecurityTokenHandler, Microsoft.IdentityModel, Version=0.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> <add type="SecurityExtensions.ACSSamlTokenHandler, SecurityExtensions"/> </securityTokenHandlers> </microsoft.identityModel> public class ACSSamlTokenHandler: Saml11SecurityTokenHandler { private string Issuer { get; set; } public ACSSamlTokenHandler() : this(new SamlSecurityTokenRequirement()) { } public ACSSamlTokenHandler(SamlSecurityTokenRequirement samlSecurityTokenRequirement): base(samlSecurityTokenRequirement) { } public ACSSamlTokenHandler(XmlElement customConfiguration): base(customConfiguration) { } private void Initialize() { if (MicrosoftIdentityModelSection.Current != null) { IssuerNameRegistryElement trustedIssuersConfig = MicrosoftIdentityModelSection.Current.IssuerNameRegistry; string s = trustedIssuersConfig.ElementAsXml.ToString(); } } public override Microsoft.IdentityModel.Claims.ClaimsIdentityCollection ValidateToken(System.IdentityModel.Tokens.SecurityToken token) { if (token == null) throw new ArgumentNullException("token"); SamlSecurityToken samlToken = token as SamlSecurityToken; if (samlToken == null) throw new ArgumentException(string.Format("Argument cannot be null: {0}", "token")); if (!samlToken.Assertion.Issuer.Contains("http://{yoursolutionname}.accesscontrol.windows.net")) { throw new SecurityTokenException(string.Format("The token issuer {0} is not expected.", samlToken.Assertion.Issuer)); } return base.ValidateToken(token); } } So if you are updating ACS samples, this may come in handy. Cheers!
|