Tuesday, December 27, 2016

Secure an API with OAuth2

When it comes to secure a webservice there are several options. One of them is OAuth2 and I will
explain how to have an hello world example running by using Sprint Security OAuth.


Some theory 

To my understanding OAuth2 is all about giving to a third-party a limited access to a ressource. Hum, pretty abstract ... With an example it will be clearer:

Let's say you are reading and article in your favorite dev news website. For example this one : Securing MongoDB Instances

You can notice a Tweet button (*) on top of the article. By clicking it, you will post a tweet in your twitter account with a link to the article you are reading. What it is really going on is that DZone website will be granted an access to your twitter account for a limited time and with limited functionality just to be able to tweet on your behalf. This grant will be given by you by entering your credentials on twitter (**), it is done by redirection and by this action you will allow DZone to access your twitter account. Notice that you never shared your credentials with DZone, you only connected to Twitter.

If it's still not clear, there is an analogy that helped me to understand (it's not from me but I don't remember where I have read it). Imagine you are the owner of a car (the ressource) and you want to go to a fancy restaurant  where someone (third-party) will drive your car (access to a ressource you own) to the restaurant's parking. You don't know this person and give him the key of your car is a risk because he can go away with it. For such situation, car manufacturers came up with a solution which is to provided a special key for the car that only work for a limited distance, it means that you can drive the car only a few meters with this key. So to limit the risk to be stolen from your car, you can give this special key (token) to the restaurant employee.

And if it's still not clear, everything can be found here : The OAuth 2.0 Authorization Framework


Hello world up and running 

For the hello world, what we want to do is to protect the access to a rest API that returns Hello World. We want this API to be callable only by users owning a token provided by an OAuth2 authorization server. Withing OAuth2 framework this use case is called : Bearer Token Usage.

I really encourage to read the documentation about bearer token which is a kind of easier form to use OAuth2 (no redirection), it's perfect for starting. And for hurried readers, have at least a look at the sequence diagram (***).

Well, that's time to make things work. For this, the spring-security-oauth project is bundled with integration tests and we will use the one called Vanilla which is exactly what we want to do.

Quote from the documentation about Vanilla:
"This project shows what you can do with the minimum configuration to set up an Authorization Server and Resource Server"

All you need to do is to clone the project in your machine (git clone https://github.com/spring-projects/spring-security-oauth) and then in the Vanille folder run the command :

mvn spring-boot:run

It will start a tomcat server listening on 8080.

As a client, here are the requests to make if you want to access the protected API
$ curl -H "Accept: application/json" my-client-with-secret:secret@localhost:8080/oauth/token -d grant_type=client_credentials
{... "access_token": "b561ff06-4259-466e-92d8-781db1a51901", ...}
$ TOKEN=b561ff06-4259-466e-92d8-781db1a5190
$ curl -H "Authorization: Bearer $TOKEN" localhost:8080/
Hello World
You basically make a first call by providing a login and password to get a token. Then you can request the API with the token.

One very important thing to keep it mind is that TLS is mandatory with OAuth2. Credentials my-client-with-secret/secret have to be kept secret.

To verify that everything works, try to make a call with an incorrect password and also make a call with an incorrect token. Those calls will be rejected.

For the understanding of this simple scenario be complete, please have a look at Application.java in Vanilla project. The API is protected just by adding @EnableResourceServer annotation. And I let you see how the authorization server is implemented with spring.

Conclusion

OAuth2 is one way to protect an API. By having a simple hello world application running I believe it is easier to understand OAuth2  and by iterating achieve more complex use cases.

I'm planning to make this exact same scenario work with Node.js. With spring it was really straightforward. I hope it will be the same with Node.js but from my first researches I think it will need more work.

Thank you for reading!

(*)


(**)


(***)

No comments:

Post a Comment