Closed mattlevan closed 6 years ago
@mattlevan I don't think %application/json
is valid syntax. I can't type it into the dojo on the master branch, at least. Is there a reason it's structured that way and not surrounded by single quotes like 'application/x-www-form-urlencoded'
?
@belisarius222 Thanks, my typo there. Same results with 'application/json'
.
I've spent some time reproducing this. It seems that %hiss
headers are not actually being used -- not sure if the bug is in %eyre
or cttp.c
:
Save as %/gen/hiss/hoon
(secrets elided):
|= *
:^ (need (de-purl:html 'https://github.com/login/oauth/authorize'))
%post
(my content-type+['application/x-www-form-urlencoded']~ accept+['application/json']~ ~)
%- some
:- 216
'code=123&client_id=456&client_secret=789&redirect_uri=http%3A%2F%2Flocalhost%3A8443%2F~%2Fac%2Fgithub.com%2F~.%2Fin&grant_type=authorization_code'
> |start %curl
> :curl +hiss ~
Note: I tried to test locally with netcat, but kept hitting urbit/urbit#784 and urbit/urbit#838. urbit/urbit#882 seemed to be an issue as well.
I added some printfs to _cttp_heds_list()
, and the headers are definitely making it that far. I'm officially out of my depth ...
Very interesting this is. Joe, I take it that you'd call yourself completely confident that this is a cttp bug?
On Tue, Oct 24, 2017 at 8:31 PM, Joe Bryan notifications@github.com wrote:
I added some printfs to _cttp_heds_list(), and the headers are definitely making it that far. I'm officially out of my depth ...
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/urbit/arvo/issues/442#issuecomment-339203603, or mute the thread https://github.com/notifications/unsubscribe-auth/AALyAb3ngIYJXUgWpREBf7ArSfJeyfpoks5svquGgaJpZM4QDMyf .
To be completely confident, I'd need to print the headers in cttp.c and observe the absence of headers in a request to an http server I control. I haven't gotten that to work on localhost -- at least not with netcat. I keep hitting the issues i linked above.
I could add a name to /etc/hosts and test with that, or stand up a server on another machine. I can give it another spin this evening.
The headers are being passed through, and are part of the request. But there are duplicates:
> =headers (my content-type+['application/x-www-form-urlencoded']~ ['Accept' ['application/json']~] ~)
> :curl [[p=[p=%.n q=[~ u=10.101] r=[%.y p=['localhost' ~]]] q=[p=~ q=~] r=~] %get headers ~]
$ nc -k -l 10101
GET / HTTP/1.1
User-Agent: urbit/vere.0.2
Accept: */*
Connection: Keep-Alive
Host: localhost
content-type: application/x-www-form-urlencoded
Accept: application/json
Confirmed on retrofit and maint.
Duplicate headers are generally frowned upon, but I don't know what real-world usage actually looks like. Maybe github has started parsing requests more strictly? Or merely changed it's default response type?
It could very well be that GitHub reads the first accept header (Accept: */*
) and says, "Hey looks like he's cool with any format!" and proceeds to send the access token in the urlencoded form. @joemfb That */*
header must be hard-coded somewhere, do you have a good idea where or some clues so I can search for where?
BTW, yes, the GitHub default response type is urlencoded form. I've checked this with curl.
Yeah, just comment this out: https://github.com/urbit/urbit/blob/retrofit/vere/cttp.c#L1512
I just confirmed that was the issue, I've successfully authorized my token and gotten JSON from github.
That line has been there for awhile ... urbit/urbit@3400b6bacb857301f988ad82a7384ceabaac9f6b
Update: make that all the way back urbit/urbit@cc255a4c496f39818be6346292e63c1229c2c31a
So good to get this fixed! Can you drop a PR?
Successfully reproduced @joemfb's findings with urbit retrofit branch and belisarius222/sec-fixes arvo branch as well. Changes to urbit/urbit and urbit/arvo are reflected respectively here: urbit/urbit#890 and urbit/arvo#446.
Here are the working parts:
cttp.c
// _cttp_ccon_fire_str(coc_u, "Accept: */*\r\n"); // line 1512 commented out
After commenting that line out, recompile urbit, boot it with retrofit arvo, and ensure lib/oauth2.hoon and sec/github.hoon are as below and GitHub OAuth2 should now work.
lib/oauth2.hoon
:: Test url +https://api.github.com/user
::
:::: /hoon/github/com/sec
::
/+ oauth2
!:
::::
::
|_ {bal/(bale:eyre keys:oauth2) tok/token:oauth2} :: note the bale:eyre here, important
++ scopes :: comment out scopes to taste
:~ 'user' 'user:email' 'user:follow' 'public_repo' 'repo'
'repo_deployment' 'repo:status' 'delete_repo' 'notifications'
'gist' 'read:repo_hook' 'write:repo_hook' 'admin:repo_hook'
'admin:org_hook' 'read:org' 'write:org' 'admin:org'
'read:public_key' 'write:public_key' 'admin:public_key'
==
:: ++aut is a "standard oauth2" core, which implements the
:: most common handling of oauth2 semantics. see lib/oauth2 for more details,
:: and examples at the bottom of the file.
++ aut (~(standard oauth2 bal tok) . |=(tok/token:oauth2 +>(tok tok)))
++ filter-request
%^ out-add-query-param:aut 'access_token'
scope=~[%client %admin]
oauth-dialog='https://github.com/login/oauth/authorize'
::
++ receive-auth-query-string
%- in-code-to-token:aut
url='https://github.com/login/oauth/api/access_token'
++ receive-auth-response bak-save-token:aut
--
sec/github.hoon
:: Test url +https://api.github.com/user
::
:::: /hoon/github/com/sec
::
/+ oauth2
!:
::::
::
|_ {bal/(bale:eyre keys:oauth2) tok/token:oauth2}
++ scopes :: comment out scopes to taste
:~ 'user' 'user:email' 'user:follow' 'public_repo' 'repo'
'repo_deployment' 'repo:status' 'delete_repo' 'notifications'
'gist' 'read:repo_hook' 'write:repo_hook' 'admin:repo_hook'
'admin:org_hook' 'read:org' 'write:org' 'admin:org'
'read:public_key' 'write:public_key' 'admin:public_key'
==
:: ++aut is a "standard oauth2" core, which implements the
:: most common handling of oauth2 semantics. see lib/oauth2 for more details,
:: and examples at the bottom of the file.
++ aut (~(standard oauth2 bal tok) . |=(tok/token:oauth2 +>(tok tok)))
++ filter-request
%^ out-add-query-param:aut 'access_token'
scope=~[%client %admin]
oauth-dialog='https://github.com/login/oauth/authorize'
::
++ receive-auth-query-string
%- in-code-to-token:aut
url='https://github.com/login/oauth/access_token' :: '/api' removed
++ receive-auth-response bak-save-token:aut
Problem
The code (likely some part of %eyre, I suppose) which
++post-quay
of arvo/lib/oauth2 relies on to send POST requests is not attaching headers correctly.Background
As part of my arvo docs work, I have been going through the security driver tutorial here, which guides the reader through configuring OAuth2 for use with the GitHub API v3.
Issue Reproduction
Run the instructions from the OAuth2 section of my
arvo-finish
branch of the docs. The only things I've changed are the URLs to enter into GitHub when you make an OAuth app and theaccess_token
API URL (from https://github.com/login/oauth/api/access_token to the correct https://github.com/login/oauth/access_token).Network Trace
The reader will notice things running smoothly:&redirect_uri=&scope=client%20admin). The reader's network activity log from the developer console in his browser will look similar to this:
|init-oauth2
performs as expected, etc. Upon reaching the part in which the reader is instructed to run+https://api.github.com/user
in thedojo
, he will receive an appropriately formatted GitHub authorization URL (https://github.com/login/oauth/authorize?state&client_id=%bad-json
He will also be met with a response from his urbit, still in the browser, which indicates "bad json":
We're not receiving JSON from the GitHub API. That's not surprising-- GitHub API v3 requires us to send the header
Accept: application/json
if we want the response in JSON.Adding to lib/oauth2
So I started to explore the correct place to add this header. It seems appropriate to me to add this to
++post-quay
of lib/oauth2.hoon, so that the new version reads as such:Please note that HTTP header field names are case insensitive. From what I've gathered, this code should tack a new header onto the POST request and we should accordingly receive JSON back from GitHub. But, it doesn't work!
hiss and httr
Last thing I did was
~&
thehiss
andhttr
(I've noted the arms from which they are being printed too):It looks like our
hiss
is okay here, complete with our newly addedaccept: application/json
header. But, we still don't receive JSON back from GitHub upon retry!So, I decided to go trawling through
arvo/eyre.hoon
and that's where I'm fairly well stuck.Commentary
Tagging @ohAitch on this one since I've heard rumors in meta that this is your work! Perhaps you can help. Also tagging @joemfb since he was so helpful in meta. And @keatondunsford because the docs are squarely in his domain! I am just learning what's going on here (editing the docs has been a great way to learn), so please let me know if I'm mistaken anywhere or if I'm missing some crucial knowledge. Looking forward to hearing back so I can finish my edits of
security-driver.md
andapi.md
in the docs. Thanks!