I'm working with GitHub specifically, but this seems pretty general.
The GitHub docs state [formatting has been modified by me]:
There are three ways to authenticate through GitHub API v3. ...
- Basic Authentication
- OAuth2 Token (sent in a header)
- OAuth2 Token (sent as a parameter)
- OAuth2 Key/Secret
... Note that OAuth2 tokens can be acquired programmatically, for applications that are not websites.
[I'm assuming that the second and third items are really considered a single 'way to authenticate' but then, based on the formatting in that section, "Failed login limit" could also possibly be misinterpreted as a 'way to authenticate' as there's no explicit list of the "three ways".]
The text at the link "acquired programmatically" above starts:
If you need a small number of tokens, implementing the web flow can be cumbersome. Instead, tokens can be created using the OAuth Authorizations API using Basic Authentication. To create tokens for a particular OAuth application, you must provide its client ID and secret, found on the OAuth application settings page, linked from your OAuth applications listing on GitHub. If your OAuth application intends to create multiple tokens for one user you should use fingerprint to differentiate between them.
Authentication via authorization via another form of authentication?
Let's parse all of the above, sentence-by-sentence.
If you need a small number of tokens, implementing the web flow can be cumbersome.
Well, hopefully, my awesome not-a-website application will have lots of users, so I need lots of tokens, right? So does that mean, right off the bat, that I should be "implementing the web flow"? I suspect it does.
Instead, tokens can be created using the OAuth Authorizations API using Basic Authentication.
Now, this is pretty confusing. I want my not-a-website-app (NAWP) to interact with GitHub, on behalf of my users, and I'd like for them to avoid the unauthenticated user API request rate limiting. And I can't just register my application with GitHub and include my registered client ID and secret in my requests because:
This method should only be used for server-to-server calls. You should never share your client secret with anyone or include it in client-side browser code.
So I'd like to authenticate to GitHub as, or on-behalf-of, the user using my NAWP.
So I can create an authentication token, to access the regular GitHub API, by using a special authorizations API, but I have to authenticate using Basic Authentication first. Great. One question – what credentials do I provide via Basic Authentication to be able to access the authorizations API? Mine? A special GitHub account just for my app? The user's?
I'm guessing I'm supposed to use the user's credentials, and the user has to trust my NAWP to promptly forget those credentials once it uses them to create an authentication token for itself. Okay, that seems non-ideal, but I'm willing to go along for now.
To create tokens for a particular OAuth application, you must provide its client ID and secret, found on the OAuth application settings page, linked from your OAuth applications listing on GitHub.
Wait. WTF. I authenticate, with my user's GitHub user name and password (or a token? that the user has to generate themselves? that they could just give my NAWP to use forever, especially if I just want to access public info but avoid rate limiting?), and then my NAWP has to make a request to generate an OAuth token by making a request, for which one of the required parameters is ... "The 40 character OAuth app client secret for which to create the token."
That doesn't seem right.
In the first section of the docs, quoted way up at the top of this question, under the "OAuth2 Key/Secret" sub-section, it is written:
This should only be used in server to server scenarios. Don't leak your OAuth application's client secret to your users.
Also, in the "Increasing the unauthenticated rate limit for OAuth applications" sub-section, it is written:
If your OAuth application needs to make unauthenticated calls with a higher rate limit, you can pass your app's client ID and secret as part of the query string.
...
This method should only be used for server-to-server calls. You should never share your client secret with anyone or include it in client-side browser code.
Am I missing something? I must be missing something. Because of course there's no way I can securely distribute the client secret GitHub generates for me in my NAWP.
If your OAuth application intends to create multiple tokens for one user you should use fingerprint to differentiate between them.
This is not confusing at all (and I am not being sarcastic). If an individual instance of my NAWP was being used by multiple users, then I just include some kind of identifier to differentiate among any tokens I need or want to create; pretty simple really.
But understanding this one sentence does nothing to dispel my confusion about the preceding three.
So, is it or is it not possible to securely authenticate on behalf of GitHub users, using OAuth, for a NAWP?
I'm guessing it's not and that the only way to securely use OAuth is with code that runs in an environment secured by its authors (so a webapp).
If I've guessed wrong, kindly explain (in detail) exactly how a NAWP can authenticate via OAuth on behalf of its users.
And if your solution involves distributing the client secret with the NAWP files, as does the solution outlined in the blog post below, kindly explain how that's not a problem, especially given the repeated insistence by GitHub in their docs, that the client secret should not be shared with anyone ever.
Yes, you are partially correct. It is not possible to securely authenticate on behalf of a user using OAuth solely using a non-web application. This is because GitHub only implements the authorization_code
OAuth flow.
Instead, you'll need to have a web server to help you securely authenticate a user.
The general process looks like this:
I did something similar with this for LinkedIn, Node.js, and an iOS app if you want to see a quick example of a similar flow.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With