无法退出 Google OAuth2

Posted

技术标签:

【中文标题】无法退出 Google OAuth2【英文标题】:Can't signOut of Google OAuth2 【发布时间】:2017-09-11 22:53:13 【问题描述】:

我无法使用 Google signOut() 退出我已登录的 oAuth 会话。

例如,我粘贴了以下代码,直接取自 Google 快速入门网站... https://developers.google.com/google-apps/calendar/quickstart/js

我已将其保存到网站上的 1.htm 文件中,并正在尝试驱动 Google API。

当我从我的 API 控制台使用 OAuth 2.0 客户端 ID(未在附加代码中显示)时,我能够登录并查看我的日历事件。但是,当单击“退出”按钮时,我并没有退出。

点击退出后,下面的代码肯定会运行...

但是,它并没有让我退出。从控制台运行,我看到它仍然认为我已登录...

我正在监听 signIn 我们的 signOut 状态的任何变化...

但是对于signOut(),回调永远不会被命中...

最后,如果我从开发者控制台尝试整个事情......

    显示 gapi.auth2 表示我已登录 手动退出命令 显示 gapi.auth2 说我仍然登录

如何修改此代码以使 signOut() 工作?

<!DOCTYPE html>
<html>
<head>
    <title>Google Calendar API Quickstart</title>
    <meta charset='utf-8' />
</head>
<body>

<p>Google Calendar API Quickstart</p>

<!--Add buttons to initiate auth sequence and sign out-->
<button id="authorize-button" style="display: none;">Authorize</button>
<button id="signout-button" style="display: none;">Sign Out</button>

<pre id="content"></pre>

<script type="text/javascript">
    // Client ID and API key from the Developer Console
    var CLIENT_ID = 'MY OAUTH CLIENT ID';

    // Array of API discovery doc URLs for APIs used by the quickstart
    var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];

    // Authorization scopes required by the API; multiple scopes can be
    // included, separated by spaces.
    var SCOPES = "https://www.googleapis.com/auth/calendar";

    var authorizeButton = document.getElementById('authorize-button');
    var signoutButton = document.getElementById('signout-button');

    /**
     *  On load, called to load the auth2 library and API client library.
     */
    function handleClientLoad() 
        gapi.load('client:auth2', initClient);
    

    /**
     *  Initializes the API client library and sets up sign-in state
     *  listeners.
     */
    function initClient() 
        gapi.client.init(
            discoveryDocs: DISCOVERY_DOCS,
            clientId: CLIENT_ID,
            scope: SCOPES
        ).then(function () 
            // Listen for sign-in state changes.
            gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);

            // Handle the initial sign-in state.
            updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
            authorizeButton.onclick = handleAuthClick;
            signoutButton.onclick = handleSignoutClick;
        );
    

    /**
     *  Called when the signed in status changes, to update the UI
     *  appropriately. After a sign-in, the API is called.
     */
    function updateSigninStatus(isSignedIn) 
        if (isSignedIn) 
            authorizeButton.style.display = 'none';
            signoutButton.style.display = 'block';
            listUpcomingEvents();
         else 
            authorizeButton.style.display = 'block';
            signoutButton.style.display = 'none';
        
    

    /**
     *  Sign in the user upon button click.
     */
    function handleAuthClick(event) 
        gapi.auth2.getAuthInstance().signIn();
    

    /**
     *  Sign out the user upon button click.
     */
    function handleSignoutClick(event) 
        gapi.auth2.getAuthInstance().signOut();
    

    /**
     * Append a pre element to the body containing the given message
     * as its text node. Used to display the results of the API call.
     *
     * @param string message Text to be placed in pre element.
     */
    function appendPre(message) 
        var pre = document.getElementById('content');
        var textContent = document.createTextNode(message + '\n');
        pre.appendChild(textContent);
    

    /**
     * Print the summary and start datetime/date of the next ten events in
     * the authorized user's calendar. If no events are found an
     * appropriate message is printed.
     */
    function listUpcomingEvents() 
        gapi.client.calendar.events.list(
            'calendarId': 'primary',
            'timeMin': (new Date()).toISOString(),
            'showDeleted': false,
            'singleEvents': true,
            'maxResults': 10,
            'orderBy': 'startTime'
        ).then(function (response) 
            var events = response.result.items;
            appendPre('Upcoming events:');

            if (events.length > 0) 
                for (i = 0; i < events.length; i++) 
                    var event = events[i];
                    var when = event.start.dateTime;
                    if (!when) 
                        when = event.start.date;
                    
                    appendPre(event.summary + ' (' + when + ')')
                
             else 
                appendPre('No upcoming events found.');
            
        );
    

</script>

<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function();handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>

【问题讨论】:

【参考方案1】:

尝试使用revoking token HTTP/REST 方法:

要以编程方式撤销令牌,您的应用程序会发出请求 到https://accounts.google.com/o/oauth2/revoke 并包含令牌 作为参数:

curl -H "Content-type:application/x-www-form-urlencoded" \
        https://accounts.google.com/o/oauth2/revoke?token=token

令牌可以是访问令牌或刷新令牌。如果令牌是 一个访问令牌,它有一个相应的刷新令牌,刷新 令牌也将被撤销。

【讨论】:

那行得通。但是,我想通过 JS API 来实现。这是怎么做到的? 尝试使用 GoogleAuth.disconnect() 的 Javascript 示例 here;其中 GoogleAuth = gapi.auth2.getAuthInstance(); 谢谢。那行得通。奇怪的 signOut 不起作用。看起来很简单。 我明白你的意思。但是除非有人专门编写,否则方法不起作用。在这种情况下,编码器选择的方法名称是 disconnect() 而不是 signOut()。【参考方案2】:

其他选项是将其添加到网页:

<a href="#" onclick="signOut();">Sign out</a>
<script>
  function signOut() 
    var auth2 = gapi.auth2.getAuthInstance();
    auth2.signOut().then(function() 
      console.log('User signed out.');
    );
  
</script>

更多信息https://developers.google.com/identity/sign-in/web/sign-in

【讨论】:

以上是关于无法退出 Google OAuth2的主要内容,如果未能解决你的问题,请参考以下文章

OAuth2

Pixel因忘记退出Google账号导致刷机无法跳过wifi设置

Google 使用 g-plus 最新 API 在 android 中登录和注销

Google Play 管理中心 - 无法编辑草稿

无法登陆Google,与Google服务器通信时出现问题,怎么回事?

检测从 Google Play UI 退出