I am making an OWIN app to self host a website. I am having trouble with the authentication part. The basic flow I am looking for is:
- Check if the request has the correct cookie. If it has the correct cookie, then get the
SecuritySessionToken
and build theClaimsIdentity
, and then return theAuthenticationTicket
. - If the cookie isn't there, then let the STS know.
- Get the SAML token from the STS and build the claims & authentication ticket. (Even though I'm using WsFederation authentication, ADFS is not involved here.)
Step 1 is working fine for me. Steps 2 and 3 are where I'm having trouble.
This is what I have for my configuration method in the startup class:
public void Configuration(IAppBuilder app)
{
CookieAuthenticationOptions options = new CookieAuthenticationOptions
{
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType,
CookieName = "MyCookieName",
CookiePath = "/cookiePath",
AuthenticationMode = AuthenticationMode.Active
};
// Not relevant how this module is made. It helps with
SessionAuthenticationModule module = this.CreateModule();
app.Use(typeof(MyCookieAuthenticationMiddleware), app, options, module);
WsFederationConfiguration fedConfig = new WsFederationConfiguration();
fedConfig.Issuer = "https://mySTS.com/NotRealUrl/";
SecurityTokenHandlerCollection handlerCollection = new SecurityTokenHandlerCollection(new List<SecurityTokenHandler>() { new SamlSecurityTokenHandler() });
WsFederationAuthenticationOptions wsFederationOptions = new WsFederationAuthenticationOptions
{
Configuration = fedConfig,
Wtrealm = "http://localhost/MyApp/NotRealUrl",
Wreply = "https://mySTS.com/NotRealUrl/Login",
SecurityTokenHandlers = handlerCollection,
AuthenticationMode = AuthenticationMode.Active,
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
};
app.Use(typeof(MyWsFederationAuthenticationMiddleware), app, wsFederationOptions);
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.Use<MyMiddleware>();
}
The part up to app.Use(typeof(MyCookieAuthenticationMiddleware), app, options, module);
works fine. That is, when the cookie is there, I use my custom cookie authentication middleware (MyCookieAuthenticationMiddleware
) to generate the AuthenticationTicket
.
The part that doesn't work is the WsFederation authentication middleware part. I created my own middleware for this (MyWsFederationAuthenticationMiddleware
) so that I could take a look at what's going on since doing app.UseWsFederationAuthentication(wsFederationOptions)
directly wasn't working for me. I am looking at the source code for WsFederationAuthenticationHandler.cs
to guide me, but I'm still confused about some overall concepts.
Questions
- I think I know what the general flow should be (what I numbered at
the top), but I'm not sure how this translates exactly to the
middleware pipeline. If I don't have a cookie, then I find this out
in
AuthenticateCoreAsync()
inMyCookieAuthenticationHandler
. But at what point do I redirect this to the STS to get the SAML token? Do I just wait for the pipeline to hitAuthenticateCoreAsync()
inMyWsFederationAuthenticationHandler
, and if the user is not authenticated, then get the token? - How do I actually tell the pipeline that it needs to get the token
from the STS? Looking again at
WsFederationAuthenticationHandler.cs
, it seems like their implementation ofApplyResponseChallengeAsync()
might be doing what I want? More specifically, if it's a 401 status code then make aWsFederationMessage
and redirect to the STS using that message? - Assuming I can actually get the STS to return the token I want, where in the pipeline does it return to?
Thanks and sorry for the sort of long post.
Update 1
I forgot to mention, when I run my code using app.UseWsFederationAuthentication(wsFederationOptions)
(instead of my own MyWsFederationAuthenticationMiddleware
), I get back a 400 "bad request - request too long" error. The URL is very long and looks like it contains various query parameters, including wtrealm, wctx, wa, and wreply, each of which contains url encoded strings. Looks like wctx is the really long one. I imagine it's some base64 encoded object. Unfortunately I don't really know what's going on.