Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google OAuth2: perform token refreshing server-side while refresh token or authorization code acquired via mobile app

TL;DR - How can I refresh tokens backend-side if the oauth2 authorization happens in native android/ios app?

I am working on oauth2 integration with google calendar. My stack is react SPA app as web client and we have a backend API (in elixir). We are also using hybrid native apps, so our JS code is transformed into corresponding iOS/Android apps (using capacitor).

The flow is as follows:

  • user authorizes us to modify their calendars using oauth2, we ask for offline access
  • we acquire client-side authorization code from google
  • we send it to our backend and it uses the auth code to acquire access token and refresh token, the tokens are then persisted in our DB
  • we use the access token to perform updates to google calendar. When token expires we refresh it backend-side

This is the flow that is working on the web client, but with native apps (android/ios) I am stuck. When I use corresponding to ios/android apps clientIds from google console project credentials, my backend cannot successfully use it to acquire refresh and access tokens, I get the following response from https://oauth2.googleapis.com/token:

%{"error" => "invalid_client", "error_description" => "Unauthorized"}

I am considering moving the process of exchanging authorization code to refresh token and access token to the native apps, but how can the backend then have access to new access tokens? I can't refresh the tokens backend side if they were generated in the native app, I will again have clientId mismatch (also backend uses clientSecret, while native apps are exempt from using clientSecret).

like image 261
genau Avatar asked Sep 15 '25 03:09

genau


2 Answers

I had the same issue and finally ended up.

In order to design user authentication from the mobile/front-end side and send the authorization code to the server-side to exchange it for access_token and referesh_token you have not to follow the Mobile or Installed App flow:

enter image description here

In this way, you've created Android app OAuth2 credentials in the google developer console and used its client_id for google oauth2 page preparation so at the end you will have access_token which works only on the mobile side and does not work on the backend as it doesn't have client_secret.


Therefore, if you want to have access to the google APIs on your server-side and just perform the google authentication on the mobile side you can choose one of the following flows:

enter image description here

enter image description here

As you can see from the above flows, there are three parts namely client-side (mobile), google, and server-side (backend) rather than communication just between mobile and google which is useful for installed applications, not web applications. To me, between these two flows, I prefer the last one as it has fewer requests to create access_token and refresh_token on the server-side.

Here's the whole procedure:

  1. create a web application oauth2 credentials on the google developer console and use all sections in the backend and the client_id on the mobile side as well. Don't forget to enable the API you want to use.
  2. create a /callback endpoint in the backend which is the same as redirect_uri that you will need on the mobile side. In this endpoint, you will get the authorization code from the google request and then exchange it to the access_token and referesh_token and persist that on the DB.
  3. create an endpoint in order to call google API such as google calendar.
  4. Bring up the google authorization page on the mobile using SDKs, web view, or browser with the following content: existing client_it (which is the same with server-side), redirect_uri (callback), response_type="code", scope="https://www.googleapis.com/auth/calendar", access_type="offline", include_granted_scopes=true, and state to put some string if you want, for example I sent user's uuid.
like image 129
Benyamin Jafari Avatar answered Sep 17 '25 17:09

Benyamin Jafari


You can obtain access_token using refresh token by sending

POST https://oauth2.googleapis.com/token
x-www-form-urlencoded
client_id:CLIENTID
refresh_token:REFRESHTOKEN
grant_type:refresh_token
like image 28
Roman O Avatar answered Sep 17 '25 18:09

Roman O