4

I'm evaluating the Kentor auth services (the OWIN version of it) to authenticate users using SAML. Now I would like to pass an additional claim to the service. Together with the samples there I was able to send the request to the service and debug it.

I made a custom claimsAuthenticationManager and there I can see the additional claim arriving at the auth service. But later on (in the Kendor examples there is a the view home/index listing all the claims) this claim is not available anymore. Does anyone have an idea what i'm doing wrong?

Thanks a lot!

tschuege
  • 761
  • 1
  • 8
  • 20
  • I need some more info to be able to help: 1. Are you sending the additional claim from the Idp? In that case, as an extra attribute or as a separate assertion? 2. Can you show the code of your `ClaimsAuthenticationManager`? – Anders Abel Nov 20 '14 at 14:34
  • Hello @AndersAbel thanks for your help. 1. Yes, i'm sending it from the ldb. I'm using your code and as far as i saw its added to the existing assertion (ClaimsIdentityExtensions.ToSaml2Assertion) 2. The ClaimsAuthenticationManager does not do anything - i just created it to check if all the claims are arriving there - which is the case. Having looked at it longer time I think the problem is more located around the ApplicationUserManager or ApplicationUser where its lost during tranformation into a "proper asp user"... – tschuege Nov 20 '14 at 16:16

1 Answers1

5

When using AuthServices (or any external login) together with ASP.NET Identity, the incoming claims are only used for looking up the ASP.NET Identity user in the database. Then incoming user is then discarded completely and the user from ASP.NET Identity is loaded and used

In the default MVC5 template, the switch from the external identity to the ASP.NET Identity is done in AccountController.ExternalLoginCallback(). To keep the incoming information you have to adjust this method. There are two options.

1. Update stored user in ExternalLoginCallback()

// Sign in the user with this external login provider if the user already has a login
var user = await UserManager.FindAsync(loginInfo.Login);
if (user != null)
{
  // Update user with info from external identity and save.
  user.GivenName = loginInfo.ExternalIdentity.FindFirst(ClaimTypes.GivenName).Value;
  await UserManager.UpdateAsync(user);

  await SignInAsync(user, isPersistent: false);
  return RedirectToLocal(returnUrl);
}

2. Use the incoming claims for current session only.

Copy the contents of SignInAsync() to your ExternalLoginCallback() method. Extract the call to user.GenerateUserIdentityAsync()to a separate line and. Add claims before callingSignInAsync()`

// Sign in the user with this external login provider if the user already has a login
var user = await UserManager.FindAsync(loginInfo.Login);
if (user != null)
{
  AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
  var identity = await user.GenerateUserIdentityAsync(UserManager);
  identity.AddClaim(loginInfo.ExternalIdentity.FindFirst(ClaimTypes.GivenName));
  AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent },
    identity);

  return RedirectToLocal(returnUrl);
}

Suggestion

It is also possible to use external login without ASP.NET Identity. If you're only using identities from the Idp and no other login method, that is probably easier to work with.

Anders Abel
  • 67,989
  • 17
  • 150
  • 217
  • Hello @AndersAbel. Thanks a lot for you response. Actually the suggestion at the bottom is what helped me since i don't need the Asp.Net Identity at all. I don't know why i did not see that post in your blog before because a read a lot there... – tschuege Nov 26 '14 at 10:46