Reputation: 4448
I am supporting a solution which acts as an IDP and STS in one. Think of it as a MVC app with simple authentication against locally stored profiles. I would like to put a link on one of my pages that, when clicked, builds a SAML payload and ships it through ACS and then on to a partner's site (which in turn uses WIF to read incoming SAML2 payloads from ACS). I don't want to show another login page (such as ACS's home realm discovery page) during the journey because by the time they are clicking my link they have already been authenticated. I just want to send claims to the destination Relying Party url and I want to pass through ACS on the way there.
ACS supports something close to this with "custom login pages". You can download an HTML page that you would presumably customize and host at an IDP and have users click through when heading to the Relying Party. The HTML file sources an ACS-hosted Javascript file (IdentityProviders.js) that provides a LoginUrl as one of the JSON parameters it sucks down. LoginUrl contains a wctx parameter (that looks to be encrypted or something) that I copy and then use like this:
private SignInRequestMessage GetSignInRequestMessage() {
SignInRequestMessage aMessage = new SignInRequestMessage(new Uri("https://something.accesscontrol.windows.net/"), "http://accesscontrol.windows.net/");
aMessage.Reply = "http://locohost:65447/Home/SAML";
aMessage.Realm = "https://something.accesscontrol.windows.net/v2/wsfederation";
aMessage.Context = THE_WCTX_PARAM_I_GRABBED;
return aMessage;
}
The end result is that my link click carries me all the way through to the landing page within the Relying Party (http://locohost:65447/Home/SAML
in this case), passing through ACS which allows for claim mapping and filtering and signature and encryption support.
I notice that when I change the Return URL in the corresponding Relying Party the wctx value is changed just slightly. My guess is that it contains the realm and return urls, though I don't understand why it needs that because I can provide those data bits programmatically as seen above. My goal is to be able to build that wctx parameter programmatically without having to grab a magic string or make an HTTP call at runtime. Can anyone offer advice?
Edit: Here is an image that outlines the desired process. Accounts are stored at the partner, not in Azure Active Directory
And here is more pseudo code that shows how I'm driving the form post to ACS with the wctx parameter
public async Task<string> DoACSSAMLPost(List<Claim> aClaimsList, ClaimsPrincipal aPrincipal, string aTokenServiceUrl) {
// SignInRequestMessage is what is sent to ACS (see code sample above)
SignInRequestMessage aSignInRequestMessage = await GetSignInRequestMessage();
// sign request with private key. Public key has been installed in ACS.
X509SigningCredentials aSigningCredentials = new X509SigningCredentials(theSigningCertificate);
// configuration allows the token service to sign request and identifies itself as the token service
SecurityTokenServiceConfiguration aConfig = new SecurityTokenServiceConfiguration(aTokenServiceUrl, aSigningCredentials);
CustomSecurityTokenService aSecurityTokenService = new CustomSecurityTokenService(aConfig, aClaimsList);
// Message is generated by the System.IdentityModel plumbing
SignInResponseMessage aResponseMessage = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(aSignInRequestMessage, aPrincipal, aSecurityTokenService);
// and the form post HTML is returned
return aResponseMessage.WriteFormPost();
}
I can grab this param from IdentityProvider.js and build this all on the fly, but I'd like to understand a) if my approach makes sense and is the 'proper' way to go about this and b) if there is a better way to get that wctx param (or if I can cache it locally if I don't change the Return URL in the Relying Party config in ACS
Upvotes: 4
Views: 1181
Reputation: 7394
Not sure if I grok 100% the intent. Are you trying to skip the HRD, so the authentication goes straight to the IdP of choice? If that's the case, you can simply inject "?whr=issuername" in your request to ACS. You can even send it in the original request to the RP, and extract & pass-through it in the redirectingtoidentityprovider event. You should not need to mess with the wctx parameter as its goal is to maintain state across various redirects - but it does not look like that's the goal here. HTH V.
Upvotes: 2