As the number of cryptocurrencies continues to grow, with several becoming available on almost a weekly basis, it’s no surprise that many people aren’t able to keep up with all of them and where’s…
Authorization framework — OAuth 2.0 — is a very popular nowadays. With this blog post I try to explain how it works and its basic concepts so in following article I could show how to implement it in a full stack app.
Love it or hate it. No matter how to you feel about security, it plays an important role in any application. As developers we usually focus on bringing new features that users wants, or trying out new tools rather than thinking of security. But regardless of our convictions, it’s highly irresponsible to put software which is not secured into operations.
There are different aspects of security in software engineering and clearly in a single blog post, or even in a series it’s not possible to tell everything about it. Therefore I would like to focus on one topic in particular — OAuth 2.0 protocol (and a little bit of OpenID Connect).
This article starts a short, practical series about how to implement security in software applications using OAuth 2.0 authorization protocol. First, I’ll explain basics of how it works (this article). Next I’ll move on to explaining it on a small project that will consists of three components (this will be part of next, upcoming blog posts):
One of the problem in a software security is how to make sure that system A is allowed to connect to system B. In other words, how to make sure that software applications are authorized to use one another. In case human to machine communication it’s fairly simple. User enters a website/mobile app and before doing anything it asks for valid credentials.
And even if a middle man application is trusted one, there are still some use cases when such software would require to store user credentials.
And among others this is the reason why OAuth protocol was created.
Before jumping to the details let’s see how OAuth 2.0 flow usually looks like from a user perspective, because I’m sure that you go thru this process once or twice.
During registration I’ve picked a GitHub option therefore now I also need to pick it. Now I’m redirected to the Github login page.
Now you may ask:
Let’s dive into it and see a full picture of described flow.
To fully understand how OAuth 2.0 works first we need to introduce all actors (roles) that are part of it.
I guess that even if I shortly introduced those key actors you probably don’t have full understanding that’s their role. But that’s ok, let’s move on to explain how they interact with each other, so it will be more clear.
I’m now on GitHub page. What is worth to mentioning here, is the fact that to the basic GitHub URL new parameters have been added:
And example od such URL would be:
code is one-time credential that client's application can use to obtain access token from the authorization server.
As a result client’s application gets an access token (7) (and sometimes identity and refresh tokens, I’ll explain more about them later), which now can be added to
Authorization header of a request to GitHub to get my email address (8).
And that’s it! In nutshell this is how OAuth 2.0 flow looks like in case of login in.
In this step we can define what
scope, what information, we would like to grant permission to read (or write) for a client applications. This decision is totally up to the resource owner and it gives her/him a control of how much power she/he wants to give to a client software.
Another thing that was only mentioned, but not explained, was access token itself. For now you know that it’s some sort of credentials written in a plain text. But how it looks like?
In OAuth 2.0 specification there are no guidance how such token should look like, which makes this open for custom implementation.
For example it could be just a simple string with random characters:
Or it could be more structured and cryptographically protected. Main advantage of that approach is the fact that tokens can hold some useful information instead of being just a random text. An example of such information could be resource owner’s permissions. One of the most popular, and de facto a standard, is JWT.
Below there is an example of JWT token (from a project which will be described in next blog post):
Still, it seems like a text with random characters. But if you look closer you can see that it’s made of 3 sections separated by dots. On above picture those sections are marked with colors — red (header), purple (payload) and blue (signature).
Each of these sections are encoded JSONs with Base64. The reason for that is because tokens are usually transported in an HTTP header there is a possibility that during it some data may be modified (uncommon characters for example). Also it makes those JSONs more compacted, with fewer number of characters. But be sure, this token is not encrypted, so anyone could read it with Base64 decoder!
It contains some metadata, like
alg which specifies what type of a signing algorithm was used (I'll talk more about them later).
It’s a main course of JWT. After decoding a payload we can see several fields with various information about a user and more. They’re called claim.
In general, we can put here anything what we want (roles, organization restrictions etc.), but there some recommended fields that could be added:
The essential concept behind JWT is the fact that anyone should be able to read the content of a token, but only an authorized server can create a valid one. Therefore a protected resource should somehow verify if a token is correct. If for some reason it will be skipped there is a possibility that an unauthorized client (or even worse, a malware program) creates a dummy token and do funky stuff.
To prevent that from happening a third section was added to JWT, called signature. Only with it we can be sure that a token is correct.
There are several ways to create a valid signature, but the most common approach is to combine encoded JWTs’ header and payload with a secret and cryptographic algorithm. Based on these 4 inputs a unique signature can be created.
If any part of this equation will be modified (e.g. payload) a signature also will be changed. And that is only possible when you know a signing alogrithm (info is provided in a JWT’s header) and a secret.
Depending on the algorithm those secret can be used in a different ways.
First, popular approach to generate signature is with symmetric key cryptography — HS256. In it we have a single secret which is shared between authorization server (to create token) and protected resource (to validate a signature). The main drawback of it is the fact that it both parties authorization server and protected resource(s) needs to have the same non-public secret. It’s not big problem if both of them are the same application or share the same database, but it might get tricky when we have it as separate entities and need to safely copy-paste it from one to another.
Another approach is to use an asymmetric signature RS256 in which there is a pair of public and private keys. An authorization server has access to private key which is used to generate a signature. Also authorization server is providing a public key, which can’t be used to sign a JWT, but can be used by a protected resource to verify if a signed JWT is correct. A public key can be provided in several ways, but usually it’s by HTTP endpoint so various applications could make a use of it.
Up till now I’ve covered basic flow of the OAuth 2.0, which is obtaining the access token. In the part about JWT it was mentioned that tokens has an expire date, which means that after certain time they won’t be valid. And usually it’s after a short period of time, like couple of minutes.
To prevent client from asking resource owner again for credentials a new kind of a token was introduced — refresh token.
Refresh token can be treated as a credentials that can be used to obtain access token, but this time they’re not assigned to the resource owner, but to the client, which can use it to obtain a new access token.
What is important, refresh token is not a valid access token and can’t be sent from client to protected resource. Technically it can, but protected resource should reject it.
Another key difference between both token is their life time. Access tokens are usually valid for couple minutes, but a refresh token can be used for couple hours or even days.
Here is the flow, how a refresh token can be used between OAuth 2.0 actors:
Protected resource is than checking the token and sees that it’s expired so it returns an error code to the client (13). Luckily the client has stored a refresh token and it’s making a new request to the authorization server (14) including a token in a request header.
As a result authorization server returns a new access and refresh token (15) (plus, possibly an identity token, which will be described in following section) so a client is able to make a request to the protected resource (16) and return a final result to me (17, 18).
Of course, it depends, but it’s very common to use JWT format:
which could be decoded to header:
and payload with claims:
There is nothing new here, which wasn’t in access token. The only difference is in algorithm, which here it’s HS256, which is sufficient enough as this token is issued and validated by the authorization server and therefore there is no need to share a private key among protected resources.
If we look closer into the OAuth 2.0 specification we found out that it was designed to handle granting access to protected resource, it describes what user/client can do and has access to (e.g. read, write, delete). It’s impersonal, because there is no information about who is the user. Only what actions can be done. And this is called authorization.
On the other hand, there is a concept of authentication which validates if a user is whom she/he claims to be. It has nothing to do with what permissions they have.
We could do it with similar approach as it was previously, using access token and making another call to GitHub to get what we want, but there is another way by adding necessary information to a token.
The most important one is that if a client make a request to get access token it will also received a new one — identity token (ID token), which hold user information. To make sure that information are correct identity token are represented in JWT format, where payload is very similar to the access token’s.
And what’s worth mentioning, identity token is designed to be used only by a client application and should not be used to get resource from the protected resource.
I hope that with this article you have learn something new about OAuth 2.0. At the beginning it might be quite a lot to digest, but definitely it’s worth it as it’s used in many projects nowadays and it’s considered as a good practices.
If you would like to see a more practical approach, how everything works, go check my other blog posts on this topic in which I’m showing:
Polusi udara kota di beberapa kota besar di Indonesia telah sangat memprihatinkan. Beberapa hasil penelitian tentang polusi udara dengan segala resikonya telah dipublikasikan, termasuk resiko kanker…