This project has moved. For the latest updates, please go here.

Custom Authentication Middleware - How to persist data between 2 requests

Apr 11, 2014 at 10:51 PM
Hi,

I'm currently trying to put together a middleware to perform custom authentication and I can't figure out something that must be possible: how to persist data in between 2 requests.

Very much like Google and Facebook, our authentication process implies the following steps:
  1. The server gets a new session id from the authentication server
  2. The server respond to the client with a 301 status code pointing to the authentication server (using also the session id)
  3. The client authenticate to Authentication Server and gets redirected back to the server
  4. The server queries the Authentication Server with the session id about the claims of the user
  5. If the claims are OK then the identity is set on the server
How is it possible to store the session id between the first time the user comes to the site (step 2) and the time the user comes back after authentication on the remote server?

Thanks in advance for any pointer!
Apr 13, 2014 at 11:16 PM
Hi Jaepetto,

the build-in middleware-components for Google and Twitter use the State-Parameter that is passed arround. This Parameter should also contain some kind of nonce for security-reasons. So they serialize a the data to pass arround and the nonce into a encrypted string that is used as the state-Parameter. In addition to that, they store the nonce within an HTTP-only cookie.

Btw: Using cookies is another way to persist data between requests.

Wishes,
Manfred
Marked as answer by Tratcher on 5/21/2014 at 2:15 PM
Apr 14, 2014 at 9:13 AM
Hi Manfred,

thanks for your response. It was really useful.

May I ask you another question?
How do you detect that Authentication is required (i.e. the method was decorated with the Authorize attribute)?
I was under the assumption that I could use a condition like the one below in order to manage the access anonymous access to the resource:
var ticket = new AuthenticationTicket(null, null);
if (Response.StatusCode == 401) {
   
     // logic to set the identity
    ticket = new AuthenticationTicket(identity, null);
}

return Task.FromResult(ticket);
Unfortunately, as my middleware uses the stage marker PipelineStage.Authenticate, the Response.StatusCode is always equal to 200 and get set to 401 only later in the pipeline.

Do you have any pointer on ow to accomplish that?
Apr 14, 2014 at 11:09 AM
Hey,

Use await AuthenticationManager.AuthenticateAsync("AuthenticationType") and check for the result to determine whether the user can be authenticated using the mentioned authentication type. You can also use AuthenticationManager.User if you configured your authentication middleware as active (i.e AuthenticationMode = AuthenticationMode.Active).
Apr 14, 2014 at 6:58 PM
@PinpointTownes: Thanks a lot for the quick answer, but I'm not quite sure I understand what you mean. I searched the cookie middleware's source code to understand and could not find any reference to await AuthenticationManager.AuthenticateAsync or AuthenticationManager.User. Would you have any running sample code? That would be be great!
Apr 14, 2014 at 7:09 PM
Edited Apr 14, 2014 at 7:11 PM
Hum, why did you search that in the cookie middleware? :o

Here's how you'd use it in a custom handler:
public partial class Startup {
    public void Configuration(IAppBuilder app) {
        app.Use(async (context, next) => {
            var result = await context.Authentication.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationType);
            if (result != null && result.Identity != null) {
                await context.Response.WriteAsync("The user has been correctly authenticated, let's execute the next middleware");
                await next();
                return;
            }

            await context.Response.WriteAsync("The user has not been authenticated, stop processing the request");
        });
    }
}
That said, if you're using an higher level framework like Web API or MVC, there are better ways to enforce authentication (see AuthorizeAttribute and HostAuthenticationAttribute). What do you want to do exactly?

If you need help, don't hesitate to visit the OWIN channel on JabbR: https://jabbr.net/#/rooms/owin
Apr 14, 2014 at 7:36 PM
Hi,

your description sounds like you have still registred the "old" Forms-Authentication-Module, that is registered by default. You can try to unregister it:

http://stackoverflow.com/questions/21652808/asp-net-mvc-5-web-config-formsauthenticationmodule-or-formsauthentication

Wishes,
Manfred
Apr 14, 2014 at 7:41 PM
Removing the FAM is indeed a necessary step when using the SystemWeb host.
But here, the 200 and 401 response codes exclude an intervention of the FAM, which would alter them to 302 responses.
Apr 15, 2014 at 5:46 PM
Hi,

as I remember, the build-in middleware-components call AuthenticationManager.SignIn and pass the AuthenticationType of the cookie-middleware. This activates the cookie-middleware. This AuthType can be defined using the property SignInAsAuthenticationType. If you don't pass a value for this property, the middleware-components use a default-AuthType.

This default AuthType can be set using app.SetDefaultSignInAsAuthenticationType and fetched using app.GetDefaultSignInAsAuthenticationType - both are extension-methods for IAppBuilder. The extension-method UseExternalSignInCookie sets this default-value to the used AuthType, which is ExternalCookie by default.

Wishes,
Manfred
Marked as answer by Tratcher on 5/21/2014 at 2:15 PM