After a ton of research (and wading through the excellent Pluralsight Course by Dominick Baier), the solution was the following:
The Over-arching Big Steps / Problems
- I wasn't setting a session authentication cookie, so the redirect was being treated as a new request, which saw no cookie and didn't set a principal.
- Later, when I used a session authentication manager, it turns out that Cassini (VS's built in debug server) wasn't loading the SessionAuthenticationManager at all
- (IIS and IIS Express do so just fine).
The Full Solution
Step by step (again, much of this is credited to Dominick's video):
Step 1: Add identity services to config
- Right-click on your project, and select "Add Reference..."
- In the Framework section, select
System.IdentityModel.Services
- Add the following to your web.config:
(full outline below, insert the two sections within that outline in your web.config):
<configuration>
<configSections>
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</configSections>
</configuration>
Step 2: Add session authentication manager
(which depends on that config setting)
In the system.webServer
section of your web.config, add the following lines:
<remove name="RoleManager"/> <!--Not needed anymore in my case -->
<add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
Step 3: Remove the PostAuthenticate method in Global.asax
(no longer needed because of SAM, which detects the cookie; why run it on every request if you don't have to, right?)
Step 4: Set your Claims Transformation method to set the authentication cookie
Add these lines in your ClaimsAuthenticationManager (mine was called ClaimsTransformer). I put this in a separate method called "EstablishSession", which took in my principal after it was already transformed:
private void EstablishSession(ClaimsPrincipal transformedPrincipal)
{
var sessionToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8));
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
}
So now the cookie is always set whenever you transform a claim, which makes sense because you're only transforming a claim if the user was successfully authenticated.
Step 5: Tear your hair out for a bit...
...wondering why SessionAuthenticationManager is always null.
Seriously, everything seems to work, and your config is correct, but darn it if it isn't null every. single. time.
Step 6: Switch the debug web server to IIS Express
Ahhhh, it appears that Cassini (the build in VS Debugger) doesn't work with SessionAuthenticationManager.
However, IIS Express does. Switch it to that in your project settings.
And Voila!
Now I have a page that works.