Validate Google ID Token

1,261 views
Skip to first unread message

Tylor Froese

unread,
Feb 4, 2014, 1:49:06 PM2/4/14
to google-api-d...@googlegroups.com
Hey there. I've been banging my head against a wall for a while here because I'm trying to simply validate a Google ID token that is passed to a .NET server from an Android application. It seems this validation is supported on a number of other platforms but I can't find it within this api. Can anyone point me in the right direction?


Here is a gist of the current implementation I was trying to do which doesn't use this api (but instead is based off an ASP.NET example I found somewhere on the Google docs), but it gives me the error listed in the gist.

https://gist.github.com/TylorF/8809785

Gus Class

unread,
Feb 4, 2014, 3:41:31 PM2/4/14
to google-api-d...@googlegroups.com

If you're on .NET 4.5 or newer, you can validate the token as demonstrated in the VerifyToken Google+ demo:

https://github.com/googleplus/gplus-verifytoken-csharp

If you are on an older version of .NET, you can validate the token by using the Tokeninfo endpoint:

/// <summary>Performs validation steps on an OAuth 2.0 token.</summary>
/// <param name="token">The access or id token to validate.</param>
/// <param name="info">(Optional) The response from Tokeninfo.</param>
/// <returns>The identifier for the user associated with the token.</returns>
protected string ValidateToken(string token, Tokeninfo info = null)
{
bool isValid = false;

// ID tokens have four parts, and Access tokens have two parts, separated by '.'.
bool isIdToken = IsIdToken(token);

Oauth2Service service = new Oauth2Service(
new Google.Apis.Services.BaseClientService.Initializer());

var request = service.Tokeninfo();
if (!isIdToken)
{
// TODO - Try an authorized API call?
request.AccessToken = token;
}
else
{
request.IdToken = token;
}
try
{
if (info == null)
{
info = request.Execute();
}
if (info.IssuedTo == PlusHelper.GetClientConfiguration().Secrets.ClientId &&
info.ExpiresIn > 0)
{
isValid = true;
}
else
{
throw new PlusHelper.GoogleTokenExpirationException();
}

if (isValid)
{
return info.UserId;
}
else
{
throw new PlusHelper.TokenVerificationException();
}
}
catch (GoogleApiException gae)
{
// Occurs when you have an invalid token, send an error to the client.
throw new PlusHelper.TokenVerificationException();
}
}

/// <summary>
/// Tries to parse the base64 payload of a token to identify whether it is an ID token.
/// </summary>
/// <param name="token">The token to test.</param>
/// <returns>True if the token is an ID token.</returns>
protected bool IsIdToken(string token)
{
try
{
string[] segments = token.Split('.');

string base64EncoodedJsonBody = segments[1];
int mod4 = base64EncoodedJsonBody.Length % 4;
if (mod4 > 0)
{
base64EncoodedJsonBody += new string('=', 4 - mod4);
}
byte[] encodedBodyAsBytes =
System.Convert.FromBase64String(base64EncoodedJsonBody);
string jsonBody =
System.Text.Encoding.UTF8.GetString(encodedBodyAsBytes);

IDTokenJsonBodyObject bodyObject =
JsonConvert.DeserializeObject<IDTokenJsonBodyObject>(jsonBody);

// Test just in case the access token parses.
return bodyObject.Audience.Equals(
PlusHelper.GetClientConfiguration().Secrets.ClientId);
}
catch (JsonReaderException jre)
{
// Ignore, the body could not be parsed because this is an access token.
}
catch (FormatException fe)
{
// Ignore, the base64 string could not be parsed because this is an access token.
}
return false;
}

Tylor Froese

unread,
Feb 5, 2014, 10:58:57 AM2/5/14
to google-api-d...@googlegroups.com
I am in .NET 4.5 and the gist I linked is a modified version of that example. The problem is .NET returning a Certificate Trust error when trying to validate the token with the certificate on the public certs endpoint. I got around this in a hacky way last night where it will add the certificates to the trusted store temporarily, but it seems strange that the certificates aren't in a chain of trust to something that is already on windows. I don't like the implementation, really, and would prefer to add a root certificate that would be the root of all of the authentication certs, but it works for now.

Herky Gottfried

unread,
May 30, 2014, 7:51:55 PM5/30/14
to google-api-d...@googlegroups.com
I was able to get this to work using the code from https://github.com/googleplus/gplus-verifytoken-csharp

but this code reads the certificates from https://www.googleapis.com/oauth2/v1/certs

On Google's OpenIdConnect documentation, they suggest accessing the jwks_uri at https://www.googleapis.com/oauth2/v2/certs

I would prefer to validate using this approach but haven't been able to successfully do this. Has anyone ventured down this path? Is it worth doing?

Reply all
Reply to author
Forward
0 new messages