如何从使用OAuth2登录Google的应用程序中注销?

109

在我的应用程序中,我使用jsapi实现了Google退出登录。

我使用以下网址 https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=xxxxxx 连接到Google,然后使用以下网址 https://www.googleapis.com/plus/v1/people/xxxxxx 从 Google 用户资料获取用户数据。

现在,我需要在用户点击应用程序按钮时从Google退出登录。如何在JavaScript中实现这一点,或者每次用户登录时都必须询问Google登录页面。

我尝试过 approval_prompt=force,但似乎没有起作用。

12个回答

298

OAuth概述:用户是否是他/她自己?

我不确定你是否使用OAuth登录Stack Overflow,比如“使用Google登录”选项,但当你使用此功能时,Stack Overflow只是询问Google是否知道你是谁:

“嘿Google,这个Vinesh家伙声称vinesh.e@gmail.com是他,这是真的吗?”

如果你已经登录了,Google会回答YES。如果没有,Google会说:

“稍等一下Stack Overflow,我将验证这个人,如果他能输入正确的Google帐户密码,那么就是他。”

当你输入Google密码时,Google会告诉Stack Overflow你是谁,并将你登录。

当你退出应用程序时,你正在退出你的应用程序:

这里是新手开发人员在OAuth上有点困惑的地方... Google、Stack Overflow、Assembla、Vinesh的非常酷的webapp都是不同的实体,Google对于你在Vinesh的酷Web应用程序上的帐户以及反之亦然除了通过API访问配置文件信息所暴露的内容外一无所知。

当你的用户退出时,他或她并没有退出Google,他/她正在退出你的应用程序、Stack Overflow、Assembla或者使用Google OAuth来验证用户的任何Web应用程序。

事实上,我可以退出所有我的Google帐户,仍然登录Stack Overflow。一旦你的应用程序知道用户是谁,那个人就可以退出Google。Google不再需要了。

话虽如此,你要做的是让用户从一个并不属于你的服务中注销。想象一下:作为一个用户,如果我用我的Google帐户登录5个不同的服务,那么第一次我从其中一个注销时,我必须再次登录我的Gmail帐户,因为该应用程序开发人员决定,在我注销他的应用程序时,我也应该注销Google?这会很快变得烦人。简而言之,你真的不想这样做...

好吧,无论如何,我仍然想让用户从Google注销,告诉我如何做到这一点?

话虽如此,如果你仍然想让用户从Google注销,并意识到你可能会干扰他们的工作流程,你可以从他们的Google服务注销按钮动态构建注销URL,然后使用img元素或脚本标记调用它:

<script type="text/javascript" 
    src="https://mail.google.com/mail/u/0/?logout&hl=en" />

或者

<img src="https://mail.google.com/mail/u/0/?logout&hl=en" />

或者

window.location = "https://mail.google.com/mail/u/0/?logout&hl=en";

如果您将用户重定向到注销页面,或者从未受跨域限制的元素中调用它,则用户将从 Google 中注销。请注意,这并不一定意味着用户将从您的应用程序中注销,只是从 Google 中注销了。 :)
总之,您需要记住的是,当您注销应用程序时,您不需要让用户重新输入密码。这就是整个目的!它对 Google 进行身份验证,因此用户不必在每个他或她使用的 Web 应用程序中一遍又一遍地输入密码。需要一些适应时间,但要知道,只要用户已登录 Google,您的应用程序就不需要担心用户是否是真正的本人。
我在一个项目中与您一样使用 Google Profile 信息和 OAuth 进行了相同的实现。我尝试了您想要尝试的同样的事情,当他们不得不一次又一次地登录 Google 时,这确实开始让人生气,所以我们停止了让他们从 Google 注销。 :)

12
感谢您宝贵的时间和详细描述。但我的客户持有不同的观点。假设用户使用公共系统通过Google登录应用程序并退出该应用程序。他可能认为他也已从Google退出,但事实上并非如此!稍后使用该系统的任何其他用户都将获得访问Google帐户的权限。 - Vinesh EG
15
那么您的用户也需要退出谷歌账户。关键是,他们要同时登录两个服务。您的用户需要学习如何使用OAuth。 :) 我建议您教育您的客户和用户。如果必要,可以给他们演示。这个实现并不需要很长时间,当您意识到它有多糟糕时,可以轻易地撤销它。:) 直到我亲身尝试过,才相信这会让每次从LoopToDo登出后重新登录谷歌非常麻烦。考虑加上一个提示信息:“您已经退出了Vinesh的酷应用,请不要忘记 >退出谷歌账户<!” - jamesmortensen
2
我正在开发一个混合移动应用程序(Ionic),使用Google OAuth,并且遇到了同样的问题,因为我想使用不同的Google帐户登录,但我总是自动登录。目前,我正在进行JSONP异步请求以从https://accounts.google.com/logout注销用户,但这是一种“肮脏”的技巧,并会向控制台输出错误,但找不到任何其他有效的解决方案。如果有人知道更好的方法,请告诉我。由于它是包含在Web视图中的混合移动应用程序,因此我没有注销用户从其他服务的问题。 - nunoarruda
3
然而,如果对用户来说,“断开连接”一词意味着完全注销应用程序。因为它会自动重新登录而无需再次输入凭据,这会导致两个问题:用户会疑惑我刚才断开连接了,但我的信息不应该被保留;第二个问题是用户无法登录到另一个帐户,因为它会始终自动登录,除非授权提供者提供一个强制登录的方法。因此,在这种情况下,注销是可取的,这样可以使 cookie 无效,并且您不再需要担心在客户端上如何管理它。 - darewreck
1
多天以来一直在寻找答案。这绝对是最好的用简单易懂的英语解释Google观点、G身份验证服务和特定应用程序使用它之间关系的文章!对于数据敏感的应用程序端用户(包括我),关键是,你们的应用程序提供了一个“注销”按钮,不过我永远都没有必要使用,因为我一直处于登录状态中,甚至不需要确认我的身份!糟糕极了!由于每个应用程序都使用G的身份验证clientID并且是idToken的一部分,如果Google提供“仅注销此应用程序”的选项,则可以解决这个问题。Google、应用程序开发人员和用户都可以获益!希望Google会听取这个建议。 - Jeb50
显示剩余15条评论

27

您可以注销并重定向到您的网站:

var logout = function() {
    document.location.href = "https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=http://www.example.com";
}

1
终于!谢谢!我已经试了整整一天,想找到如何注销以防止下一个用户只需点击即可登录为上一个用户,而不知道电子邮件或密码... - some
1
它不起作用,因为在另一个选项卡中打开相同的页面就足以让您再次登录... - Bartłomiej Semańczyk
1
谢谢。我已经寻找这个东西多年了。 - sakib11
是的,它可以工作,但有谷歌警告页面提示我们将被重定向到... - Kattabomane
3
这将注销你在所有站点上的所有 Google 帐户。 - Shaybc
如何避免重定向页面? - Manohar Pamishetty

7
对我而言,它有效(Java - Android)。
void RevokeAcess()
{
    try{
    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost("https://accounts.google.com/o/oauth2/revoke?token="+ACCESS_TOKEN);
    org.apache.http.HttpResponse response = client.execute(post);
    }
    catch(IOException e)
    {
    }
    CookieManager.getInstance().removeAllCookie(); // this is clear the cookies which tends to same user in android web view
}

你需要在Android的AsyncTask中调用这个函数。


2
虽然这样做是可行的,但问题实际上是关于JavaScript而不是Java。 - jamesmortensen
2
听起来很可怕,只需要一个令牌,就可以使用暴力破解的方式强制注销所有人的谷歌账户。 - Archimedes Trajano
它不会从设备中注销您,它只会注销应用程序(在Android中)。 - Vinoj John Hosan
3
从查看一些 google oauth2 文档 可知,一个典型的访问令牌长这样:"1/fFAGRNJru1FTz70BzhT3Zg"。假设 "1/" 部分只是为了方便人类识别数字。你仍然有两个字母表(大写和小写)加上十个数字字符,并且长度为22个字符。这是 22^(26*2+10) 的结果,约等于 已知宇宙中的原子数量。祝你在 HTTP 上暴力破解好运。;) - Chris Balogh
这似乎没有撤销刷新令牌,而在删除 cookie 之前可能会被窃取(如果它存储在那里)。 - Ondrej Galbavý

3

退出应用程序但不退出Gmail账户:

window.gapi.load('auth2', () => {
      window.gapi.auth2
        .init({
          client_id:
            '<Your client id configired on google console>'
        })
        .then(() => {
          window.gapi.auth2
            .getAuthInstance()
            .signOut()
            .then(function() {
              console.log('User signed out.');
            });
        });
    });

我在我的 ReactJs 代码中使用了上述内容。


1
非常好用!特别是当您所在的页面不再支持gapi时,这实际上可以初始化和注销。 - oavi

2

2

这个功能可以让用户退出应用程序,但无法退出 Google。

var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
  console.log('User signed out.');
});

来源:https://developers.google.com/identity/sign-in/web/sign-in

这是一个有关IT技术的网站,提供了有关Google身份验证登录的信息。在使用此功能时,请确保您已经按照说明进行了设置,并遵循相关的安全措施以确保您的账户安全。如果您需要帮助或有任何疑问,请查看文档或联系技术支持团队。

1
这并不会完全注销用户的 Google 帐户。它只会销毁您使用的“AuthInstance”。您的本身就说了... "您可以让用户在不注销 Google 的情况下从您的应用程序中注销..." - Roshana Pitigala
@RoshanaPitigala 更新了答案以做出具体说明。这个答案是针对问题标题的回答,但是一旦你仔细阅读问题,你就会发现标题写错了。这个答案适用于所有根据问题标题过来的人。 - CamHart

1

这段代码将会注销用户

    <script>
      function signOut() 
      {
        var auth2 = gapi.auth2.getAuthInstance();
        auth2.signOut().then(function () {   
        console.log('User signed out.');   
        auth2.disconnect();   
      }); 
        auth2.disconnect();
      } 
    </script>

1
Ouath 只是使 Google 实例为空,因此它会使您退出 Google。现在这就是架构的设计方式。如果您从应用程序注销,则注销 Google 是一项麻烦的工作,但如果要求规定相同,则无法帮助。因此,请将以下内容添加到您的 signOut() 函数中。我的项目是一个 Angular 6 应用程序:
document.location.href = "https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=http://localhost:4200";
这里的 localhost:4200 是我的应用程序的 URL。如果您的登录页面是 xyz.com,则输入该页面的 URL。

0
我希望我们能通过在登录时将令牌存储在会话中,并在单击注销时访问该令牌来实现这一目标。
    String _accessToken=(String)session.getAttribute("ACCESS_TOKEN");
    if(_accessToken!=null)
    {
        StringBuffer path=httpRequest.getRequestURL();
        reDirectPage="https://www.google.com/accounts/Logout?
        continue=https://appengine.google.com/_ah/logout?
        continue="+path;
    }
    response.sendRedirect(reDirectPage);

0
1. Try this code, if you are using onSignIn() function
2.
        <script src="https://apis.google.com/js/platform.js?onload=onLoad" async defer></script>
       <script>
       function signOut() {
       onLoad();
       var auth2 = gapi.auth2.getAuthInstance();
       auth2.signOut().then(function () {
       console.log('User signed out.');
       if(auth2.isSignedIn)
       {
          auth2.isSignedIn.set(false);
       }
       });
       }
       function onLoad() {
          gapi.load('auth2', function() {
            gapi.auth2.init();
          });
        }
        </script>

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