Подтвердить что ты не робот

Как получить токен доступа после входа пользователя из Gmail в Android?

Я следую Google Войти в Android. Теперь я могу получить idToken, но мой сервер back end, который я использовал ранее, ожидает токена доступа, поскольку ранее я использовал Google+ Login. Теперь я не хочу менять серверную часть. Но все же, как я могу использовать Google Войти и получить токен доступа в своем приложении для Android, чтобы я мог проверить моего пользователя на моем сервере.

Я использовал GooglePlay Service 7.5.0 ранее, и теперь я использую GooglePlay Service последние 8.3.0.

4b9b3361

Ответ 1

Для ваших требований вы можете использовать следующий код:

Во-первых, убедитесь, что у вас есть действующий Web идентификатор клиента OAuth 2.0:

<!-- Server Client ID.  This should be a valid Web OAuth 2.0 Client ID obtained
         from https://console.developers.google.com/ -->
    <string name="server_client_id">...e4p8.apps.googleusercontent.com</string>

Затем внутри класса Activity:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ...

    // For sample only: make sure there is a valid server client ID.
    validateServerClientID();

    // [START configure_signin]
    // Configure sign-in to request offline access to the user ID, basic
    // profile, and Google Drive. The first time you request a code you will
    // be able to exchange it for an access token and refresh token, which
    // you should store. In subsequent calls, the code will only result in
    // an access token. By asking for profile access (through
    // DEFAULT_SIGN_IN) you will also get an ID Token as a result of the
    // code exchange.
    String serverClientId = getString(R.string.server_client_id);
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestScopes(new Scope(Scopes.DRIVE_APPFOLDER))
            .requestServerAuthCode(serverClientId)
            .requestEmail()
            .build();
    // [END configure_signin]

    // Build GoogleAPIClient with the Google Sign-In API and the above options.
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build();
}

private void getAuthCode() {
    // Start the retrieval process for a server auth code.  If requested, ask for a refresh
    // token.  Otherwise, only get an access token if a refresh token has been previously
    // retrieved.  Getting a new access token for an existing grant does not require
    // user consent.
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_GET_AUTH_CODE);
}

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

    if (requestCode == RC_GET_AUTH_CODE) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        Log.d(TAG, "onActivityResult:GET_AUTH_CODE:success:" + result.getStatus().isSuccess());

        if (result.isSuccess()) {
            // [START get_auth_code]
            GoogleSignInAccount acct = result.getSignInAccount();
            String authCode = acct.getServerAuthCode();

            // Show signed-in UI.
            mAuthCodeTextView.setText(getString(R.string.auth_code_fmt, authCode));
            updateUI(true);

            // TODO(user): send code to server and exchange for access/refresh/ID tokens.
            // [END get_auth_code]
        } else {
            // Show signed-out UI.
            updateUI(false);
        }
    }
}

Вы можете увидеть весь код на следующем ServerAuthCodeActivity.java

Результат, если вы используете этот образец, выглядит следующим образом:

Снимок экрана BNK

Затем вы можете выполнить шаги, указанные в документации Google ниже (начиная с шага 3. Отправьте код авторизации в бэкэнд приложения через HTTPS POST):

Вход в Google для Android - включение серверного доступа


UPDATE: из комментариев, если вы хотите получить токен доступа непосредственно из клиентского приложения Android, используйте следующий пример кода (замененный на ваш client_id, client_secret и код auth)

OkHttpClient client = new OkHttpClient();
    RequestBody requestBody = new FormEncodingBuilder()
            .add("grant_type", "authorization_code")
            .add("client_id", "812741506391-h38jh0j4fv0ce1krdkiq0hfvt6n5amrf.apps.googleusercontent.com")
            .add("client_secret", "{clientSecret}")
            .add("redirect_uri","")
            .add("code", "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8")
            .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();
            }
        }
    });

Используйте compile 'com.squareup.okhttp:okhttp:2.6.0' (ver 3-RC1 будет иметь разные классы)

При успешном ответе у вас будет следующая информация в logcat:

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

Ответ 2

BNK имеет место по большей части. Класс Activity аналогичен тому, как BNK отвечают только с добавлением части OkHttp, когда вы получите GoogleSignInAccount в методе onActivityResult().

Но я все еще получал ошибки с частью запроса OkHttp. Наконец, после небольшого тестирования (и частичной удачи) в Postman, я обнаружил, что мне не хватает параметра id_token. В запросе OkHttp отсутствовал один параметр i.e id_token. Используйте токен ID, который вы получаете из GoogleSignInAccount, например,

GoogleSignInAccount acct = result.getSignInAccount();
String idTokenString = acct.getIdToken();

Теперь используйте эту idTokenString вместе со всеми параметрами в части OkHttp BNK, чтобы ответить примерно так:

...

RequestBody requestBody = new FormEncodingBuilder()
            .add("grant_type", "authorization_code")
            .add("client_id", "812741506391-h38jh0j4fv0ce1krdkiq0hfvt6n5amrf.apps.googleusercontent.com")
            .add("client_secret", "{clientSecret}")
            .add("redirect_uri","")
            .add("code", "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8")
            .add("id_token", idTokenString) // Added this extra parameter here
            .build();

...

Ответ, полученный одним, совпадает с ответом BNKs

{
  "access_token": "ya29.CjBgA_I58IabCJ...remainingAccessTokenHere",
  "token_type": "Bearer",
  "expires_in": 3577,
  "id_token": "eyJhbGciOiJS...veryLongStringHere"
}

Теперь отправьте этот access_token на ваш серверный сервер для проверки подлинности так же, как вы делали во время GoogleAuthUtil и PlusAPI.

Надеюсь, это поможет:) Особая благодарность BNK!

Ответ 3

В случае, если у кого-то еще возникают проблемы с окончательным запросом на захват маркера доступа из Google. ниже - проверенный и действующий подход на 11-01-2018. Использование retrofit2.

Прежде всего, здесь ссылка на google doc о конечной точке обмена токенами: https://developers.google.com/identity/protocols/OAuth2WebServer#exchange-authorization-code

public interface GoogleService {

@POST("token")
@FormUrlEncoded
@Headers("Content-Type:application/x-www-form-urlencoded")
Call<GoogleAuthData> getToken(
        @Field("grant_type") String grantType,
        @Field("client_id") String clientId,
        @Field("client_secret") String clientSecret,
        @Field("redirect_uri") String redirectUri,
        @Field("code") String code);
}

Затем назовите его следующим образом:

Call<GoogleAuthData> call = RetroClient.getGoogleService().getToken(
            "authorization_code", context.getString(R.string.server_client_id),
            context.getString(R.string.server_client_secret), "", authCode);