I've implemented my own classes for handling authorization via OAuth to GitHub using Faraday in Ruby. I've verified that under the following conditions:
- Not logged into GitHub
- No token exists for the app
that a request for authorization via GET
to "/login/oauth/authorize"
with a random state
variable:
- Redirects to the GitHub login page
- Redirects to the Authorize Application page after login
- Executes callback to my app with temporary code after authorizing
- Responds with access_token when I
POST
to"/login/oauth/access_token"
with temporary code
The problem I have is when I alter the first condition, I'm not already logged into GitHub. The same GET request is sent to GitHub, I see the correct URL with the right parameters. I then see what appears to be the correct redirect by GitHub with a return_to
parameter, but it quickly just redirects again back to the GitHub home page.
I'm hoping it's something easy like forgetting a header parameter or something, and someone might spot the problem right away. Anyway, any help is appreciated...
Code to setup Faraday connection:
def connection
@connection ||= Faraday.new(url: 'https://github.com') do |faraday|
faraday.request :url_encoded
faraday.response :logger
faraday.adapter Faraday.default_adapter
end
end
Code to send authorization request:
def request_authorization(client_id, redirect_uri, redirect_id, scope, expected_state)
response = connection.get '/login/oauth/authorize', {
client_id: client_id,
redirect_uri: "#{redirect_uri}?id=#{redirect_id}",
scope: scope,
state: expected_state
}
if response.status == 302
response.headers[:location]
else
nil
end
end
I didn't show the code, but my controller does a redirect to the URL reply from request_authorization()
. Again, I definitely see the redirect from my controller in both cases, but the second case seems to encounter something GitHub didn't like in the redirected request. I assume it then redirects to the home page and never replies to my app because of this unknown problem in my original request.
Thanks, David
Ivan from GitHub was a great help in finding the answer to my question. I had assumed the problem was some detail with using Faraday or OAuth, but it turns out the problem was a basic assumption that proved wrong. Hopefully this will help others that run into a similar misunderstanding.
I had assumed that a user of my app that wanted to connect to GitHub (or another OAuth service) would issue something like a "connect" request to my app. My app would then generate the OAuth authorization request to GitHub, handle any redirects, and eventually wind up presenting the Authorize App page to the user for acceptance.
Turns out I just needed to make the "connect" request actually a link to directly make the authorization request to GitHub. My app then only has to worry about handling the callback, which it already did. Easier and works in all cases now.
Turns out the wrong approach worked when not logged in due to it being the simple case. It failed when logged in because I wasn't handling session state that normally the browser would provide.
A more careful read of the OAuth RFC cleared up my confusion about where requests and responses are handled for the User Agent and for the Client.