获取Google一次性授权码

时间:2014-01-27 18:56:28

标签: android ruby-on-rails google-authentication google-cloud-platform

我无法从Google获取一次性授权码。我试图从Android客户端获取授权代码,以便我可以将其发送到我的Rails后端(Web客户端)。

在我的Google Cloud Developer Console中,我有一个包含两个客户端ID的应用程序:

  1. Web应用程序的客户端ID(对于我的rails后端)

  2. Android应用程序的客户端ID(适用于我的Android客户端)。使用的SHA1来自〜/ .android / debug.keystore

  3. 假设Web应用程序客户端ID为12345.apps.googleusercontent.com

    假设Android客户端ID为67890.apps.googleusercontent.com

    这是我的一些代码:

    private final static String WEB_CLIENT_ID = "12345.apps.googleusercontent.com";
    private final static String GOOGLE_CALENDAR_API_SCOPE = "audience:server:client_id:" + WEB_CLIENT_ID;
    
    private void getAndUseAuthToken(final String email) {
            AsyncTask task = new AsyncTask<String, Void, String>() {
                @Override
                protected String doInBackground(String... emails) {
                    try {
                        return GoogleAuthUtil.getToken(AddExternalCalendarsActivity.this, emails[0], GOOGLE_CALENDAR_API_SCOPE);
                    } catch (UserRecoverableAuthException e) {
                        startActivityForResult(e.getIntent(), IntentConstants.REQUEST_GOOGLE_AUTHORIZATION);
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (GoogleAuthException e) {
                        e.printStackTrace();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
    
                    return null;
                }
    
                @Override
                protected void onPostExecute(String authToken) {
                    if (authToken != null) {
                        saveTokenAndGetCalendars(email, authToken);
                    }
                }
            };
    
            String[] emails = new String[1];
            emails[0] = email;
            task.execute(emails);
        }
    

    一些额外的说明

    • 我正在点击GoogleAuthException并收到“未知”作为留言详情

    • 我无法在此项目的Google云端控制台权限中添加其他成员 - 添加新成员时,弹出窗口显示“服务器错误。哎呀!我们不好。”。我已经两次向Google发送反馈。

    • 我指的是documentation。请注意下面的引用。通过“修复”,他们是否说我不需要在GOOGLE_CALENDAR_API_SCOPE变量中添加受众:server:client_id ?我已经尝试过和不使用,但仍然得到相同的GoogleAuthException。

      

    在这种情况下,Android应用可以调用   GoogleAuthUtil.getToken()方法代表任何Google   设备上的帐户,范围参数值为   观众:服务器:CLIENT_ID:9414861317621.apps.googleusercontent.com。   前缀受众:server:client_id:是固定的,其余部分是   scope string是Web组件的客户端ID。

    • 如果我使用此范围,我可以通过设备上的谷歌进行身份验证。但是,我读过的文档表明,我需要在范围内使用服务器Web客户端ID(与Android客户端ID在同一个google控制台项目中),以便服务器代表google api在Android客户端上授权的用户:

      private final static String GOOGLE_CALENDAR_API_SCOPE = "oauth2:https://www.googleapis.com/auth/calendar";

    更新1

    我最初补充说: 我第一个问题的原因 - 我正在点击GoogleAuthException并收到“Unknown”作为消息详细信息 - 这是我在云控制台中添加android客户端ID时犯的错误。 SHA1是正确的但我没有正确输入包名称。当我的android包实际上是com.company.android.app时,我使用了com.company.app。 原始问题中的代码运行正常。只需确保您的Google云端控制台项目中包含所有必需的客户端。

    但另一个问题仍然存在。当我将从 GoogleAuthUtil.getToken()返回的一次性授权令牌发送到Rails后端,然后尝试将其交换为access_token和refresh_token时,我得到以下内容:

    Signet::AuthorizationError:
      Authorization failed.  Server message:
      {
          "error" : "invalid_grant"
      }
    

    这个google documentation和几个SO帖子表明我需要设置access_type=offline。但我认为,当您从Web服务器请求一次性授权代码和脱机访问时。我正在尝试从Android客户端请求一次性授权代码并将其发送到Web服务器。

    这可以通过 GoogleAuthUtil.getToken()实现吗?

    更新2

    即使您只是尝试访问日历,Google Plus登录也必须在范围内:

    private final static String GOOGLE_CALENDAR_API_SCOPE = "oauth2:server:client_id:" + WEB_CLIENT_ID + ":api_scope:https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/calendar";
    

    SO post很有帮助。此外,Google's Cross Client identity documentation确实声明:

      

    [注:此政策逐步推出。目前,当涉及访问令牌时,它仅适用于请求的范围包括https://www.googleapis.com/auth/plus.login.]

    如果令牌交换在Rails后端工作,我会在答案中总结。

2 个答案:

答案 0 :(得分:3)

有两件事为我解决了这个问题:

  1. 确保在同一个Google Cloud Console项目中正确设置了Android和Web客户端ID。

  2. 使用正确的范围。即使您只访问日历api,也需要登录:

    //正在交换用于访问和刷新令牌的身份验证代码的Web服务器的ID

    private final static String WEB_CLIENT_ID =“12345.apps.googleusercontent.com”; private final static String GOOGLE_CALENDAR_API_SCOPE =“oauth2:server:client_id:”+ WEB_CLIENT_ID +“:api_scope:https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/calendar”;

答案 1 :(得分:0)

这就是我所做的:

final String authToken = GoogleAuthUtil.getTokenWithNotification (this.context, account.name, "oauth2:" + AuthUtils.profileScope, new Bundle (),
                Contract.authority, new Bundle ());

但是普通的getToken应该对前台活动的工作方式相同。

获取此令牌,以一种可以像HTTP标头(通过HTTPS)一样使用它的方式将其发送到服务器。只要服务器作用域是用于获取令牌的作用域的子集,就不应该有问题。服务器使用服务器ID,而android客户端使用android客户端ID。

您应该将范围设置为:

oauth2:https://www.googleapis.com/auth/calendar

oauth2:https://www.googleapis.com/auth/calendar.readonly

请参阅https://developers.google.com/google-apps/calendar/auth

编辑:好的,我知道你要做什么。范围值是一个以空格分隔的列表,因此您可能需要将受众:server:client_id:附加到您的范围,如:

"oauth2:https://www.googleapis.com/auth/calendar audience:server:client_id:12345-your-web-component-client-id"