5
votes

I am setting up refresh tokens in a web service that is based on the Web API 2 template. It is going to be consumed by both our own website as well as external clients.

After researching for some time, the general recommendation on securing the refresh token from XSS attacks is to store the identifier within an encrypted cookie. I know that I could return both the authentication and refresh tokens in cookies by using the UseCookieAuthentication method instead of the UseOAuthBearerAuthentication, but that would then cause complications when I'm dealing with external clients.

The code I currently have for setting up the configuration is:

public void ConfigureAuth(IAppBuilder app)
{
    var applicationProvider = new ApplicationOAuthProvider();

    var applicationRefreshProvider = new ApplicationRefreshTokenProvider();

    var oAuthServerOptions = new OAuthAuthorizationServerOptions
    {
        AllowInsecureHttp = true,

        TokenEndpointPath = new PathString("/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),

        Provider = applicationProvider,
        RefreshTokenProvider = applicationRefreshProvider
    };

    // Token Generation
    app.UseOAuthAuthorizationServer(oAuthServerOptions);
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}

A workaround I could implement would be adding a method to a controller on the resource server that then does that transformation step for the javascript based clients, but that doesn't quite make sense to me to do.

Is there a way I can accomplish this in the auth configuration, and is that the correct approach to take? I don't want to take the wrong direction if I can help it.

1

1 Answers

0
votes

I have been looking into this as well, I am just experimenting, and I have not finalized a solution yet. However, I have found that in my refreshTokenProvider, in the CreateAsync method, instead of context.SetToken I can do:

public async Task CreateAsync(AuthenticationTokenCreateContext context)
{
  // actual logic that retrieves refresh token...
  context.Response.Cookies.Append("refresh_token", refreshToken.ToString());
}

This will set a cookie in the response instead of adding a refresh token to the JSON response body, as one would expect. My plan would be to either do this or use SetToken depending on which client is requesting the refresh token.

Then, in the ReceiveAsync method, I have:

public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
  var refreshToken = context.Request.Cookies["request_token"];
  // actual logic that verifies refresh token, etc. 
}

The only caveat I've found thus far is that the AuthenticationTokenReceiveContext constructor that gets created when sending a grant_type=refresh_token request will not allow a null token, so if I pass any string as refresh_token it will work fine.

To repeat, I haven't fully fleshed it out. I need to figure out how to mitigate CSRF attacks and obviously encrypt the cookie, mark it http-only, etc. I am certain that none of this is insurmountable. But I was hoping this may help someone else and possibly spark a discussion, as I honestly do not know if I am doing this "correctly" either. It works, though, and my goal was to come up with a solution following this: http://jeremymarc.github.io/2014/08/14/oauth2-with-angular-the-right-way/.