3

OAuth 2.0 and OIDC

This chapter is going to get you started on the technical journey to understand the advanced concepts that will be covered in the following chapters.

In this chapter, we are going to learn about the basics of the most used authentication protocol for cloud applications, which is OAuth 2.0, and we are going to appreciate why OAuth 2.0 has become the de facto standard in web authentication.

This chapter will also introduce you to OpenID Connect (OIDC).

OIDC extends the OAuth 2.0 protocol by introducing new flows, reusing some existing ones, and making the user, not the application, the center of these flows.

In this chapter, we will go through and learn all about the basics of OAuth 2.0 and OIDC, their similarities and differences, where they can be used and why, and what the actors that participate in authentication and/or authorization flows are.

This chapter will not analyze the flows of these protocols in depth; those will be covered in the next chapter. We are going to provide some technical background information that will be needed to better understand the upcoming chapters of the book.

In this chapter, we are going to cover the following topics:

  • OAuth and OIDC basic concepts
  • How OAuth and OIDC work together
  • How the protocols are implemented in the real world
  • Technical background

OAuth and OIDC basic concepts

The basic architecture of applications that are composed of multiple tiers separating the presentation from the business logic and data, with the business logic exposed through a set of services, has largely gone unchanged for the last decade.

However, the environment in which these applications are expected to operate has completely changed in this same timeframe. Today, you cannot just offer a simple browser-based website; you need to also support IoT devices (such as presentation screens, smart devices, sensors, and electrical appliances) and mobile clients, and these mobile clients must be supported across a broad range of devices, mostly based on iOS, Android, or Windows.

In today’s landscape, users expect applications and services to interoperate – to be able to be used together. For example, users expect to be able to post the latest purchase they have made from Amazon or ASOS to their Facebook wall or share a photograph on Instagram from the camera application on their mobile phone. These requirements have also brought the need to manage user consent for sharing information.

Over the course of the last decade, we have already seen the movement to extract identity management logic out of applications and enable users to authenticate to applications from external identity providers and utilize claims-based authentication. Historically, we have seen WS-Federation and SAML fulfilling this requirement. These protocols have been covered in Chapter 1, Walkthrough of Digital Identity in the Enterprise. There is also an undeniable trend of retail websites (among others) today offering authentication through external identities.

With the growth of mobile clients, the widespread adoption of REST-based web APIs, and the need to support user consent on resources across these APIs, the industry has come together and agreed on OAuth as the delegated protocol for securing web APIs, with the latest evolution, OAuth 2.0, supported by Google, Microsoft, Facebook, and PayPal.

It’s important to know that OAuth 2.0 is intended to be an authorization protocol, not an authentication protocol. As you may also be aware, authentication is the process of determining whether someone or something is, in fact, who or what it says it is, whereas authorization is mainly the process of checking what privilege the user has to access a specific domain or application.

It’s important to note that OIDC is intended to be used for authentication and OAuth is the protocol to be used for authorization. This is the reason why OAuth and OIDC complement each other and why, in technical literature, they are often found mentioned together.

How OAuth and OIDC work together

Despite OAuth being commonly used together with OIDC to cover both authentication and authorization requirements, it is not mandatory for them to be used together. Just to provide an example, OAuth can be used for authorization even in contexts where another protocol (for example, the SAML protocol, described in the Security Assertion Markup Language section in Chapter 1, Walkthrough of Digital Identity in the Enterprise) is used for authentication. As a matter of fact, the specification of OAuth does not include OIDC, which can be seen as an optional layer to add.

Let’s use a concrete example to better understand the usage of the OAuth protocol without any authentication flow. OAuth is the protocol that is used by Facebook when a user needs to access a third-party application (for example, Spotify) with their Facebook account. In this context, the user is usually already logged in to the Facebook platform and they are just prompted to grant privilege to the third-party application to use information stored in the Facebook account so that the third-party application can acquire this information when the user enables Facebook to release it to the third party. The granting of this privilege is done through the OAuth protocol and it can happen without any explicit authentication. Once the third-party application grabs the access token (the concept of the access token will be covered in detail in the next chapter) from the Facebook identity provider, it can allow the user to register or authenticate with whatever protocol the third-party application wants to implement, which is completely independent of the OAuth Facebook authorization flow described previously.

The previous flow outlines a scenario where OIDC is not involved.

The following screenshot shows the login prompt presented by Spotify. The blue LOG IN WITH FACEBOOK button triggers the OAuth flow, which is supposed to provide Spotify with the authorization to access the user’s Facebook data. It also allows the user to log in with their username and password and not just with Facebook:

Figure 3.1 – Sample of OAuth login

Figure 3.1 – Sample of OAuth login

In the next chapter, we will also provide examples of flows focused on authentication rather than authorization as the one we’ve just presented was; as a consequence, these flows will have OIDC as the main actor, rather than OAuth.

To best appreciate the differences between the OAuth and OIDC protocols, it is important to reference how they are defined in the original specs (https://openid.net/connect/):

The OpenID Connect specification is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.

Technically speaking, OIDC is built on the OAuth 2.0 protocol. OIDC uses an additional JSON Web Token (JWT): the ID token. This is to create standards for areas where OAuth 2.0 leaves ambiguity (for example, scopes and endpoint discovery).

How the protocols are implemented in the real world

It is important to note that both OAuth 2.0 and OIDC are standards supported by a number of services, including Azure Active Directory, OWIN and Katana, NetIQ Access Manager, Google Authentication, and PingFederate, just to mention a few.

Generally speaking, as they are the de facto standard, a developer who wants to implement an OAuth/OIDC flow for their application doesn’t necessarily need to know the specification in depth and apply custom code to their solution. Client libraries, generally grouped into frameworks, that implement these protocols can be found in the most widely adopted programming languages to ease the development of an application that implements these standards.

The following is a non-exhaustive list of technologies that enable developers to take advantage of either commercial or non-commercial libraries to implement authentication/authorization through OIDC/OAuth:

  • ActionScript
  • C
  • ColdFusion
  • Dart
  • .NET
  • Elixir
  • Elm
  • Erlang
  • Go
  • Java
  • JavaScript
  • Kotlin
  • Lua
  • Node.js
  • Objective-C
  • Perl
  • PHP
  • PowerShell
  • Python
  • C++
  • Ruby
  • Rust
  • Scala
  • Swift

To better understand OAuth, this book will not focus on these libraries but on the protocol specs themselves. For more information about the implementation of these libraries, you can consult the following website: https://oauth.net/code/.

Often, when we are approaching OAuth for the very first time, the questions at the forefront of our minds are generally focused on how these protocols fit into the wider picture. The typical questions on a newbie’s mind are the following:

  • In what kind of solution can I adopt OAuth?
  • Can I adopt OAuth for an IoT solution? If so, how can I do it?
  • Can I use OAuth for both web applications and single-page applications? What are the differences?

All of these are valid questions and they need to be tackled individually in detail. The current chapter will focus on what can be done using OAuth. The next chapter will tackle the OAuth flows and it will tell us more about how to perform certain authentications/authorizations using the OAuth/OIDC combination.

The following is a list of the most typical use cases that can help you to understand in which context OAuth can be adopted:

  • Single-page apps
  • Web apps
  • Web APIs
  • Mobile apps
  • Native apps
  • Daemon apps
  • Server-side apps

How OAuth or OIDC is adopted and which authentication flow needs to be chosen is dependent on the scenario. Whether it is browser-to-server communication, mobile-to-API communication, or server-to-server communication, each of them is going to have a different flow. The flow can also be different for the same scenario but with a different implementation; for example, within browser-to-server communication, a single-page application typically has a different OAuth flow than a multi-page application (we will discuss this in more detail in later chapters). This requires careful attention to the application design. It is important to identify what our context is before moving forward and choosing the proper flow to implement. The wrong flow may expose the application we are designing to unwanted security risks.

OAuth flows will be discussed in depth in Chapter 4, Authentication Flows.

For further information about which authentication flow to use in a specific scenario, it is recommended to use the external Microsoft documentation as a reference: https://docs.microsoft.com/en-us/azure/active-directory/develop/authentication-flows-app-scenarios. This article provides a full picture of which OAuth flow to apply to a specific context.

This chapter provides a high-level picture of the main use cases for OAuth; you can appreciate them in depth once you are familiar with the flows discussed in upcoming chapters.

Technical background

Before diving deep into flows, it’s important to understand some basic concepts regarding the actors that participate in the authorization or authentication process. If you are familiar with other protocols, you will appreciate that the concept is not so different.

Let’s start with the basics by trying to understand what the actors, devices, and servers involved in an OAuth 2.0/OIDC flow are and what their role during the authentication and authorization process is.

These are the main parties involved in nearly all protocol exchanges. The following diagram summarizes all of them:

Figure 3.2 – OAuth/OIDC parties

Figure 3.2 – OAuth/OIDC parties

The preceding diagram shows the typical parties involved in authorization/authentication flows. The following are descriptions of each of the roles reported in the diagram:

  • Resource owner: This is the entity that allows access to the final resource (the resource server). If this entity is a human, then it is also called an end user.
  • OAuth/OIDC client: This is the means by which the resource owner accesses the resource server. A client can be any device: an IoT sensor, a smartphone, a desktop, or a server. Technically speaking, regardless of the device that implements the flow, usually, there is a major distinction between a native client and a web client.
  • Resource server: This is the entity that hosts the resource that needs to be accessed by the client. Access to this server must be protected properly by checking the validity of the client requests’ access tokens.

In other words, we can connect the dots with the OAuth/OIDC client and say that in a context when the OAuth/OIDC is passive (that is, authentication is carried out by a web client and not by a native client), the resource server is the entity that sends HTTP responses as redirects to take the user to the authorization server. This enables this component to drive the behavior of the OAuth/OIDC client.

  • Access token: The access token is released by the authorization server upon successful authorization/authentication. More information about access tokens will be provided later in this section.
  • Authorization server: Finally, the authorization server is the entity that issues the tokens. It publishes the endpoints of the protocols that the clients need to use to implement the authentication flows and receive the access tokens. The authorization server typically has a configuration stored somewhere either in their filesystem or an external database that contains all the applications (clients) allowed to invoke their endpoints and the resource servers from which these applications are allowed to ask for a token.

A web client typically behaves passively. In other words, the web client does not directly implement the authentication/authorization logic; rather, the flow is driven from the server and not from the client. This means the server sends an HTTP status code (that is, a 302 redirect) to drive the behavior of the client and redirect it to the identity provider to require the user to log in. This logic is not even known by the client, which passively executes the instruction received on the server side.

Indeed, a native client explicitly implements authentication flow logic and does not need the server to tell it what it has to do or where it has to go by using a redirection, which is typical of OAuth flows adopted out of the native client context.

As you will probably already know, generally speaking, in all contexts where user interaction is not possible (for example, an IoT device), a native client should be considered and a non-passive flow should be implemented. On the other hand, in all contexts where the user can explicitly log in to the web client, this is generally adopted.

To summarize, the OAuth/OIDC client is the entity that receives the protocol’s final tokens (the access token and ID token), stores them, and uses them to access resource server-provided services if authorized.

To understand the concepts discussed in the previous list better, let’s see how the actors mentioned so far are used in a sample application design.

We are going to describe a sample that covers the most typical application design, which implements web client authentication.

The resource server is the server where the application is implemented. Web applications are implemented on top of application servers such as Apache, NGINX, or IIS. The application server can be on a virtual machine, a PaaS service such as Azure Web Apps, or AWS Elastic Beanstalk, just to mention a few of the most used cloud services. For the sake of understanding, it is important to know that the resource server is where developers deploy their code, which will then be consumed by the browser. During development, the developer chooses to delegate the authentication to an external entity, which is the authorization server. As a consequence, we can expect the application not to store information such as passwords because the whole authentication (OIDC) or authorization (OAuth) process will be delegated to the authorization server. As we are going to learn in the next chapter, when an OAuth/OIDC client accesses an application that is exposed through a resource server, the resource owner will never make their credentials visible to the resource server. This is because the resource server will just redirect the OAuth/OIDC client to the authorization server, and only in this location is the resource owner supposed to insert their credentials.

It’s important to remember that what we described so far is consistent with the web client authentication.

An authorization server that is implemented by major identity providers nowadays enables both authorization and authentication. As a consequence, they tend to follow both the OIDC and the OAuth specs.

Reporting the full list of specs for each protocol is out of the scope of this book; however, it is important to mention the well-known endpoint. The well-known endpoint is usually a suffix that can be added to the authorization server URL to obtain public information about it.

As an example, in Azure Active Directory, which is the Microsoft identity provider that follows the OAuth 2.0 and OIDC specification, it is possible to add the .well-known/openid-configuration suffix to the authorization server URL to obtain information about the logged entity. More information about the OAuth 2.0/OIDC authorization server metadata can be found in the OAuth 2.0 specification, under Obtaining Authorization Server Metadata at the following URL: https://datatracker.ietf.org/doc/html/rfc8414.

According to the Request for Comment (RFC) and in order to be compliant with its standards, an authorization server must provide an endpoint to enable public entities, including the resource servers, to obtain information about it. This is particularly important to enable the resource server to get access to the public keys required to validate JWTs signed by the authorization server with the related private keys.

To enable a resource server to delegate the authentication to an authorization server, the resource server needs to be registered against the application server.

In other words, the authorization server needs to be aware of all the applications that can perform authentication against it. A registered application will obtain a pair of strings from the authorization server: the client ID and client secret. This is necessary because this pair of strings will then be used by the resource server whenever an authentication or authorization activity needs to be performed against the authorization server. This pair of strings is supposed to be confidential and, as a consequence, be used by the resource server as proof of an already-performed registration. This can happen because, for every authorization/authentication request, the authorization server will double-check whether the pair of strings matches with the one released to the resource server during the registration phase.

Application identity details are registered in the authorization server, which typically retains the following information:

  • Application ID: This is a string that uniquely identifies a client application within the authorization server.
  • Client secret: This is a secret, password, or certificate that is used in some OAuth flows to authenticate a client application so that it can retrieve an access token from the authorization server.
  • Redirect URIs: These are the URIs specific to the application to which the issued tokens are sent.
  • Allowed scopes: These are allowed scopes that a client application can request for a specific resource server. For instance, a client application may only be allowed to request the read scope for a specific REST API protected by the authorization server.

OAuth uses the following types of tokens (which are issued by the authorization server):

  • Access tokens: Access tokens are basically credentials used to access protected resources (resource servers). An access token is, according to the public definition (https://datatracker.ietf.org/doc/html/rfc6749), “a string representing an authorization issued to the client. The string is usually opaque to the client. Tokens represent specific scopes and durations of access, granted by the resource owner, and enforced by the resource server and authorization server.” Typically, access tokens are issued in a specific format called a JWT, which is a JSON file made of three parts: the header, the body, and the signature. The body contains the claims for the application or the user for which the token has been issued. The following is an example of a JWT:
    {
     "typ": "JWT",
     "alg": "RS256",
     "kid": "JRX9C2vPdG2-3YDi14buhEVvO_O9bFwzz-pMBxtDh18"
    }.{
     "exp": 1633425451,
     "nbf": 1633421851,
     "ver": "1.0",
     "iss": "https://myauthzserver.issuer.com/",
     "sub": "application_or_user_unique_id",
     "aud": "audience_unique_id",
     "acr": "signin",
     "nonce": "defaultNonce",
     "iat": 1633421851,
     "auth_time": 1633421851,
     "name": "unknown"
    }.[Signature]

The most important claims are as follows:

  • aud: The audience or the entity (resource server) the token is intended for
  • iss: The unique ID of the authorization server that issued the token
  • exp: The expiration of the token; the timeframe for which the token is considered valid
  • sub: The subject of the token; the entity the token has been issued for (an application)
  • Refresh tokens: Refresh tokens are credentials used to obtain a new access token when it becomes invalid without involving the user in the process. They typically have an expiration time far greater than an access token, they are opaque to the client, and they are intended for use only with the authorization server. They are never sent to the resource server.

OIDC introduces a new type of token:

  • ID token: An ID token is basically an access token for users. It’s the SAML token counterpart used for user authentication that contains the user’s claims needed by either the client OIDC or the resource server to establish a user’s identity.

Both the OAuth and OIDC protocols utilize two authorization server endpoints (HTTP endpoints) within their flows:

  • Authorization endpoint: This is used by the resource owner who interactively obtains (by typing in their username and password) an authorization grant after successful verification of the resource owner’s identity by the authorization server.
  • Token endpoint: This is used by the client to obtain an access token, an ID token, or both (depending on the specific flow used).
  • User info endpoint: This is an authenticated endpoint that is used by an application to retrieve additional information (claims) about a user that has already been authenticated. To access this endpoint, an application must use an access token that is typically issued by the authorization server during the user’s authentication.

Last but not least, let’s understand the different types of client applications that can be encountered in the different flows:

  • Web applications: A passive web application hosted on a web server and accessed through a browser
  • Native applications: An application that typically does not use a web browser and is installed on the resource owner’s device (for example, a mobile application)

Moreover, web and native applications can be of two different types:

  • Public clients: Client applications that are not trusted because they are installed on a resource owner’s device
  • Confidential (private) clients: Client applications hosted on a secure server and accessed remotely by a user agent (for example, a web browser)

Each HTTP request against one of the authorization server endpoints contains specific headers (or query string parameters) that the protocols describe within their specifications. The most important are described as follows:

  • response_type: This parameter is used by an application during the initial authentication request to specify which piece of information it would like to receive in the response returned by the authorization server
  • grant_type: This is used to specify which OAuth 2.0 or OIDC flow must be used
  • client_id: An ID for the application that has been registered in the authorization server
  • redirect_uri: The URL, registered in the authorization server, to which the token should be issued
  • client_secret: A secret (password) assigned to an application and used by a confidential client to authenticate the application’s identity
  • scope: A set of space-separated strings that specify the information (claims) and the audience (resource server) that should be issued within the security token
  • username: The username of a user, specified only when using the Resource Owner Password Credentials (ROPC) flow
  • password: The password of a user, specified only when using the ROPC flow

Knowing how OAuth 2.0 and OIDC work in the background might seem like something that is done just to satisfy a technical appetite (if any), but this is far from the truth; knowing the protocols can really make a difference during the design phase of an application. As a matter of fact, the interoperability of an application with other applications in the same enterprise or applications developed by external teams strongly depends on the authentication and authorization strategy that has been chosen for your application. Choosing the right OAuth 2.0 or OIDC flow can really make the difference in the user experience since single sign-on can only be achieved if specific authentication flows are selected, and the possibility to strengthen the overall identity security and surface attack area depends on these choices too (we will see how those flows work later in the book).

Summary

In this chapter, we reviewed the analogies and differences across OAuth and OIDC. We understood OAuth and OIDC to be authorization and authentication protocols, respectively. These protocols share the same flows and logic.

OIDC is defined as an authentication protocol that runs on top of OAuth. This is because the flows adopted are the same.

We also familiarized ourselves with the terminology needed to understand the OAuth 2.0/OIDC flows that we will cover in depth in the next chapter, and the patterns that will be discussed in a later chapter.

This chapter provided the basis to understand these protocols and their related flows better. In the next chapter, we are going to view how these concepts are implemented and look at OAuth flows in much more detail.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.205.166