用MFC撤销Google访问令牌

用MFC撤销Google访问令牌,mfc,google-oauth,Mfc,Google Oauth,我已经看到了一些关于这方面的问题,但它们不完全在我的场景中。除非我错过了什么 以下是我撤销谷歌访问权限的方式: bool CCalendarSettingsGooglePage::RevokeGoogleAccess() { CInternetSession iSession; CHttpFile *pWebFile = nullptr; CWaitCursor wait; TCHAR szEr

我已经看到了一些关于这方面的问题,但它们不完全在我的场景中。除非我错过了什么

以下是我撤销谷歌访问权限的方式:

bool CCalendarSettingsGooglePage::RevokeGoogleAccess()
{
    CInternetSession    iSession;
    CHttpFile           *pWebFile = nullptr;
    CWaitCursor         wait;
    TCHAR               szError[_MAX_PATH];
    DWORD               dwStatusCode;
    CString             strError, strToken, strRevokeURL;

    if (m_strGoogleToken == _T(""))
        return true;

    strRevokeURL.Format(_T("https://accounts.google.com/o/oauth2/revoke?token=%s"), (LPCTSTR)m_strGoogleToken);

    // ask user to go online
    if (InternetGoOnline((LPTSTR)(LPCTSTR)strRevokeURL, GetSafeHwnd(), 0))
    {
        TRY
        {
            // our session should already be open
            // try to open up internet session to my URL
            // AJT v10.4.0 Use flag INTERNET_FLAG_RELOAD
            pWebFile = (CHttpFile*)iSession.OpenURL(strRevokeURL, 1,
            INTERNET_FLAG_TRANSFER_BINARY |
            INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD);

            if (pWebFile != nullptr)
            {
                if (pWebFile->QueryInfoStatusCode(dwStatusCode))
                {
                    if (dwStatusCode == 200) // OK!
                    {
                        return true;
                    }
                    else
                    {
                        // There was a problem!
                        strError.Format(_T("Revoke error: %lu"), dwStatusCode);
                        AfxMessageBox(strError, MB_OK | MB_ICONERROR);
                    }
                }
            }
            else
            {
                AfxMessageBox(_T("Revoke error"), MB_OK | MB_ICONERROR);
            }
        }
            CATCH(CException, e)
        {
            e->GetErrorMessage(szError, _MAX_PATH);
            AfxMessageBox(szError, MB_OK | MB_ICONERROR);
        }
        END_CATCH

        // Tidy up
        if (pWebFile != nullptr)
        {
            pWebFile->Close();
            delete pWebFile;
        }
        iSession.Close();
    }
    return false;
}
我的问题是,这种方法并不总是有效的。我发现用户实际上必须在线进入他们的谷歌账户,找到他们的应用程序,然后手动撤销它


是否有更可靠的方法支持撤销访问令牌?

curl
选项根据以下内容撤销令牌:

所以你的方法应该没问题。可能令牌已经无效,Google告诉您它不知道如何处理请求(令牌的生命周期可能很短)

OAuth通常期望使用
“POST”
方法,而不是
“GET”
。您可以尝试使用
“POST”
方法。在MFC中,应如下所示:

DWORD flag = INTERNET_FLAG_SECURE | INTERNET_FLAG_DONT_CACHE |
    INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;

CStringW header;
CStringA query;

{
    CStringW queryW;
    queryW.Format(L"token=%s", token);
    query = CW2A(queryW, CP_UTF8);
}

header.Format(L"\
Content-Type: application/x-www-form-urlencoded\r\n\
Content-length: %d\r\n\
Connection: Close\r\n\
\r\n", query.GetLength());

CInternetSession session;
CHttpConnection *connection = session.GetHttpConnection(L"accounts.google.com", 
    (INTERNET_PORT)INTERNET_DEFAULT_HTTPS_PORT);
if(connection)
{
    CHttpFile *file = connection->OpenRequest(L"POST", 
        L"o/oauth2/revoke", L"http://localhost", 1, NULL, NULL, flag);
    if(file)
    {
        if(file->SendRequest(header, 
            query.GetBuffer(), query.GetLength()))
        {
            DWORD dwRet;
            if (file->QueryInfoStatusCode(dwRet))
            {
                if (dwRet == 200 || dwRet == 400)
                {
                    //success!
                }
            }
        }
        delete file;
    }
    delete connection;
}

上面的代码使用Unicode版本,它必须将UTF-16
query
转换为UTF-8…

实际上,你在说什么令牌?如果OAuth令牌过期或被吊销,应用程序仍将保留在Google应用程序设置中。我的应用程序有一个“身份验证”按钮。显示我的应用程序的同意屏幕。然后列出他们的日历。将存储令牌以供以后进行身份验证。所以他们不会经常被问到。但他们应该能够撤销该授权,这样代币就不再有效了。从设置中删除实际应用程序是一项额外的功能。
dwStatusCode
400表示成功,它只表示令牌已经无效。如果(dwStatusCode==200 | | dwStatusCode==400)返回true;,则应将错误检查更改为
@BarmakShemirani OK。你是说我可以使用现有代码进行更改吗?还是我应该听从你的回答?此外,如果我对我的应用程序使用的范围进行更改,我假设该应用程序需要从他们的帐户中删除,或者授权尝试会自动再次请求同意吗?这是我的猜测。我认为您的一些用户报告在上面显示的代码中看到错误消息
“Revoke error:400”
,他们抱怨。或者您的程序继续使用过期的令牌。因此,如果更改错误条件,问题应该消失。如果您请求刷新令牌,可能还有其他问题。从您自己的计算机上运行更多测试以尝试复制错误。
标志
的值是多少?我添加了标志。我打算删除这篇文章,因为我不确定你自己的GET方法是否有问题。如果您使用此方法,还可以添加
文件->查询fostatuscode
。谢谢。正在尝试。另外,你给我看的页面上的状态是400:对于错误情况,会返回一个状态码400和一个错误码。我只是好奇你关于400的评论,因为它与文件不符。此外,令我惊讶的是,撤销令牌和身份验证实际上并不需要我再次授权应用程序。我猜这是因为该应用程序仍在我同意的应用程序中。因此,用户必须手动删除应用程序。这不能通过编程完成?我为
QueryInfoStatusCode
编辑了这篇文章。我不知道如何从谷歌应用程序设置中删除该程序。
DWORD flag = INTERNET_FLAG_SECURE | INTERNET_FLAG_DONT_CACHE |
    INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;

CStringW header;
CStringA query;

{
    CStringW queryW;
    queryW.Format(L"token=%s", token);
    query = CW2A(queryW, CP_UTF8);
}

header.Format(L"\
Content-Type: application/x-www-form-urlencoded\r\n\
Content-length: %d\r\n\
Connection: Close\r\n\
\r\n", query.GetLength());

CInternetSession session;
CHttpConnection *connection = session.GetHttpConnection(L"accounts.google.com", 
    (INTERNET_PORT)INTERNET_DEFAULT_HTTPS_PORT);
if(connection)
{
    CHttpFile *file = connection->OpenRequest(L"POST", 
        L"o/oauth2/revoke", L"http://localhost", 1, NULL, NULL, flag);
    if(file)
    {
        if(file->SendRequest(header, 
            query.GetBuffer(), query.GetLength()))
        {
            DWORD dwRet;
            if (file->QueryInfoStatusCode(dwRet))
            {
                if (dwRet == 200 || dwRet == 400)
                {
                    //success!
                }
            }
        }
        delete file;
    }
    delete connection;
}