37 votes

Récupérer le jeton d'accès Google après s'être authentifié en utilisant l'authentification Firebase

Je essaie de récupérer le jeton d'accès Google pour accéder à l'API REST de Google tel que YouTube Data API à partir d'un utilisateur authentifié (en utilisant l'authentification Firebase).

J'ai intégré avec succès la connexion Google dans mon application avec l'aide de la bibliothèque Firebase-UI pour Android - Auth. Le jeton récupéré à partir de la méthode FirebaseUser.getToken() n'est pas un jeton d'accès Google valide pour l'API REST.

user.getToken(true).addOnCompleteListener(new OnCompleteListener() {
    public void onComplete(@NonNull Task task) {
        if (task.isSuccessful()) {
            String token = task.getResult().getToken();
            // 'token' n'est pas un jeton d'accès Google
        }
    }
});

Dans le guide de Connexion Google pour le Web, il est possible d'obtenir le jeton d'accès en appelant var token = result.credential.accessToken;, mais je ne peux pas trouver de méthode similaire sur Android.

Des suggestions? Veuillez commenter ici si je ne fournis pas suffisamment d'informations. Merci :)

45voto

Abhinav Puri Points 3538

La manière dont vous procédez vous donnera un jeton d'identification firebase, voir aquí .


Il existe trois types de jetons que vous rencontrerez dans firebase :

  • Jetons d'identification Firebase

    Créé par Firebase lorsqu'un utilisateur se connecte à une application Firebase. Ces jetons sont des JWT signés qui identifient de manière sécurisée un utilisateur dans un projet Firebase. Ces jetons contiennent des informations de base sur le profil d'un utilisateur, notamment la chaîne d'identification de l'utilisateur, qui est unique au projet Firebase. Comme l'intégrité des jetons d'identification peut être vérifiée, vous pouvez les envoyer à un serveur dorsal pour identifier l'utilisateur actuellement connecté.

  • Jetons du fournisseur d'identité

    Créé par des fournisseurs d'identité fédérés, tels que Google et Facebook. Ces jetons peuvent avoir différents formats, mais sont souvent des jetons d'accès OAuth 2.0. Les applications Firebase utilisent ces jetons pour vérifier que les utilisateurs se sont bien authentifiés auprès du fournisseur d'identité, puis les convertissent en informations d'identification utilisables par les services Firebase.

  • Jetons personnalisés Firebase

    Créé par votre système d'authentification personnalisé pour permettre aux utilisateurs de se connecter à une application Firebase en utilisant votre système d'authentification. Les jetons personnalisés sont des JWT signés à l'aide de la clé privée d'un compte de service. Les applications Firebase utilisent ces jetons de la même manière que les jetons renvoyés par les fournisseurs d'identité fédérés.


Maintenant, ce que vous obtenez est un jeton d'identité firebase, ce dont vous avez besoin est un jeton de fournisseur d'identité.

Il est simple d'obtenir le jeton du fournisseur d'identité, c'est juste une étape avant l'étape que vous avez montrée.

Donc, la façon dont nous nous connectons à Google en utilisant Firebase est mentionnée. aquí .

Je vais ajouter ci-dessous le code complet qui affiche un bouton dans l'interface utilisateur, qui, lorsqu'il est cliqué, va connecter l'utilisateur à son compte Google. Ensuite, j'obtiendrai le jeton d'accès Google, qui sera ensuite envoyé à Firebase, où il sera converti en jeton d'identification Firebase.

Je présume que vous avez configuré l'application Android pour l'identification par Google. Si ce n'est pas le cas, vous pouvez entrer dans les détails. aquí .


(Pour faire court, il suffit de regarder l'étape 5 ci-dessous, si vous avez déjà fait la configuration).

Code :

  1. Configurer Google SignIn et GoogleApiClient :

     // Configure sign-in to request the user's ID, email address, and basic
     // profile. ID and basic profile are included in DEFAULT_SIGN_IN.
     GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestIdToken(getString(R.string.default_web_client_id))
        .requestEmail()
        .build();
    
     // NOTE : 
     // The string passed to requestIdToken, default_web_client_id, 
     // can be obtained from credentials page (https://console.developers.google.com/apis/credentials).
     // There mentioned Web application type client ID is this string.
    
     // ... 
     // Build a GoogleApiClient with access to the Google Sign-In API and the
     // options specified by gso.
     mGoogleApiClient = new GoogleApiClient.Builder(this)
        .enableAutoManage(this /* Activity */, this /* OnConnectionFailedListener */)
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
        .build();
  2. Ajoutez le bouton d'identification Google à votre application

    <com.google.android.gms.common.SignInButton
        android:id="@+id/sign_in_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
  3. Définir l'écouteur de clics de connexion

    findViewById(R.id.sign_in_button).setOnClickListener(new OnClickListener() {
        public void onClick(View v){
            Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
            startActivityForResult(signInIntent, RC_SIGN_IN);   
        }
    });
  4. Remplacer OnActivityResult dans l'activité :

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    
        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            // Google Sign In was successful, authenticate with Firebase
            GoogleSignInAccount account = result.getSignInAccount();
            firebaseAuthWithGoogle(account); // This method is implemented in step 5.
        } else {
            // Google Sign In failed, update UI appropriately
            // ...
        }
    }
  5. Authentification Firebase avec Google SignInAccount

    String idTokenString = "";
    ...
    private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
        Log.d(TAG, "Google User Id :" + acct.getId());
    
        // --------------------------------- //
        // BELOW LINE GIVES YOU JSON WEB TOKEN, (USED TO GET ACCESS TOKEN) : 
        Log.d(TAG, "Google JWT : " + acct.getIdToken());
        // --------------------------------- //
    
        // Save this JWT in global String : 
        idTokenString = acct.getIdToken();
    
        AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
        mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
    
                    if(task.isSuccessful()){
                        // --------------------------------- //
                        // BELOW LINE GIVES YOU FIREBASE TOKEN ID : 
                        Log.d(TAG, "Firebase User Access Token : " + task.getResult().getToken());
                        // --------------------------------- //
                    }
                    // If sign in fails, display a message to the user. If sign in succeeds
                    // the auth state listener will be notified and logic to handle the
                    // signed in user can be handled in the listener.
                    else {
                        Log.w(TAG, "signInWithCredential", task.getException());
                        Toast.makeText(GoogleSignInActivity.this, "Authentication failed.",
                                Toast.LENGTH_SHORT).show();
                    }
                }
            });
    }
  6. Dernière étape : Auth Listeners pour Firebase

    private FirebaseAuth mAuth;
    private FirebaseAuth.AuthStateListener mAuthListener;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ...
        mAuth = FirebaseAuth.getInstance();
        mAuthListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();
                if (user != null) {
                    // User is signed in
                    Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
                } else {
                   // User is signed out
                   Log.d(TAG, "onAuthStateChanged:signed_out");
                }
                // ...
            }
       };
       // ...
    }
    
    //...
    
    @Override
    public void onStart() {
        super.onStart();
        mAuth.addAuthStateListener(mAuthListener);
    }
    
    @Override
    public void onStop() {
        super.onStop();
        if (mAuthListener != null) {
            mAuth.removeAuthStateListener(mAuthListener);
        }
    }

Donc, votre réponse se trouve à l'étape 5, qui était juste avant que vous vous authentifiez sur firebase et juste après que vous vous authentifiez dans google sign in.

J'espère que cela vous aidera !


UPDATE :

Il est important qu'à l'étape 1, vous demandiez le token Id, sinon à l'étape 5, vous obtiendrez un token Id nul. Pour en savoir plus, voir [aquí](https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInAccount.html#getIdToken()) . J'ai mis à jour l'étape 1.


UPDATE :

Selon la discussion, le jeton récupéré était le jeton JWT tel qu'écrit [aquí](https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInAccount.html#getIdToken()) . Et ce dont nous avons besoin est le jeton d'accès de Google. Le code ci-dessous utilise le token JWT pour lancer le backend OAuth et récupérer ce token d'accès :

(Note : J'ai utilisé la version 2.6.0 de okhttp, d'autres versions peuvent avoir des méthodes différentes).

Code :

...
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new FormEncodingBuilder()
            .add("grant_type", "authorization_code")
            .add("client_id", "<Your-client-id>")   // something like : ...apps.googleusercontent.com
            .add("client_secret", "{Your-client-secret}")
            .add("redirect_uri","")
            .add("code", "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8") // device code.
            .add("id_token", idTokenString) // This is what we received in Step 5, the jwt token.
            .build();

final Request request = new Request.Builder()
        .url("https://www.googleapis.com/oauth2/v4/token")
        .post(requestBody)
        .build();

client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(final Request request, final IOException e) {
        Log.e(LOG_TAG, e.toString());                
    }

    @Override
    public void onResponse(Response response) throws IOException {
        try {
            JSONObject jsonObject = new JSONObject(response.body().string());
            final String message = jsonObject.toString(5);
            Log.i(LOG_TAG, message);                    
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
});

Voici la sortie qui a un jeton d'accès comme requis :

I/onResponse: {
          "expires_in": 3600,
          "token_type": "Bearer",
          "refresh_token": "1\/xz1eb0XU3....nxoALEVQ",
          "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjQxMWY1Ym......yWVsUA",
          "access_token": "ya29.bQKKYah-........_tkt980_qAGIo9yeWEG4"
     }

J'espère que cela vous aidera !

28voto

vovkas Points 621

Essayez GoogleAuthUtil.getTokenscope est comme "oauth2:scope1 scope2 scope3"

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.default_web_client_id))
            .requestEmail()
            .build();

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this, this)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build();
}

private void signIn() {
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        if (result.isSuccess()) {
            final GoogleSignInAccount account = result.getSignInAccount();

                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        try {
                            String scope = "oauth2:"+Scopes.EMAIL+" "+ Scopes.PROFILE;
                            String accessToken = GoogleAuthUtil.getToken(getApplicationContext(), account.getAccount(), scope, new Bundle());
                            Log.d(TAG, "accessToken:"+accessToken); //accessToken:ya29.Gl...

                        } catch (IOException e) {
                            e.printStackTrace();
                        } catch (GoogleAuthException e) {
                            e.printStackTrace();
                        }
                    }
                };
                AsyncTask.execute(runnable);

        } else {
        }
    }
}

6voto

cutiko Points 2514

Je suis en train de suivre la solution de @vovkas et je veux vous informer qu'avec la dernière mise à jour 11.6.0, vous pouvez obtenir le Compte nécessaire plus facilement, afin que vous puissiez tout avoir à l'intérieur d'un pratique AsyncTask pour être réutilisé quand vous le souhaitez :

public class GetToken extends AsyncTask {

    private final Context context;

    public GetToken(Context context) {
        this.context = context;
    }

    @Override
    protected String doInBackground(Void... voids) {
        try {
            String scope = "oauth2:" + Scopes.EMAIL + " " + Scopes.PROFILE;
            GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(context);
            return GoogleAuthUtil.getToken(context, account.getAccount(), scope, new Bundle());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (GoogleAuthException e) {
            e.printStackTrace();
        }
        return null;
    }
}

La clé est d'utiliser GoogleSignIn.getLastSignedInAccount(context).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X