skip to Main Content

I’m developing an Android app that consumes data from my own REST API server. I want to use Firebase authentication because it allows the user to login using Google, Facebook, Twitter… in a very simple way.

But I’m not sure how to use ID tokens:

  • Because ID tokens have expiration date, should I call getToken method on every request in the client app, so I’m sure I’m sending a valid token every time?
  • Should I call verifyIdToken in the server each time I receive a request from the client app?

I don’t know what these methods (getToken and verifyIdToken) do under the hood, and because they are asynchronous, I fear they are doing a request to Firebase servers on every call. So I think that making 2 request to Firebase servers in each of my requests is not the way to go…

5

Answers


  1. Use below code in your application class and regId is the value holder for your device token.

    private void checkPlayService() {
        // Check device for Play Services APK. If check succeeds, proceed with
        // GCM registration.
        if (checkPlayServices()) {
         GoogleCloudMessaging googleCloudMessaging = GoogleCloudMessaging.getInstance(activity);
            regId = getRegistrationId();
    
            if (TextUtils.isEmpty(regId)) {
                registerInBackground();
            }
        } else {
            Log.i(TAG, "No valid Google Play Services APK found.");
        }
    }
    
    private String getRegistrationId() {
        String registrationId = sp.getString(Consts.PROPERTY_REG_ID, "");
        if (TextUtils.isEmpty(registrationId)) {
            Log.i(TAG, "Registration not found.");
            return "";
        }
        // Check if app was updated; if so, it must clear the registration ID
        // since the existing regID is not guaranteed to work with the new
        // app version.
        int registeredVersion = sp.getInt(PROPERTY_APP_VERSION,0);
        int currentVersion = getAppVersion();
        if (registeredVersion != currentVersion) {
            Log.i(TAG, "App version changed.");
            return "";
        }
        return registrationId;
    }
    
    private void registerInBackground() {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... params) {
                String msg = "";
                try {
                    if (googleCloudMessaging == null) {
                        googleCloudMessaging = GoogleCloudMessaging.getInstance(activity);
                    }
    
                    regId = googleCloudMessaging.register(Consts.PROJECT_NUMBER);
                    msg = "Device registered, registration ID=" + regId;
                    Log.e("GCMID",msg);
                    storeRegistrationId(regId);
    
                } catch (IOException ex) {
                    msg = "Error :" + ex.getMessage();
                }
                return msg;
            }
    
            @Override
            protected void onPostExecute(String msg) {
                Log.i(TAG, msg + "n");
            }
        }.execute(null, null, null);
    }
    
    
    
    private void storeRegistrationId(String regId) {
        int appVersion = getAppVersion();
        Log.i(TAG, "Saving regId on app version " + appVersion);
        sp.edit().putString(Consts.PROPERTY_REG_ID, regId).commit();
        sp.edit().putInt(PROPERTY_APP_VERSION, appVersion).commit();
    }
    
    Login or Signup to reply.
  2. You refresh token each time when is no more valid. And yes, you should verify token on server-side each time. If is no more valid, you send 401 error code with error message (if you want). Verify token is used when you refresh token, and token is append to each request. If you use OkHttp you can create an interceptor that is adding token in header to each request and also can refresh token when error code is 401.

    Login or Signup to reply.
  3. From what you have explained in the question, I guess you are talking about cross client resource access using Google sign in. And specifically you seem to be interested in obtaining the Id token once and use it without having to obtain on each subsequent API call.

    This more or less is synonymous with the offline access mechanism.
    In offline access, the Client I.e. the Android app asks for user authorisation for requested scopes. Upon authorisation, instead of issuing an access token, auth server returns a short lived authorisation code which can be used to generate an access token and refresh token.

    The client then can pass the authorisation code to the backend over a secure connection. Backend server can retrieve the author token and refresh token and store them in a secure location. The access token is short lived and can be used to access scoped resources for a short time and refreshed from time to time using the refresh token. The refresh token does not expire but can be revoked. If revoked, server app should ask the client app to re-fetch the author code.

    Please go through this link which details the complete infrastructure along with the steps to be followed both by client and server app –
    https://developers.google.com/identity/protocols/CrossClientAuth

    Now coming to your question, you should use a slightly different API to obtain the auth code. Check out this API –
    https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInOptions.Builder.html#requestServerAuthCode(java.lang.String)

    Sample code at – https://developers.google.com/identity/sign-in/android/offline-access

    Login or Signup to reply.
  4. POST https://YOUR_AUTH0_DOMAIN/delegation
    Content-Type: 'application/json'
    {
      "client_id":       "YOUR_CLIENT_ID",
      "grant_type":      "urn:ietf:params:oauth:grant-type:jwt-bearer",
      "refresh_token":   "your_refresh_token",
      "api_type":        "app"
    }
    
    Login or Signup to reply.
  5. Both getToken() and VerifyIdToken() are designed to be called for every outgoing/incoming request.

    1) Although getToken() is asynchronous, the Firebase Android SDK actually caches the current Firebase user token in local storage. So long as the cached token is still valid (i.e. within one hour since issued), getToken() returns the token immediately. Only when the cached token expires does the SDK fetch a new token from remote Firebase server.

    2) VerifyIdToken() is also optimized for performance. It caches the Firebase token public cert (valid for 6 hours) which is used to validate the token signature on local machine. No RPC is involved except for downloading the public cert.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search