通过使用Android的Google登录来获取Google API的访问令牌的首选方法是什么?

问题描述 投票:1回答:1

我正在开发一个可直接连接到Google Books API的android应用。其工作的一部分还在于获取用户的私人图书数据。 (例如书架)

我使用Android的Google登录进行身份验证。但是,我也需要访问令牌来获得请求的授权。

问题:-

Google登录在处理身份验证部分方面做得很好,但是由于它没有提供任何方法,因此我不得不实施授权部分。以下是我想出授权的有效解决方案。

问:我当前的解决方案(如下所示)是否可以(如果不是首选方式)来获取访问令牌?

当前解决方案:-

首先,我使用requestServerAuthCode(...)方法请求授权代码并传递了Web应用客户端ID(由Google API控制台自动为Google登录创建的:-]

...
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestScopes(new Scope(SCOPE_BOOKS))
                .requestServerAuthCode(WEB_APP_CLIENT_ID)  //NOTE: this was auto generated for Google Sign-in along with my android client id.
                .requestEmail()
                .build();
...

然后,我使用接收到的身份验证令牌(通过调用getServerAuthCode())并使用它来手动获取访问令牌,

MainActivity.java

...
Task<GoogleSignInAccount> accountTask = GoogleSignIn.getSignedInAccountFromIntent(data);
GoogleSignInAccount account = accountTask.getResult(ApiException.class);
new TokenTask().execute(account.getServerAuthCode());
...

TokenTask.java

@Override
    protected String doInBackground(String... authToken) { 

            //Time to get the access token from the authToken 
            ...
            final URL url = new URL("https://www.googleapis.com/oauth2/v4/token");

            conn = (HttpsURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            ...

            final StringBuilder b = new StringBuilder();
            b.append("code=").append(authToken[0]).append('&')
                    .append("client_id=").append(WEB_APP_CLIENT_ID).append('&')   //NOTE: this client id was auto generated for Google Sign-in along with my android client id.
                    .append("client_secret=").append(WEB_APP_CLIENT_SECRET).append('&')
                    .append("redirect_uri=").append("").append('&')
                    .append("grant_type=").append("authorization_code");

            final byte[] postData = b.toString().getBytes(StandardCharsets.UTF_8);

            os = conn.getOutputStream();
            os.write(postData);
/*
The response contains fields such as: access_token, expires_in, refresh_token etc...
*/


            final int responseCode = conn.getResponseCode();
            if (200 <= responseCode && responseCode <= 299) {
                is = conn.getInputStream();
                isr = new InputStreamReader(is);
                br = new BufferedReader(isr);
            } else {
                Log.d("Error:", conn.getResponseMessage());
                return null;
            }

            b.setLength(0);
            String output;
            while ((output = br.readLine()) != null) {
                b.append(output);
            }

            final JSONObject jsonResponse = new JSONObject(b.toString());
            String mAccessToken = jsonResponse.getString("access_token");

注:-

我从here获得了有关此解决方案的想法。尽管传递到requestServerAuthCode(...)的Web客户端ID应该是我们服务器端应用的客户端ID。但由于我没有任何网络应用程序,因此我使用由Google api控制台自动生成的网络客户端ID进行Google登录(在上面的代码中声明为WEB_APP_CLIENT_ID)。

android oauth-2.0 google-signin google-oauth2 google-books
1个回答
1
投票

这些天,您应该在移动应用中使用授权码流(PKCE),作为recommended by Google。在登录时提供code_challenge而不是在交换令牌的授权码时提供code_verifier,而不是客户机密。

出于兴趣,我的Android Blog Post显示了一些带有上述参数的示例消息。它还有一个可以运行的代码示例,以及有关用户体验和令牌存储的一些内容。

© www.soinside.com 2019 - 2024. All rights reserved.