- Why you may want to read this article
- Implementation
- How to obtain Google OAuth credentials
- Google Auth Problems
- Demo
- Conclusion
Why you may want to read this article
In the last article we have integrated our React SPA (single page application) with Github OAuth protocol.
Today we will implement Google OAuth client using pure React Client without any additional backend. This is exactly this “Sign in with Google” button which we will implement here. This Google authorization/authentication is also needed for Google API integration, so you might use obtained token to integrate with any Google API: Calendar, Drive, etc.
Implementation
We have already implemented the core of our React OAuth client in the first article. We will use Core repository and change some configuration to make it work with Google.
The whole source code for current project can be found here
Update utils/config.js
const googleSettings = {
authority: 'https://accounts.google.com/',
client_id: 'CLIENT_ID',
client_secret: 'CLIENT_SECRET',
redirect_uri: 'http://localhost:3000/oauth/callback',
silent_redirect_uri: 'http://localhost:3000/oauth/callback',
post_logout_redirect_uri: 'http://localhost:3000/',
response_type: 'code'
};
export const googleConfig = {
settings: googleSettings,
flow: 'google'
};
authority
- we put a Google Authorization server domain. By this domain we will access Discovery Endpoint. This way we don’t need to override metadata in our configuration as we did in Github integration.
client_id
- see How to obtain Google OAuth credentials
client_secret
- see How to obtain Google OAuth credentials
response_type
- we specify that the OAuth protocol should be an Authorization Code.
Update services/AuthService.js
import { googleConfig } from '../utils/config';
const userManager = new UserManager(googleConfig.settings);
export async function logout() {
await userManager.clearStaleState();
try {
await userManager.signoutRedirect();
} catch (e) {
console.log('error on signoutRedirect', e);
window.location.href = '/';
}
}
Here we changed config names, and logout function. Logout needed to be changed because Google didn’t provide end_session_endpoint
in discovery endpoint response.
signoutRedirect
would fail since UserManager does not have end_session_endpoint.
So we cannot log out user on the Google side, but still we will drop all local state about authentication by calling await userManager.clearStaleState();
Update services/Api.js
const url = 'https://www.googleapis.com/oauth2/v3/userinfo';
All parts remain the same, we only change url from our local Resource Server to Google API to demonstrate our token work with Google API properly.
Update pages/unauthenticated.page.js
<button onClick={sendOAuthRequest}>Login via Google</button>
We just change button name
How to obtain Google OAuth credentials
Create Google Cloud Project
Go to this url
Follow instructions until you create your project.
Create Consent Screen
Select your project and go to APIs & Services -> Credentials
Click Create Credentials -> OAuth client ID
If you don’t have Consent Screen - you would need to create it first.
Select User Type
to be external
, any app name, your personal email as support email and developer email. Then click Create
.
Next screen is for scopes configuration. You might add one if you need to access any Google services with the access token that we will obtain.
Click the “Public app” button to make your consent screen available.
Obtain credentials (Client Id, Client Secret)
Click Create credentials -> OAuth client ID
again. Set the application type to Web Application
.
Set Authorized Javascript Origins
to http://localhost:3000.
Set Authorized redirect URIs
to http://localhost:3000/oauth/callback. Click Create.
Copy Client Id and Client Secret for the use in our React OAuth Client.
Google Auth Problems
Google does not have end_session_endpoint
I searched tons of forums, stackoverflow, github, official doc, asked GPT, Copilot - but I didin’t find end_session_endpoint.
According to OpenId Connect official documentation:
end_session_endpoint
REQUIRED. URL at the OP to which an RP can perform a redirect to request that the End-User be logged out at the OP.
The Discovery endpoint really does not have it:
Demo
Put Client Id and Client Secret to the configuration.
Run npm start
to start the application.
Click Login via Google
As you can see we have obtained the token and showed it on the page. On top of that you might see our call to userinfo endpoint with a token and its response that contains the “sub” field and “picture” field.
You might try to access this endpoint with invalid token that will result in error, so 200 OK shows that we did everything correctly and our token is the correct one.
Conclusion
Our core implementation proved itself once more with Google OAuth. It turned out that Google has much less problems and OAuth/OIDC incompatibilities compared to Github. Here we proved that our client is very flexible and we can make it work with any OAuth/Identity provider including Google Open Id Connect/OAuth2.
Please subscribe to my social media to not miss updates.: Instagram, Telegram
I’m talking about life as a Software Engineer at Microsoft.
Besides that, my projects:
Symptoms Diary: https://symptom-diary.com
Pet4Pet: https://pet-4-pet.com