I've spent hours trawling through various tutorials and articles and am finally giving in to asking.
I want to enforce the use of Google Sign-In authentication for all users of my Angular 7 application. However, once Google authentication is complete, I want to first check that the user exists in my back-end DB (PostgreSQL). If they do, then I want to issue a JWT for two purposes:
So far, I have been able to retrieve the id_token from the gapi auth2 auth response and forward it to my Spring Boot POST mapping, but I'm struggling to pin down exactly which OAuth 2.0/OpenId flows/grants I'm aiming for which is making life difficult when sourcing appropriate Spring Boot documentation/tutorials.
Is anyone able to clarify which flow/grant I should be aiming for and whether or not my current direction is valid?
The JWT ID Token is only needed during Sign-in. We just need to validate it once during Sign-in like so: client. verifyIdToken({idToken: token, audience: CLIENT_ID}) . The ID Token is not used to Authenticate a user to My Web App.
The id_token is used in OpenID Connect protocol, where the user is authenticated as well as authorized. (There's an important distinction between authentication and authorization.) You will get id_token and access_token. The id_token value contains the information about the user's authentication.
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 :
The general idea is :
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With