1
votes

My ASP.NET MVC application is using WIF 3.5 and Azure ACS for Federated Authentication with Google, Facebook, etc. During sign up, after user's authenticated with IdP, we store custom user data in our database.

At the moment, it allows one user account to be associated with one identity provider, but I have a requirement to add support to several identity providers for one account (.i.e. user can add Google, Facebook, etc to his account and he can use either of these IdP to log in to our site). To add additional IdP to his account, the user needs to log in to main IdP first. The sequences are like this:

  • User goes to login page, choose one IdP (e.g. Google), log in in Google, Azure ACS redirects back to our site after authentication
  • In profile page, user chooses to add additional IdP, he's redirected to page to choose IdP
  • He clicks on another IdP (e.g. Facebook), log in in Facebook, Azure ACS redirects back to our site (I can see all the correct claims from Facebook that Azure ACS passed back to our site)
  • The problem is I'm not sure how to extract these Facebook claims. If I use

    HttpContext.Current.User.Identity as Microsoft.IdentityModel.Claims.IClaimsIdentity

It returns Google (current IdP that user's logging in) claims

1

1 Answers

1
votes

Finally I need to read the response and parse it into claims manually, here's how I did it just for reference:

//Response from Azure ACS is stored in wresult parameter
string samlResponse = Request.Params["wresult"];

var xmlTextReader = new XmlTextReader(new StringReader(samlResponse));

//Only interested in Assertion section of the response
xmlTextReader.ReadToFollowing("Assertion", "urn:oasis:names:tc:SAML:2.0:assertion");

SecurityTokenHandlerCollection handlers = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;

// read the token
var securityToken = handlers.ReadToken(xmlTextReader);

// validate the token and create the identity collection
var claimsIdentityCollection = handlers.ValidateToken(securityToken);

// create ClaimsPrincipal
var claimsPrincipal = new ClaimsPrincipal(claimsIdentityCollection); 

Although it works, I'm not sure whether this is the best way, so I still leave the question open for anyone who has better answer