6

I'm using DotNetOpenAuth to connect to Facebook and Google via OAuth2. The OAuth specs ask that no additional parameters be supplied in the request_uri and Google actually enforces this somewhat by forcing to to specify an exact call back uri when you define your Google App with them.

What I want to accomplish is to be able to return the user to a specific URL after they have been authenticated with Facebook or Google. The flow is this, the user clicks on a protected link, they get forwarded to my login page with a returnUrl parameter and then I kick off the authorization process based on the OAuth2 authorization server they choose.

Since the request_uri can't have any parameters in it (though Facebook lets you get away with this), I can't send the returnUrl parameter to the authorization server and get it back such that when the user is returned to my site, I forward them to the protected page they were trying to access. The best I can do is to forward them to the homepage or a member welcome page.

The way to fix this is to use the "state" parameter which the authorization server will send back to the request_uri, but I can't find a way to specify this with DotNetOpenAuth.

By default, it looks like the code uses the SessionID as the state parameter to verify the request coming back from the authorization server. Specifying an IClientAuthorizationTracker on the WebServerClient class lets me plug in my logic when the response is coming back from the authorization server but it's not called when the authorization request is being prepared, so I can't plug in my additional state.

This is code from WebServerClient.cs's PrepareRequestUserAuthorization:

            // Mitigate XSRF attacks by including a state value that would be unpredictable between users, but
        // verifiable for the same user/session.
        // If the host is implementing the authorization tracker though, they're handling this protection themselves.
        if (this.AuthorizationTracker == null) {
            var context = this.Channel.GetHttpContext();
            if (context.Session != null) {
                request.ClientState = context.Session.SessionID;
            } else {
                Logger.OAuth.WarnFormat("No request context discovered, so no client state parameter could be set to mitigate XSRF attacks.");
            }
        }

There is no else block here which is what I would have expected to be able to play along and plug in my own data.

Any tips on what I'm missing?

Ameen
  • 2,576
  • 1
  • 14
  • 17

1 Answers1

0

The state parameter is necessarily preoccupied with mitigating XSRF attacks. Since you already have a user session, can you just store the returnUrl in the session dictionary?

Alternatively, you can file an issue with DotNetOpenAuth asking that you be allowed to bundle your own data into the state parameter (along with DNOA's own XSRF mitigation code).

Wouter
  • 534
  • 3
  • 14
  • 22
Andrew Arnott
  • 80,040
  • 26
  • 132
  • 171
  • 1
    sorry for digging up this old thread but we need the ability to set the state value to track the OAuth2 journey. In WebServerClient.cs, If AuthorizationTracker is NOT null, the xsrf token is not added but there is no "else" to allow setting it to the value of the AuthorizationTracker clientState or otherwise to allow a user-supplied value in place of the xsrf token. That sounds like an oversight unless it was a deliberate design decision you could elaborate on. – Lukos Sep 02 '14 at 15:03
  • In my case, I cannot differentiate the user based on different URLs, I need to track what type of signup they are performing so that they hit a different landing page after OAuth2 is finished. I think state is the only way to achieve this without modifying the signup journey to divide at a later point (which I would like to avoid). – Lukos Sep 02 '14 at 15:04