I'm on owin, currently the flow is, javascript launches window with url to my authentication service. Authentication service redirects to SAML server, I enter in my credentials and SAML server redirects to the return url specified in the configuration. However, I don't see anything that indicates a SAML payload.
My config:
<kentor.authServices entityId="https://100.105.80.38:13855/AuthServices"
returnUrl="https://100.105.80.38:13855/slb/ExternalLoginCallback/">
<identityProviders>
<add entityId="https://saml.svr" destinationUrl="https://saml.svr" allowUnsolicitedAuthnResponse="true" binding="HttpRedirect">
<signingCertificate fileName="TokenSigningStaging.cer" />
</add>
</identityProviders>
</kentor.authServices>
<system.identityModel />
My callback
public HttpResponseMessage GetExternalLoginCallback()
{
// this is null
var loginInfo = this.AuthenticationManager.GetExternalLoginInfoAsync().Result;
http://stackoverflow.com/questions/19564479/mvc-5-owin-facebook-auth-results-in-null-reference-exception suggests that it is a bug in the Owin code, have you updated the NuGet package Microsoft.AspNet.Identity.Owin to at least 2.0.1?
@albinsunnanbo My nuget package is at 2.2.1, I was wondering if the idP is supposed to send me the claims they want to, or am I supposed to request them, or if it even matters?
There are basically two reasons that logininfo is null. Either the login was unsuccessfull, or it's lost before the call to the callback.
First follow the steps in [Understanding the Owin External Authentication Pipeline][https://coding.abel.nu/2014/06/understanding-the-owin-external-authentication-pipeline](https://coding.abel.nu/2014/06/understanding-the-owin-external-authentication-pipeline/) to debug the flow. Especially the AuthenticationResponseGrant. If it can't be found, the authentication was unsuccessful. If it can be found, check if the .AspNet.ExternalCookie is properly set (in the browser's debug tools). If not, you might be a victim of the Owin Cookie Monster
Check with https://addons.mozilla.org/sv-se/firefox/addon/saml-tracer/ to see the actual SAML2 response as sent by the IDP.
@AndersAbel thanks, i'll try to debug it and see how far i get.
@albinsunnanbo I do see a saml response but its encrypted, the response has a set-cookie header though, so it looks like i'm getting a correct response back. Its probably on my end.
I'll post a reply when I get it figured out.
@AndersAbel this might be the cookie monster issue, here are my debugging results
my server
browser hits my endpoint
endpoint sends redirect to idp
saml server
browser shows idp login page
I enter creds
idp redirects to /authservices/acs
my server
browser hits authservices/acs
logging interesting stuff now
app.Use(async (Context, next) =>
{ // 1. nothing
await next.Invoke();
});
Kentor.AuthServices.Configuration.Options.GlobalEnableSha256XmlSignatures();
app.Use(async (Context, next) =>
{ // 2. nothing
await next.Invoke();
}); //5. set-cookie is changed
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.Use(async (Context, next) =>
{ // 3. nothing
await next.Invoke();
}); //4. got grant
app.UseKentorAuthServicesAuthentication(new KentorAuthServicesAuthenticationOptions(true));
app.Use(async (Context, next) =>
{
await next.Invoke();
});
hits the redirect url (/ExternalLoginCallback)
the response.cookies has an aspnet.externalcookie with an ecrypted value
am i doing something wrong?
What are the contents of the grant at comment //4 in your code snippet? Are the expected claims present there?
Also you mention "encrypted". Do you mean that the entire SAML response is encoded (which is easily unpacked with the firefox extension Albin mentioned) or does it indeed contain an EncryptedAssertion node? In the latter case I have to make you disappointed, as AuthServices does not (yet) support encrypted assertions.
contents in the grant come over as expected. I see my name and my email address in plain text. As for encrypted, the value of the externalcookie in set-cookie is what's encrypted. Which i would think is expected? From what I can see, I think I'm either handling something incorrectly, or the identity/principal is getting dropped after the redirect from /acs
To clarify, the extension also shows the response, so I think that's working, too.
Another thing is, if I understand your article correctly, if the /ExternalLoginCallBack has the external cookie (which it does), the call to AuthenticationManager.GetExternalLoginInfoAsync() is supposed to read the external cookie and I'm supposed to be able to do whatever I want with the resulting ExternalLoginInfo object. Assuming the external cookie has the identity information, it looks like I might be doing something wrong there.
okay, i found this article and changed my externallogincalback to this:
var loginInfo = this.AuthenticationManager.AuthenticateAsync("ExternalCookie").Result;
this.AuthenticationManager.SignOut("ExternalCookie");
and now i have data in loginInfo. I don't understand what's the difference, though. If i just go by the method names, i would assume the code above does the same thing as the GetExternalLoginInfoAsync? Or did I miss a middleware somewhere?
Digging in the source with ILSpy, there is actually a difference between those two methods. Calling AuthenticateAsync directly more "raw" and gets the values directly. Using GetExternalLoginInfoAsync() makes a few more checks kick in. One of them is to check that there is a nameidentifier claim (which is created from the Subject NameIdentifier field in the SAML message) and if not, return null. Could that be your issue?
Wow that's cool, i was looking on github hoping i could find the source for the two methods for a long time. I can't confirm it right now, but I think that's the case.
IIRC, the only thing I'm getting from the test server right now is an email. I'm not sure what I need to tell the admin to get a name identifier. When I'm in the office tomorrow, I'll check to see if that value is there, and if its not, I'll let the SAML admin know to add subject NameIdentifier and see how things go from there.
so it looks like the only claim i'm getting at this point is email. The server admin is not in right now, so I can't confirm if adding the name identifier will make the other call work. For now this is enough for me to continue. Thanks for your help.
Most helpful comment
There are basically two reasons that
logininfois null. Either the login was unsuccessfull, or it's lost before the call to the callback.First follow the steps in [Understanding the Owin External Authentication Pipeline][https://coding.abel.nu/2014/06/understanding-the-owin-external-authentication-pipeline](https://coding.abel.nu/2014/06/understanding-the-owin-external-authentication-pipeline/) to debug the flow. Especially the
AuthenticationResponseGrant. If it can't be found, the authentication was unsuccessful. If it can be found, check if the.AspNet.ExternalCookieis properly set (in the browser's debug tools). If not, you might be a victim of the Owin Cookie Monster