You can download the full solution here.
The relevant parts in the sample are:
I use the standard WIF configuration with passive redirect. This kicks automatically in, whenever authorization fails in the application (e.g. when the user tries to get to an area the requires authentication or needs registration).
Checking and transforming incoming claims
In the claims authentication manager we have to deal with two situations. Users that are authenticated but not registered, and registered (and authenticated) users. Registered users will have claims that come from the application domain, the claims of unregistered users come directly from ACS and get passed through. In both case a claim for the unique user identifier will be generated. The high level logic is as follows:
public override IClaimsPrincipal Authenticate(
string resourceName, IClaimsPrincipal incomingPrincipal)
// do nothing if anonymous request
return base.Authenticate(resourceName, incomingPrincipal);
string uniqueId = GetUniqueId(incomingPrincipal);
// check if user is registered
if (Repository.TryGetRegisteredUser(uniqueId, out data))
return CreateRegisteredUserPrincipal(uniqueId, data);
// authenticated by ACS, but not registered
// create unique id claim
new Claim(Constants.ClaimTypes.Id, uniqueId));
The registration page is handled by a controller with the [Authorize] attribute. That means you need to authenticate before you can register (crazy eh? ;). The controller then fetches some claims from the identity provider (if available) to pre-fill form fields.
After successful registration, the user is stored in the local data store and a new session token gets issued. This effectively replaces the ACS claims with application defined claims without requiring the user to re-signin.
All pages that should be only reachable by registered users check for a special application defined claim that only registered users have. You can nicely wrap that in a custom attribute in MVC:
public ActionResult Registered()