Get id token on Android app and verify it on backend server (How to use id token?)

百般思念 提交于 2021-02-06 02:32:26

问题


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...


回答1:


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.




回答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.




回答3:


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"
}



回答4:


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




回答5:


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();
}


来源:https://stackoverflow.com/questions/41598222/get-id-token-on-android-app-and-verify-it-on-backend-server-how-to-use-id-token

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!