Reputation: 19157
I have seen a few questions on this but they are not quite in my scenario. Unless I missed something.
This is how I revoke Google Access:
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;
}
My problem is that this approach does not always works. I find that a user has to actually go into their Google Account online, locate their apps, and manually revoke it.
Is there a more robust way to support revoking of an access token?
Upvotes: 2
Views: 253
Reputation: 31619
curl
option to revoke token according to Google:
curl -H "Content-type:application/x-www-form-urlencoded" https://accounts.google.com/o/oauth2/revoke?token={token}
So your method should be okay. Maybe the token is already invalid and Google tells you that it doesn't know what to do with the request (the token may have a short life span)
OAuth usually expects "POST"
method instead of "GET"
. You can try the "POST"
method instead. In MFC it would be as follows:
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;
}
Above code uses Unicode version, it has to convert UTF-16 query
to UTF-8...
Upvotes: 2