Google Sign-In with Backend Verification Flow Clarification

I suggest you to implement a “stateless” authentication system, coupled with Google Sign-in ID provider.

“Using a JWT as a bearer for authorization, you can statelessly verify if the user is authenticated by simply checking if the expiration in the payload hasn’t expired and if the signature is valid.” — Jonatan Nilsson

Some good resources on the subject :

  • https://www.jbspeakr.cc/purpose-jwt-stateless-authentication/
  • https://auth0.com/blog/stateless-auth-for-stateful-minds/

The general idea is :

  • frontend retrieves a Google Sign-in authentication JWT token.
  • frontend sends JWT token with each HTTP request (with authorization header)
  • backend retrieves JWT for each request, validates its signature, and gets payload attributes (email, id…)
  • then, backend checks ‘email’ or ‘id’ in users database to allow or not request.

Backend is stateless, and simple to implement. This design tends to become a good practice in cloud platform, and for instance, Google Cloud is using this a lot in its new products : Cloud Run

Some details on each step:

1) frontend retrieves a Google Sign-in authentication JWT token.

To do that, you can use Google Sign-in library directly or use ng-gapi to manage Google Sign-In in Angular.

2) Each http call to backend has an authorization header with JWT token (id_token) retrieved from Google Sign-in.

You can use an HttpInterceptor for that.

headers: {
  Authorization: Bearer ___JWT ID TOKEN___
}

See Top 10 ways to use Interceptors in Angular from Michael Karén.

Pay attention, to not store the Google JWT Id_token in variable. It could be refreshed if expired (automatically done by Google Sign-in), so you should take a fresh version each time you use it inside HttpInterceptor.

3) Implement a filter inside Spring Boot

For each request, this security filter will retrieve JWT ID TOKEN and validate it with Google library.

NetHttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = new GsonFactory();

GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
  .setAudience(Collections.singletonList(clientId))
  .build();

GoogleIdToken idToken = GoogleIdToken.parse(verifier.getJsonFactory(), token);
boolean tokenIsValid = (idToken != null) && verifier.verify(idToken);

if (tokenIsValid) {
  GoogleIdToken.Payload payload = idToken.getPayload();

  // Get profile information from payload
  payload.getEmail())...
...

But be careful, to not create a GoogleIdTokenVerifier for each request, use factory pattern. This class will retrieve certificates and cache them automatically, to avoid useless request to google servers.

Some resources : Google Sign-in, Authenticate with a backend server