Getting Started 

Auth is hard. I cannot even begin to recall the number of times I’ve come up with an exciting idea for a personal project, only to be delayed in the early stages by something as seemingly simple as user sign up and login. It’s not quite as exciting as new trends in web development or as relevant as current events, but it is a very important domain of knowledge for developers. 

This is the first post in a small series that will break down these concepts in an easily digestible way. This blog will tackle some high-level definitions and concepts. Later posts will expand on these concepts with examples. 

Authentication vs Authorization 

Authentication and authorization are terms that are frequently thrown around and used interchangeably, however they describe two related albeit different concepts. 

Authentication 

In simple terms, authentication is verifying that a user is who he / she claims to be. The most common authentication scheme is a simple username and password, however several other authentication methods are available and becoming increasingly common, such as fingerprint authentication and facial recognition. 

Authorization 

Authorization defines assigned privileges and access for a user. For example, some users may have read / write access to a service, where others many only have read access. Authorization is generally performed after (or during, as we will see later) authentication. 

OAuth 2.0 and Open ID Connect (OIDC) 

OAuth 2.0 

OAuth is a framework / protocol that was developed and is maintained by the IETF OAuth working group. It was developed to allow third party services to access resources without explicitly sharing user credentials (i.e. passwords). The result of a successful OAuth flow is a token. How this token is generated, used, and structured will be elaborated on later. 

Open ID Connect (OIDC) 

OIDC is a standard that is built on top of OAuth and is maintained by the OpenID Foundation. It allows for authorization as well as authentication. As the name suggests, OAuth only provides authorization through a token and does not include login and profile information. In other words, ODIC not only describes what a service can do but also who a user is. This user information, called identity is also stored in a token, called an ID Token. This will be important later In addition, OIDC allows for single sign-on functionality or SSO. 

Definitions 

Let’s define some terms before we get into the actual OAuth / OIDC flows. 

Resource Owner: A user, in other words, you!
Resource Server: An application that has protected resources. This is your API.
Client: The application that wants access to a resource owner’s data. Frequently, this is a mobile app, single-page application (SPA), or a traditional application.
Authorization Server: The service the resource owner has an account with. This can be a custom service that you write or commonly used ones such as Facebook or Google. When an Authorization Server provides user information (OIDC) it is known as an Identity Provider. 

JSON Web Tokens (JWT) 

A JWT (pronounced “jot”) is a standard that is used to securely contain tokens for transfer over the internet. I won’t dig too deep into them here but will instead give a high-level overview. 

As referenced before, this is the primary way that access tokens and id tokens are shared between different servers. 

There are 3 parts to a JWT: 

  1. Header: Contains metadata about the type of encryption 
  2. Payload: Data being transferred 
  3. Signature: Validation for the token 

These tokens allow for stateless authentication. This means that a service does not need to maintain a user’s session, but it is instead managed by the token itself. 

OAuth / OIDC Flows 

Below are descriptions of some OAuth flows, why they were created, and when they might be used. I will cover a couple of them, but keep in mind that there are several more than the examples listed. You can even create your own! 

While OAuth flows can be used for several different applications such as server-to-server, native apps, or anything you can think of, the following examples assume Google as an identity provider with a Single Page Application (SPA) client that accesses a protected API. 

In addition, anywhere in the following flows where an access_token is returned, an id_token may be returned as well. This id_token is a special JWT that has user information such as a user’s name, email, profile picture, and more. This fulfills the requirements for ODIC. 

Note: Some required parameters are omitted here but will be included in the examples in the upcoming blogs. 

Implicit Grant (Deprecated) 

The Implicit Grant flow was created in the early 2010s to fill the need that was created by new technologies such as SPAs and mobile apps. It is one of the simplest flows as an access token is returned immediately without an authorization code exchange step. 

  1. The Resource Owner sends a request to log into the Client App. 
  2. The Client App requests authorization from the Authorization Server. 
  3. The Authorization Server redirects to an authorization page. 
  4. The User confirms the authorization. 
  5. The Authorization Server redirects back to a callback URL on the Client App with an access_token. 
  6. The User performs an action that requires data from the Resource Server. 
  7. The Token is included with API requests that are sent to the Resource Server. 
  8. The Resource Server validates the access_token on every request that requires authorization and returns the requested data. 

OAuth 1

As you can see, the OAuth working group has deprecated the implicit grant flow as it has some inherent security risks. It is interesting that no big security event caused this change and the OAuth working group was aware of its vulnerabilities at the time of its release and use. Thankfully, the adoption of Cross-Origin-Resource Sharing (CORS) in modern browsers has allowed for more secure authorization flows for client apps. 

Code Authorization Grant with PKCE 

The Code Authorization flow with Proof Key for Code Exchange (PKCE) was created to solve many of the security problems that exist in the implicit flow. It is currently the recommended way to perform authorization on SPAs. This flow introduces the concept of a code challenge and a code verifier to ensure that the client can be trusted by the Authorization Server. 

  1. The Resource Owner sends a request to log into the Client App. 
  2. The Client App generates a code_verifier and a code_challenge. 
  3. The Client sends a request to the Authorization Server with the challenge_code. 
  4. The Authorization Server redirects to an authorization page. 
  5. The User confirms the authorization. 
  6. The Authorization Server saves the code_challenge and redirects the Client to a callback page with an authorization code. 
  7. The Client sends a request with the code_verifier and the authorization_code to the Authorization Server. 
  8. The Authorization Server verifies the code_challenge and code_verifier.  
  9. The Authorization Server returns an access_token to the Client. 
  10. The User performs an action that requires data from the Resource Server. 
  11. The Resource Server validates the access_token on every request that requires authorization. 
  12. The Resource Server returns the requested data. 

OAuth 2

Whew, that was a lot! While this flow may seem rather complicated, luckily, many libraries exist that can abstract away the more complicated bits. This is great as it keeps us in compliance with the golden rule of crypto, that is, “don’t roll your own crypto.” 

Refresh Token Grant 

Coming Soon! This will be covered in the next blog. All you need to know for now is that since JWTs have an expiration time built in, there needs to be a way to renew a user’s session without explicit reauthorization. 

So, there we have it, we now have a way for a client app to access protected resources from a server with the login delegated to a third-party serverStay tuned for concrete examples in the next blog!

 

You May Also Like These Topics