Firstly, what the hell is Auth?
Well, auth could mean "authentication" or "authorization". Authentication is the process of verifying that you are who you say you are. Typically, this would mean validating your credentials such as your username and password. Authorization, on the other hand is the process of determining if you (the authenticated user) have permission for a resource that you are trying to access. To be explicit, henceforth, let's use authN and authZ to refer to authentication and authorization respectively.
When we login to a website, how does the server know I'm authenticated for every subsequent request I make?
Well, there exists a naive mechanism of authentication called Basic Authentication, which can be used by a HTTP user agent to provide a username and a password when making a request. If you use this mechanism, you'll have to include the username and password in every subsequent request.
But there are other more sophisticated mechanisms of authentication used by websites. For example, in session based authentication, after the first login, the server creates a session for the user, and returns a
session_id as a cookie back to the user-agent. As long as the user is logged in, the cookie would be sent along with every subsequent request. The server can just compare the
session_id it receives with the
session_id that it had created to verify the user's identity.
There also exists a token-based mechanism of authentication, where the user first provides the username and password in exchange for a
token. For every subsequent request, the client will send the
token for the server to perform authentication.
More reading - https://stackoverflow.com/questions/51341562/alternatives-to-basic-authentication-when-logout-is-required
Hang on. Session-based and token-based sound like the same thing. What's the difference?
The biggest difference is that in token-based authentication, the user's state is not stored on the server. The payload(including the token) that is sent is self-sufficient for validation by the server(by the means of something known as digital signatures). This makes it easy to scale your application. More reading - https://blog.angular-university.io/angular-jwt/
Ok, cool. Jumping to API development, I usually have to use an API key and a secret. What's that all about?
These are used for authN..
Wait, why do I need an API key and secret in the first place? Why can't I just use my username and password which I'm already using anyway?
Good question. One reason is to make it more complicated a task for an attacker. If the attacker is resorting to a brute-force attack, they would have to search a much larger space (the search space for a key would be much more random as compared to usernames). Also, using a key instead of a username prevents a leaked key from tracing back to the user.
Ok, but if we're choosing a separate key, why do I need a key and a secret, both? Why wouldn't a single unique code serve as username and password both?
You must first understand the difference between symmetric and asymmetric cryptographies. In symmetric cryptography, a single key is shared between both parties. The problem with this type of cryptography is that of key exchange. How do you safely exchange keys with which you plan to subsequently exchange information in a safe manner? What if the key exchange process is itself compromised?!
Enter, asymmetric cryptography, where each party has a public and a private key pair. A message encrypted with a public key can only be decrypted by its private key (and vice versa). So, if I want to send you a message that only YOU can read, I simply encrypt with your public key. You receive the message, and decrypt it with your private key! That's where the secret comes in handy.
Wait. If I'm using HTTPS, my requests should already be encrypted right? Why do I need a secret, then?
You're right. It's an additional layer of security on top of HTTPS. It may sound trivial, but more layers of security, the better. More reading - https://stackoverflow.com/a/11561986/4434664
What is OAuth? That comes up a lot.
Ahaa. We've been talking about authN till now. OAuth is all about authZ. Let me explain the motivation behind OAuth. Let's say you have a photo printing web application. Your users upload a picture, and you print it out, and deliver it to them. Now, your users want the option of directly selecting an image from their google drive as opposed to downloading it and uploading it. (Users are lazy, aren't they?) Now, one option is to blatantly ask the user for their google drive username and password. Obviously, that's not acceptable.
Fine, another option is to ask users to share the photo with you, using a sharable link. That might work for this use-case, but it might not work for other use-cases. For example, what if you want the user to share the entire list of their contacts, so that you can broadcast some message of sorts? Now, as a simple user, I don't have the capability of retrieving all that information from google drive. That's only accessible via an API. Ok so, they could create an application on google drive, and then share the API key and secret with you. But that's still too tedious for the user.
Enter, OAuth. You must have encountered some screen like this at some point.
That's OAuth in action. It's a standard created for services to access each other on behalf of the user. User is authenticated with your photo printing application. User is also authenticated with google drive. Now, you simply ask google drive for permission on behalf of the user. Google drive asks the user if they want to give you(the photo printing app) permission via the screen shown above, which you accept(you better accept...). Google drive returns an authZ token to you, using which you make subsequent requests to Google drive for retrieving photos, contacts, etc on behalf of the user. More reading - https://developer.okta.com/blog/2017/06/21/what-the-heck-is-oauth
That makes sense! Final question - If I'm building an API, should I use key and secret, or should I use OAuth?
If the users of your API are all developers, you're better off using API keys and secrets. You only need to use OAuth when you want to enable your user to use some third-party client application to use their data stored on your application without having to give their username/password to the third-party client application. One other advantage of using OAuth tokens over API keys and secrets is that they also provide the feature of authZ. Tokens can be tied to scopes. You can create a token that can only read contacts. You can create another token that can not only access contacts, but also modify and delete them! Also, OAuth tokens have an expiry feature, making it more secure! More reading - https://zapier.com/engineering/apikey-oauth-jwt/