seescode
seescode

Reputation: 2131

What does GenerateCorrelationId() and ValidateCorrelationId() do?

I see this code within a custom owin handler to do Oauth2. For example here: https://github.com/RockstarLabs/OwinOAuthProviders/blob/master/Owin.Security.Providers/Reddit/RedditAuthenticationHandler.cs

Can someone explain to me in plain English what these two methods do in the context of oauth2? It seems to be related to CSRF but not sure how.

Upvotes: 3

Views: 2028

Answers (1)

Crescent Fresh
Crescent Fresh

Reputation: 116998

When a redirect to an "OAuth 2" partner occurs there must be someway of correlating the eventual redirect back to your own application with the original redirect that you sent.

The way the Microsoft.Owin AuthenticationHandler accomplishes this:

  1. generates a nonce of random bytes and retains it in a browser cookie (GenerateCorrelationId)
  2. encrypts this nonce and other information and your job is to pass this in a state query string parameter to the partner (recall that the partner's job is to return this value right back to your application after authenticating the user)
  3. validates the nonce by decrypting the state query string parameter and verifying it matches the value in the cookie stored (ValidateCorrelationId)

Here is the source:

protected void GenerateCorrelationId(AuthenticationProperties properties)
{
    if (properties == null)
    {
        throw new ArgumentNullException("properties");
    }

    string correlationKey = Constants.CorrelationPrefix + 
                                BaseOptions.AuthenticationType;

    var nonceBytes = new byte[32];
    Random.GetBytes(nonceBytes);
    string correlationId = TextEncodings.Base64Url.Encode(nonceBytes);

    var cookieOptions = new CookieOptions
    {
        HttpOnly = true,
        Secure = Request.IsSecure
    };

    properties.Dictionary[correlationKey] = correlationId;

    Response.Cookies.Append(correlationKey, correlationId, cookieOptions);
}

protected bool ValidateCorrelationId(AuthenticationProperties properties, 
                                     ILogger logger)
{
    if (properties == null)
    {
        throw new ArgumentNullException("properties");
    }

    string correlationKey = Constants.CorrelationPrefix + 
                                BaseOptions.AuthenticationType;

    string correlationCookie = Request.Cookies[correlationKey];
    if (string.IsNullOrWhiteSpace(correlationCookie))
    {
        logger.WriteWarning("{0} cookie not found.", correlationKey);
        return false;
    }

    var cookieOptions = new CookieOptions
    {
        HttpOnly = true,
        Secure = Request.IsSecure
    };

    Response.Cookies.Delete(correlationKey, cookieOptions);

    string correlationExtra;
    if (!properties.Dictionary.TryGetValue(
        correlationKey,
        out correlationExtra))
    {
        logger.WriteWarning("{0} state property not found.", correlationKey);
        return false;
    }

    properties.Dictionary.Remove(correlationKey);

    if (!string.Equals(correlationCookie, correlationExtra, StringComparison.Ordinal))
    {
        logger.WriteWarning("{0} correlation cookie and state property mismatch.", 
                                correlationKey);
        return false;
    }

    return true;
}

Upvotes: 4

Related Questions