OAuth 2.0?
If you are to work in a medium to large enterprise its very likely OAuth 2.0 will be used heavily. However in my experience a lot of junior and senior developers have trouble with it. So lets talk about it!
2.0? Where is 1?
You may be wondering...why OAuth 2, why not 1. Or maybe why not OAuth 0...isn't that the new thing? (Credit goes to Auth 0 for confusing developers across the globe)
OAuth 2 essentially...was created due to OAuth 1 being hard to use. Generally applications shouldn't store the usernames and passwords if they can avoid it. For example, in a large company generally there will be some central data store of employees that knows who an employee is and what they can do and all web applications across the copmany will use that data store going forward. This could be Auth 0, Okta, maybe AWS cognito even. This is what we call the Authorization server.
In OAuth 1.0, we didn't need to use HTTPS, OAuth 1 tries to solve encryption and authorization for each HTTP request. Today, instead of this, a combination of HTTPS (all of your communication to servers is encrypted) and OAuth 2.0 for user authorization should cover this.
For now we will look at a client authentication flow. There are many types of OAuth 2.0 implementations for different use cases but for now we will look this in the context of a user logging into a web application.
OAuth 2 Basics
OAuth 2.0 defines four roles:
Resource Owner - A web app user
Client - A website or server that wants to login a user.
Resource Server - The server that hosts the protected resource.
Authorization Server - The server that issues access tokens to the client after successfully authenticating the resource owner and obtaining their consent. Examples of well known Authorization providers include Microsoft, facebook, google, Okta, Auth0, Ping etc. Most cloud providers will also have various services to help implement OAuth flows and user sign up, AWS Cognito for example and they will have an authorization server somewhere under all those API's.
OAuth 2.0 uses the following flow to obtain an access token:
The web app requests authorization from the user.(Enter your username/password) User enters their credentials and clicks login. This sends your username and password to the resource server, if the credentials are valid - the resource server returns a 1 time use(hopefully) authorization grant code. The client then passes this 1 time code back to a different URL on the authorization server and receives a JWT back known as an access token. The client uses the access token in every following request to the servers to access the protected resource for the user.(Essentially - when doing anything on the backend - you send your token to the Authorization server every time to check if its still valid and authorized)
Some things to note here, the access token is typically only active for 15-30 minutes. Once this time has passes the authorization server will reject it and another access token must be retrieved. For client authentication we get something called a refresh token which can be used to retrieve an access token with the need for prompting the user to login again. More on that below...
Auth 0 OAuth 2.0 flow
Yes. Auth 0 actually uses OAuth 2.
JWT Basics
JWT stands for JSON Web Token. It is a compact, URL-safe means of representing claims to be transferred between two parties. JWTs consist of three parts separated by dots:
- Header - Contains information about the type of token and the algorithm used to sign it. - Payload - Contains the claims, which are statements about an entity (typically, the user) and additional data. - Signature - A cryptographic signature generated by combining the header, payload, and a secret key.
The following is an example JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 .eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicm9sZXMiOlsiR3JvdXBzIiwiQWRtaW5pc3RyYXRvciJdLCJhY2Nlc3MiOiJhY2NvdW50Iiwid3JpdGVzIjpbeyJhY2Nlc3MiOiJyZWFkIn1dfQ .SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
While this may look like gibberish - it is actually just base64 encoded JSON - to make it easier to move around in HTTP headers.
Decoded JWT JWT decoding tool:
{ "alg": "HS256", "typ": "JWT" } { "sub": "1234567890", "name": "John Doe", "roles": ["Groups", "Administrator"], "access": { "actions": "account", "writes": [ {"access": "read"} ] }, "iat": 1516239022 }
So now we have our access token. How is this even secure?
Well first things first, if a hacker somehow obtains your access token - they only have it until the timeout of the access token, in OAuth 1 that access token may never time out! User credentials are actually stored in the Authorization server so we don't need to store them in our applications database. If your JWT is modified, is will now change the entire signature of JWT! This means if you try to validate a modified access token against the authorization server it will fail.
Further more, you can see the token contains what is called a claim, the user contains an administrator role, this means that the web app can trust that this user is actually an admin and should be able to perform admin tasks. The Authorization server will tell you about users who log in. This is very common in large companies and is a good way separating users into different roles securely.
In a follow up article we will look at SSO, PKCE, client credentials flow and machine to machine flows as they present their own challenges and security risks and we will be implementing an OAuth 2.0 flow in React JS using google's OAuth 2.0 API - (Sign in with google) showing how to protect both your front end URLs and back end API's.