如何在用户从AndroidloginGmail后访问令牌?
我正在关注GoogleloginAndroid 。 现在我可以获得idToken,但是之前使用的后端服务器期望访问令牌,因为我之前使用的是Google+login。 现在我不想改变我的服务器端。 但是,我仍然可以如何使用Googlelogin并在我的android应用程序中获取访问令牌,以便我可以validation我的用户到我的后端服务器。
我之前使用的是GooglePlay Service 7.5.0,现在我正在使用GooglePlay Service最新的8.3.0。
根据您的要求,您可以使用以下代码:
首先,确保您有一个有效的Web OAuth 2.0客户端ID:
<!-- 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's 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中查看完整的代码
结果,如果您使用该示例,如下图所示:
然后,您可以按照以下Google文档中提到的步骤进行操作(从第3步开始, 使用HTTPS POST将身份validation码发送到您应用程序的后端 ):
适用于Android的Googlelogin – 启用服务器端访问
更新:从注释,如果你想直接从android客户端应用程序获得访问令牌,请使用下面的示例代码(用您的client_id,client_secret和authentication代码取代)
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'
(版本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" }
BNK有它的大部分。 Activity类与BNKs只有在获得onActivityResult()
方法中的GoogleSignInAccount
时添加OkHttp部分的答案相同。
但是,我仍然得到OkHttp请求部分的错误。 最后经过Postman的一些testing(和部分运气),我发现我错过了id_token参数。 OkHttp请求缺less一个参数,即id_token。 使用您从GoogleSignInAccount获得的ID令牌
GoogleSignInAccount acct = result.getSignInAccount(); String idTokenString = acct.getIdToken();
现在使用这个idTokenString以及BNK答案的OkHttp部分中的所有参数,就像这样
... 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发送到您的后端服务器进行身份validation,就像您在GoogleAuthUtil和PlusAPI时代所做的一样。
希望这有助于:)特别感谢BNK!