Search code examples
c++oauth-2.0google-oauthboost-beast

OAuth2 with beast boost returns temporary redirect 307


I'm trying to implement an app with access to google drive in beast boost C++ usingoauth2 authentication.

https://developers.google.com/identity/protocols/OAuth2ForDevices

I try to get the user code in Postman with the following POST request:

POST /o/oauth2/device/code HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache


scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&client_id=610490019085-l1v2mv7lv95lu7cr111vbtqmp1bigv42.apps.googleusercontent.com

And it works perfectly fine, returning:

{
"verification_url": "https://www.google.com/device",
"expires_in": 1800,
"interval": 5,
"device_code": "AH-1Ng0IgBnIXIUeltwDoL7AwNExNTT0rozdxD5FMnP8dip4DaDi8_XtzK2aVT92YKYmYa7KWqHRVqw5AmJCDtalzK3k6pvbFw",
"user_code": "LWZY-BDXD"

}

Now I want to do the same request in C++ using boost, with the following code snippet for the request:

http::request<http::string_body> req{http::verb::post, "/o/oauth2/device/code", 11};

req.set(http::field::host, "accounts.google.com");
req.set("Cache-Control", "no-cache");
req.set(http::field::content_type, "application/x-www-form-urlencoded");
req.body() = "scope=https://www.googleapis.com/auth/drive.file&client_id=610490019085-l1v2mv7lv95lu7cr111vbtqmp1bigv42.apps.googleusercontent.com";

req.prepare_payload();

This one returns:

HTTP/1.0 307 Temporary Redirect
Content-Type: text/html; charset=UTF-8
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Date: Mon, 14 May 2018 11:06:01 GMT
Location: https://accounts.google.com/o/oauth2/device/code
Content-Length: 232
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE

<HTML>
<HEAD>
<TITLE>Temporary Redirect</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Temporary Redirect</H1>
The document has moved <A HREF="https://accounts.google.com/o/oauth2/device/code">here</A>.
</BODY>
</HTML>

Any ideas how I can get the JSON returned as with Postman?

Thank You!


Solution

  • Beast is a low-level protocol library, it doesn't know anything about resolving domain names or connecting sockets. It doesn't even know about TCP/IP, just how to serialize and deserialize HTTP/1 messages over objects which meet Asio's stream concept requirements (examples: SyncReadStream, or AsyncWriteStream). You have to handle redirects yourself. If you get a redirect response, extract the Location field value and parse the URI, resolve the domain, and then issue another GET request for the specified resource.

    It is my hope that other folks (maybe you?) will build on top of beast and provide higher-level functionality like this in the form of open source libraries.