OAuth flow with Integration: "406 Not Acceptable"


#1

I’m trying to follow the instructions described in here: https://developer.github.com/early-access/integrations/user-identification-authorization/

I first redirect the user to request their GitHub identity with the following:

curl -v -H 'Accept: application/vnd.github.machine-man-preview+json' https://github.com/login/oauth/authorize?client_id=<integration_client_id>&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fauth%2Fgithub%2Fcallback&state=123abcrandom
[1] 43906
[2] 43910
*   Trying 192.30.253.112...
* TCP_NODELAY set
[2]+  Done                    redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fauth%2Fgithub%2Fcallback
* Connected to github.com (192.30.253.112) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: github.com
* Server certificate: DigiCert SHA2 Extended Validation Server CA
* Server certificate: DigiCert High Assurance EV Root CA
> GET /login/oauth/authorize?client_id=<integration_client_id> HTTP/1.1
> Host: github.com
> User-Agent: curl/7.51.0
> Accept: application/vnd.github.machine-man-preview+json
>
< HTTP/1.1 302 Found
< Server: GitHub.com
< Date: Tue, 16 May 2017 21:42:10 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Status: 302 Found
< Cache-Control: no-cache
< Vary: X-PJAX
< Location: https://github.com/login?client_id=<integration_client_id>&return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3D<integration_client_id>
< X-UA-Compatible: IE=Edge,chrome=1
< X-Request-Id: a228a510d7804116262066c6b57d57b2
< X-Runtime: 0.004549
< Content-Security-Policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src render.githubusercontent.com; connect-src 'self' uploads.github.com status.github.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-user-asset-79cafe.s3.amazonaws.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; img-src 'self' data: assets-cdn.github.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; media-src 'none'; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Public-Key-Pins: max-age=5184000; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho="; pin-sha256="k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4="; pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0="; pin-sha256="LvRiGEjRqfzurezaWuj8Wie2gyHMrW5Q06LspMnox7A="; includeSubDomains
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-XSS-Protection: 1; mode=block
< Vary: Accept-Encoding
< X-Served-By: e878d09eac725c89f5f15204c1326660
< X-GitHub-Request-Id: ADBD:6AD7:282CA7:3B2F68:591B7232
<
* Curl_http_done: called premature == 0
* Connection #0 to host github.com left intact
<html><body>You are being <a href="https://github.com/login?client_id=<integration_client_id>&amp;return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3D<integration_client_id>">redirected</a>.</body></html>
[1]+  Done

I then access the URL returned by the response above, which leads me to the GitHub login page and then the “authorize integration” page. I proceed and get redirected to my return_to URL with a code parameter that I use to request an access token:

curl -v -H 'Accept: application/vnd.github.machine-man-preview+json' --data 'client_id=<integration_client_id>&client_secret=<integration_client_secret>&code=<the_token_i_just_received>&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fauth%2Fgithub%2Fcallback&state=123abcrandom' https://github.com/login/oauth/access_token

But then GitHub responds with 406 Not Acceptable:

*   Trying 192.30.253.113...
* TCP_NODELAY set
* Connected to github.com (192.30.253.113) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: github.com
* Server certificate: DigiCert SHA2 Extended Validation Server CA
* Server certificate: DigiCert High Assurance EV Root CA
> POST /login/oauth/access_token HTTP/1.1
> Host: github.com
> User-Agent: curl/7.51.0
> Accept: application/vnd.github.machine-man-preview+json
> Content-Length: 202
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 202 out of 202 bytes
< HTTP/1.1 406 Not Acceptable
< Server: GitHub.com
< Date: Tue, 16 May 2017 21:43:06 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Status: 406 Not Acceptable
< Cache-Control: no-cache
< Vary: X-PJAX
< X-UA-Compatible: IE=Edge,chrome=1
< X-Request-Id: cf27ec9aeb7a078439ca458800c4d00f
< X-Runtime: 0.031884
< Content-Security-Policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src render.githubusercontent.com; connect-src 'self' uploads.github.com status.github.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-user-asset-79cafe.s3.amazonaws.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; img-src 'self' data: assets-cdn.github.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; media-src 'none'; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Public-Key-Pins: max-age=5184000; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho="; pin-sha256="k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4="; pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0="; pin-sha256="LvRiGEjRqfzurezaWuj8Wie2gyHMrW5Q06LspMnox7A="; includeSubDomains
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-XSS-Protection: 1; mode=block
< X-GitHub-Request-Id: D220:6AD7:285438:3B68AE:591B726A
<
* Curl_http_done: called premature == 0
* Connection #0 to host github.com left intact

I’m probably missing something here, but after a few this stuck on this I couldn’t figure it out by myself, so any help would be much appreciated.


#2

Hi again, @volmer :wave:

curl -v -H ‘Accept: application/vnd.github.machine-man-preview+json’ https://github.com/login/oauth/authorize?client_id=<integration_client_id>&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fauth%2Fgithub%2Fcallback&state=123abcrandom

I think you forgot to wrap that URL in quotes. As a result of that, the part after & was dropped and wasn’t sent to GitHub.

Try wrapping that URL in quotes like this:

'https://github.com/login/oauth/authorize?client_id=&lt;integration_client_id&gt;&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fauth%2Fgithub%2Fcallback&state=123abcrandom'

Hope this helps!


#3

Hi @izuzak

I tried the flow again with URLs wrapped in quotes but I still get a 406 back:

curl -v -H 'Accept: application/vnd.github.machine-man-preview+json' 'https://github.com/login/oauth/authorize?client_id=<integration_client_id>&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fauth%2Fgithub%2Fcallback&state=123abcrandom'
*   Trying 192.30.253.112...
* TCP_NODELAY set
* Connected to github.com (192.30.253.112) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: github.com
* Server certificate: DigiCert SHA2 Extended Validation Server CA
* Server certificate: DigiCert High Assurance EV Root CA
> GET /login/oauth/authorize?client_id=<integration_client_id>&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fauth%2Fgithub%2Fcallback&state=123abcrandom HTTP/1.1
> Host: github.com
> User-Agent: curl/7.51.0
> Accept: application/vnd.github.machine-man-preview+json
>
< HTTP/1.1 302 Found
< Server: GitHub.com
< Date: Thu, 18 May 2017 16:14:38 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Status: 302 Found
< Cache-Control: no-cache
< Vary: X-PJAX
< Location: https://github.com/login?client_id=<integration_client_id>&return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3D<integration_client_id>%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A3000%252Fusers%252Fauth%252Fgithub%252Fcallback%26state%3D123abcrandom
< X-UA-Compatible: IE=Edge,chrome=1
< X-Request-Id: a00c313a1c2b4d534529aca2024a48b3
< X-Runtime: 0.019980
< Content-Security-Policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src render.githubusercontent.com; connect-src 'self' uploads.github.com status.github.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-user-asset-79cafe.s3.amazonaws.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; img-src 'self' data: assets-cdn.github.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; media-src 'none'; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Public-Key-Pins: max-age=5184000; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho="; pin-sha256="k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4="; pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0="; pin-sha256="LvRiGEjRqfzurezaWuj8Wie2gyHMrW5Q06LspMnox7A="; includeSubDomains
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-XSS-Protection: 1; mode=block
< Vary: Accept-Encoding
< X-Served-By: 29885c8097c6d503a86029451b2e021c
< X-GitHub-Request-Id: 0A25:6EE7:E7D8D2:156F1F2:591DC86E
<
* Curl_http_done: called premature == 0
* Connection #0 to host github.com left intact
<html><body>You are being <a href="https://github.com/login?client_id=<integration_client_id>&amp;return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3D<integration_client_id>%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A3000%252Fusers%252Fauth%252Fgithub%252Fcallback%26state%3D123abcrandom">redirected</a>.</body></html>
curl -v -H 'Accept: application/vnd.github.machine-man-preview+json' --data 'client_id=<integration_client_id>&client_secret=<integration_secret>&code=<the_token_i_just_received>&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fauth%2Fgithub%2Fcallback&state=123abcrandom' 'https://github.com/login/oauth/access_token'
*   Trying 192.30.253.112...
* TCP_NODELAY set
* Connected to github.com (192.30.253.112) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: github.com
* Server certificate: DigiCert SHA2 Extended Validation Server CA
* Server certificate: DigiCert High Assurance EV Root CA
> POST /login/oauth/access_token HTTP/1.1
> Host: github.com
> User-Agent: curl/7.51.0
> Accept: application/vnd.github.machine-man-preview+json
> Content-Length: 208
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 208 out of 208 bytes
< HTTP/1.1 406 Not Acceptable
< Server: GitHub.com
< Date: Thu, 18 May 2017 16:15:09 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Status: 406 Not Acceptable
< Cache-Control: no-cache
< Vary: X-PJAX
< X-UA-Compatible: IE=Edge,chrome=1
< X-Request-Id: adbe69bc8c497f70fb4910af1d1955a1
< X-Runtime: 0.171073
< Content-Security-Policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src render.githubusercontent.com; connect-src 'self' uploads.github.com status.github.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-user-asset-79cafe.s3.amazonaws.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; img-src 'self' data: assets-cdn.github.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; media-src 'none'; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Public-Key-Pins: max-age=5184000; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho="; pin-sha256="k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4="; pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0="; pin-sha256="LvRiGEjRqfzurezaWuj8Wie2gyHMrW5Q06LspMnox7A="; includeSubDomains
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-XSS-Protection: 1; mode=block
< X-GitHub-Request-Id: C1F5:6EE7:E7F6C2:1571ED0:591DC88C
<
* Curl_http_done: called premature == 0
* Connection #0 to host github.com left intact

#4

Ahh, I wasn’t paying attention – sorry, @volmer. I was looking at the first curl output you provided – that curl output had the wrapping problem, not the second one. And the second one is which triggers the 406.

Related to the first curl output you provided – the https://github.com/login/oauth/authorize URL isn’t something you should be hitting with curl. It’s something users visit in the browsers since they’ll need to sign in and click the Authorize button. Just to make sure I’m not missing anything – why are you hitting that URL?

Related to the second curl output you provided – can you try making it without the Accept header? That accept header is needed only when hitting the API (i.e. api.github.com), I believe – you shouldn’t provide it when hitting github.com (which these requests are doing). I made that change in your second curl and it worked fine for me.

Let me know if that doesn’t help, though!


#5

can you try making it without the Accept header?

Awesome! Removing the Accept header solved the problem :tada: Thank you @izuzak!

Related to the first curl output you provided – the https://github.com/login/oauth/authorize URL isn’t something you should be hitting with curl. It’s something users visit in the browsers since they’ll need to sign in and click the Authorize button. Just to make sure I’m not missing anything – why are you hitting that URL?

You’re absolutely right. In my tests I was hitting that URL in the browser. I used curl in here just to share the output.

That accept header is needed only when hitting the API (i.e. api.github.com)

I was using that header because the documentation about Integration Oauth mentions it: https://developer.github.com/early-access/integrations/user-identification-authorization/

Perhaps it would be good to remove the mention of the Accept header from that page to avoid confusion?

Thanks again for all your help, @izuzak! :heart:


#6

Glad to hear that resolved the problem, @volmer! :tada:

I was using that header because the documentation about Integration Oauth mentions it: https://developer.github.com/early-access/integrations/user-identification-authorization/. Perhaps it would be good to remove the mention of the Accept header from that page to avoid confusion?

Thanks for clarifying! The note you’re referring to says this (emphasis mine): “In order to access the API with your Integration …”, so you should only need to pass that header when accessing the API. The flow you’re going through is not going through the API (as I mentioned before), but a bit further down on that page you’ll see a section which mentions using some API endpoints:

https://developer.github.com/early-access/integrations/user-identification-authorization/#check-which-installations-resources-a-user-can-access

For API endpoints listed in that section, you’ll need to pass in the Accept header.

Perhaps instead of removing the note it can be moved to the section in which it’s actually required, or the note can be clarified. In any case – I’ll mention your feedback to the team to consider. Thanks again for clarifying! :bow:


#7

Thanks for passing the feedback along, @izuzak.

Just one more thing: I don’t know if this is an issue on GitHub’s side, but the popular omniauth-github Ruby gem is not compatible with GitHub integrations since in this Oauth flow callback URLs cannot include query strings. I opened a pull request to fix this, maybe it would interest you: https://github.com/intridea/omniauth-github/pull/73


#8

I don’t know if this is an issue on GitHub’s side

Thanks for asking, @volmer. No, it’s not an issue on our side – that behavior is expected. Integrations use a strict check when comparing the callback_url from the Integration’s configuration to the redirect_uri used during the flow.

And thanks for opening a pull request to help other users out as well :sparkles:


#9