使用Google Sign in进行授权的Google Cloud Endpoints

5
我有一个使用Google Cloud Endpoints的应用程序。一些方法需要授权,所以我遵循了this教程。这需要GET_ACCOUNTS权限。
我正在更新该应用程序以使用运行时权限。我不想请求读取联系人的权限,但GET_ACCOUNTS属于同一组。因此,我正在寻找在没有GET_ACCOUNTS权限的情况下使用授权的方法。
我认为Google登录可能有效,但我无法找到使用Google登录结果的方法。
这是用于创建对象以调用端点的代码:
Helloworld.Builder helloWorld = new Helloworld.Builder(AppConstants.HTTP_TRANSPORT, AppConstants.JSON_FACTORY,credential);

凭据对象必须是一个HttpRequestInitializer,但从Google登录中获取的是GoogleSignInAccount
那么,这是否可能?应该如何做到这一点?
1个回答

6

我终于找到了解决方案。使用在这里找到的教程。

你必须在GoogleSignInOptions中添加客户端ID:

 GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(CLIENT_ID)
            .requestEmail()
            .build();

在完成教程后,您最终将获得一个GoogleSignInAccount。 将GoogleSignInAccount中的令牌设置为GoogleCredential对象:
GoogleCredential credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport())
            .setJsonFactory(JacksonFactory.getDefaultInstance())
            .build();
credential.setAccessToken(GoogleSignInAccount.getIdToken());

这个凭证已经可以用于向Google Cloud Enpoints发起身份验证调用。
请注意,您必须从CLIENT_ID中删除“server:client_id:”部分。因此,如果您正在使用以下内容:
credential = GoogleAccountCredential.usingAudience(this,
    "server:client_id:1-web-app.apps.googleusercontent.com");

您的客户端ID将是:

CLIENT_ID = "1-web-app.apps.googleusercontent.com"

请注意,令牌的有效期是有限的(在我的测试中大约为1小时)。
为避免1小时令牌限制,请在每次调用终端节点之前使用GoogleSignInApi.silentSignIn()获取新的令牌。例如,如果您不在UI线程中:
GoogleSignInOptions options = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail()
                .requestIdToken(CLIENT_ID)
                .build();
GoogleSignInClient client = GoogleSignIn.getClient(context, options);
GoogleSignInAccount user = Tasks.await(getGoogleSignInClient(context).silentSignIn());

// Use the new user token as before 
GoogleCredential credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport())
        .setJsonFactory(JacksonFactory.getDefaultInstance())
        .build();
credential.setAccessToken(user.getIdToken());

对我来说不起作用:后端接收到一个空的com.google.appengine.api.users.User,这是授权失败时发生的情况。你遇到过同样的问题吗?谢谢。 - Creos
谢谢,实际上我已经解决了客户端ID的问题,我的问题更多在后端。找到了这个解决方案https://dev59.com/5F8e5IYBdhLWcg3wyM0r。坦率地说,端点文档网站关于@authenticators功能的信息太少了,这是疯狂的https://cloud.google.com/appengine/docs/java/endpoints/javadoc/com/google/api/server/spi/config/Authenticator。 - Creos
哦,等等,你是说你能够使用默认验证器使其工作(即在服务器上不明确使用GoogleTokenIdVerifier)? - Creos
是的,我从未在服务器上使用任何显式认证器代码。我只需将用户参数添加到方法中即可。我目前只使用用户的电子邮件,因此我不知道ID是否已设置(与您的第一条评论相关)。 - 9and3r
感谢提供ID的提示。我应该改用它。目前我还没有重新认证的解决方案。似乎可以在每次调用中调用登录意图,用户只需要在第一次输入,但我认为这不是一个好的解决方案,所以我正在寻找更好的解决方案。我使用了这个教程来设置端点 https://cloud.google.com/appengine/docs/java/endpoints/auth。其中一个问题是,我花了很长时间才弄清楚在Android应用程序中使用的CLIENT_ID是名为WEB_CLIENT的客户端ID(相当令人困惑)。除此之外,我没有遇到任何设置默认验证器的问题。 - 9and3r
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接