2.3 Authentication
Now that we can create users in the Issue Tracker application,
we turn out attention to authentication and security. We'll learn
about the difference between authentication and authorization,
sometimes referred to as authn and authz, respectively. From
there, we'll learn about common protocols implemented by a large
number of companies that enable features like single sign-on (SSO).
Authentication vs. Authorization
These terms are so often misused and misinterpreted that it's worth dedicating a short section focused on clearing it up.
Authentication is used to verify that someone says who they say they are. In other words, if I log in to an application, I need to authenticate myself as the user that I claim to be. Traditionally, I perform this process by providing my username and password, which only I should know. Thus, when I use my private credentials and prove that I am the owner of the account, I have authenticated myself as the user that I say I am.
Authorization, on the other hand, is used to determine what actions a user is allowed to perform in an application (this is also known as access control). In other words, regardless of if the user is actually who they say they are, authorization determines what capabilities the user has.
For the Issue Tracker application, authentication is used in the login
process (which you will develop in Assignment 3), whereas
authorization can be used to make issues private to certain cohorts of users,
and also distinguish between which users can edit issues versus read issues,
similar to reading and writing documents created in Google Docs, for example).
Session management
As you've probably noticed, a variety of popular websites support persistent sessions, such that you're still logged in after days, weeks, or even months away from the platform (e.g. Amazon). Web browsers are able to support this functionality with HTTP cookies, which are small pieces of information that are exchanged between the Web browser client and the application server. In many cases, a cookie is used to personalize your experience, such that it is used to recognize which user is logged in.
The data encoded in an HTTP cookie depends on the application server that manages
it. A common data format used in applications today is known as the JSON Web Token
(JWT).
JWT
The JWT is a token format that is used to represent claims between two parties (i.e. the client and server). JWTs on their own are not inherently secure, but they can be signed with a secret value along with the HMAC algorithm (which is commonly paired with the SHA256 hash function). There's a lot to unpack here, so let's break it down with a visualization.
A JWT is represented as a dot-delimited string, containing exactly three components: the header, payload, and signature. This is represented as the following:
The jwt.io website (created by Auth0) provides a great visualization tool
for changing header, payload, and secret values so that you can visualize how the
rest of the token changes. Give it a try, and set your own name in the payload, which
is currently set to John Doe. Now try and change the secret value - do you see how
the cryptographic signature changes with each of your keystokes? This demonstrates the
effects of the HMAC-SHA256 hash algorithm in real-time!
JWTs in practice
But what's the point? How is this actually used in practice? The simple JWT structure can actually be used to implement both authentication and authorization flows.
JWT claims are encoded in the <$payload> portion of the token. The sub claim
uniquely identifies the subject of the token, and is commonly used to associate a
client request to some internal user data. For example, the sub claim can be used to
associate a token to additional user data stored in the persistence layer, but not
stored in the JWT.
For authentication, the application server can generate and respond with a JWT when the user logs in, and the user can use the token to make more authenticated requests. For web applications, the JWT can be stored as a HTTP cookie, which can be set in the client's browser with the Set-Cookie response header.
Then, for authorization, the JWT can encode a variable set of custom claims that
can be recognized by the application server to grant additional permissions. For example,
a user with admin privileges might have a JWT that contains a <$payload> with the
following:
With this, the application server can handle client requests by first inspecting the
JWT sent in the request's HTTP Cookie request header, verifying the signature
contained (which prevents users from obfuscating information found in the <$header>
and <$payload>), then determining what capabilities this user has based on the claims
contained in the <$payload>, and finally serving the request by either permitting the
operation or rejecting it based on unsatisfactory permissions.
OIDC and OAUTH2
The OpenID Connect Protocol (OIDC) is a protocol built on top of OAUTH2.
In short, OIDC is used to implement single sign-on (SSO), which makes it
possible for users to authenticate themselves with other popular applications. For example,
you've probably signed in to an application with Google, Facebook, Apple, or some
other identity provider - this is OIDC in action! When you log in with your identity
provider of choice, your personal information is returned in the form of a JWT, which is
then used to authenticate future requests (as described above).
Okta (another popular identity provider) created a fantastic video that explains OIDC in greater detail - please watch it by clicking on the image below before proceeding to the assignment!
