Reputation: 806
I'm migrating from the old Google Sign In library to the new Google Identity Services (GIS) library. This is mandatory, since the old one will no longer be in use from March 2023.
Previously, I did (simplified for clarity):
<script src="https://apis.google.com/js/api:client.js"></script>
gapi.load();
var auth2 = gapi.auth2.init();
auth2.attachClickHandler();
onGoogleSignIn(googleUser); // attachClickHandler's callback
var profile = googleUser.getBasicProfile(); // profile info accessible
var authResponse = googleUser.getAuthResponse(); // auth response accessible
var accessToken = authResponse.id_token; // get actual access token
Now, I'm trying (simplified for clarity):
<script src="https://accounts.google.com/gsi/client"></script>
var gisClient = google.accounts.oauth2.initTokenClient();
gisClient.requestAccessToken();
callback(); // initTokenClient's callback
var accessToken = response.access_token; // get access token in callback
With the old google sign in library, I validated the access token server side as such:
Payload payload = await GoogleJsonWebSignature.ValidateAsync(accessToken);
This also returned the user's email and name in the payload.
The access token I am getting back from GIS, is much shorter than the old one from GAPI.
An online token debugger tells me it's not a valid JWT token.
The ValidateAsync method throws an exception:
JWT must consist of Header, Payload, and Signature
No surprise, considering it's not a valid JWT token.
I also tried the following call:
Payload payload = await JsonWebSignature.VerifySignedTokenAsync(AccessToken, options);
Same result.
The official documentation doesn't say how to validate this token server side for C# / .NET.
I can't find help on this anywhere in the documentation.
What can I do to get server side access token validation (and retrieval of email + profile) working with Google Identity Services?
Upvotes: 8
Views: 3329
Reputation: 1526
The new Google Sign in returns "CredentialResponse"
which contains a property called credential
, which is the JSON Web Token (JWT) in base64 that you need.
This JWT can be sent to client or server for validation.
After validation you will receive user profile data.
<div id="g_id_onload"
data-client_id="YOUR_GOOGLE_CLIENT_ID"
data-callback="handleCredentialResponse">
</div>
<script>
function handleCredentialResponse(response) {
//get JSON Web Token (JWT) out of the response object
var jwt = response.credential;
//send JWT to backend server for validation
var result = ValidateAtServer(jwt);
//do something with result
KillUserInstantly(result);
}
</script>
public static void ValidateAtServer(httpRequest)
{
//get jwt string from request
...
//validate it using Google.Apis.Auth (null if invalid)
var validPayload = await GoogleJsonWebSignature.ValidateAsync(jwtToken);
//get user data & use it
var userId = validPayload.Subject; //The unique ID of the user's Google Account
var email = validPayload.Email;
//do something with data
...
}
subject
or sub
Example JWT/ID Token
eyJhbGciOiJSUzI1NiIsImtpZCI6IjE1NDllMGFlZjU3NGQxYzdiZGQxMzZjMjAyYjhkMjkwNTgwYjE2NWMiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2NTk3NTk0MzEsImF1ZCI6IjEwODgwNjIxNjM1NzMtaXMwdWQ1aDRza2JscmR1Njp0cnVlLCJheuZXMiLCJpYXQiOjE2NTk3NTk3MzEsImV4cCI6MTY1OTc2MzMzMSwianRpIjoiMDhlNjRhM2I1YzdmNzcxYmRjNTg5M2YwNmMyZjM1ZWZlMzIyNjYyMCJ9.UT07_-_4o_1D5NmVAI0QtXLupVZtXys3Kg0c--Cv-xrMpUZXInfqj142eojvTEf6QBmBPY3k-Mtu7djJAenB8Ed8-dWtvFdGdv5FdSJCSyLN70ObzCsdo_IgjG5r3HTw1C9pIFKggOklJrVN-zL0_Kh3TZdxfMdyEbAUuhIRCreUVgZ74XEWhR6x4l0EY9o2331HcrzAaie_LN4C8NVHhkQ0DLg5dO2v8T1uKG-eTyv-uvjMuhkSVBJR3MnvkGepj7o0h_ELGO9x74P9nNjIKTyZboEr4_YO0BP5aLPwt67LJHactAJ8DJTzugXwaJBVhusK1KPYYGRhy7nTfbfTSg
Upvotes: 6