Author: Brian Pontarelli

  • Architecting an Auth System for Applications

    Architecting an Auth System for Applications

    Applications today use many login and authentication methods and workflows. Here, I’ll share the most relevant and proven authentication workflows, which you can use as a basis for architecting and designing an authentication system for traditional web applications, single-page applications and native mobile applications.

    Authentication Workflows for Traditional Web Applications

    Traditional web applications load a web page and provide user functionality using a message-based model where a browser makes an HTTP request to a web server based on the URL in the address bar. The server responds to this request with HTML, CSS and JavaScript and then displays a resource in the browser. Along with traditional web apps, new web apps often still provide functionality in this manner.

    When a user submits a form or clicks a link or button, the browser sends a new HTTP request to the web server and changes the URL in the address bar. The server again responds by returning HTML, CSS and JavaScript and then displaying a resource in the browser.

    Browsers support only two HTTP methods for traditional web apps: GET and POST. GET is used to request data from a specified resource and POST is used to send data to a server to create or update a resource.

    Below are several workflows you can use for traditional web app login and authentication. Note that the application backend is the backend of the application (not the identity provider, or IdP) and native login form is a form built directly into the application instead of an external login form.

    Native login form to the application backend using …

    JWTs and refresh tokens stored in cookies

    Sessions

    Sessions plus refresh tokens stored in cookies

    OAuth 2 authorization code grant using …

    JWTs and refresh tokens stored in cookies (RECOMMENDED)

    Sessions (RECOMMENDED)

    Sessions plus refresh tokens stored in cookies

    OAuth 2 resource owner password credentials grant using …

    JWTs and refresh tokens stored in cookies

    Sessions

    Sessions plus refresh tokens stored in cookies

    Authentication Workflows for Single-Page Applications

    A single-page web app (SPA, pronounced as “spa” or “S-P-A”) runs entirely in the browser after loading the HTML, CSS and JavaScript source code from a web page. After retrieving the HTML, CSS and JavaScript that make up the application, the browser invokes a JavaScript framework that bootstraps and then renders the application.

    SPAs call APIs to handle user interactions and input. For example, if a user clicks a link or submits a form, the SPA might render a different page or form.

    APIs are invoked using XMLHttpRequest, a built-in browser object that can make HTTP requests in JavaScript. When the server responds, the JavaScript running in the browser updates the data dynamically without performing a  full page refresh.

    SPAs use a single request and response model. Since the browser uses XMLHttpRequest, it can support GET and POST, as well as other standard HTTP methods, such as PUT and DELETE. (PUT is used to replace all current representations of the specified resource and DELETE is used to, well, delete the specified resource.) The HTTP method chosen tells the server how to handle the request.

    Here are some workflows you can use for SPA login and authentication.

    Native login form to the application backend using …

    JWTs and refresh tokens stored in cookies

    Sessions

    Sessions plus refresh tokens stored in cookies

    Native login form to FusionAuth using …

    JWTs stored in local storage and refresh tokens stored in cookies

    JWTs and refresh tokens stored in cookies

    JWTs and refresh tokens stored in cookies

    OAuth 2 authorization code grant using …

    JWTs and refresh tokens stored in cookies (RECOMMENDED)

    Sessions (RECOMMENDED)

    Sessions plus refresh tokens stored in cookies

    OAuth 2 implicit grant using …

    JWTs stored in cookies

    JWTs stored in local storage

    Sessions

    OAuth 2 resource owner password credentials grant using …

    JWTs and refresh tokens stored in cookies

    Sessions

    Sessions plus refresh tokens stored in cookies

    When using OAuth for SPAs, note that the browser navigates away from the SPA to the OAuth provider. Once the OAuth workflow is complete, the browser is sent back to the SPA page where it quickly restarts the SPA with cached assets.

    Authentication Workflows for Native Mobile Applications

    Native mobile applications are usually installed on a mobile device or any smart device through an online marketplace like App Store and Google Play Store. Clicking the application icon on the device launches the device operating system, which starts the application and its user interface.

    Almost all native applications call APIs on the server to handle user interactions and input, such as button clicks and form submissions. Native applications often use libraries designed to directly access all of the classes, objects, functions and methods of the source code to communicate quickly with APIs and simplify API calls.

    auth mobile

    Here are a few workflows you can use for native mobile application login and authentication:

    Native login form to the application backend using JWTs and refresh tokens

    Native login form to FusionAuth using JWTs and refresh tokens (RECOMMENDED)

    OAuth 2 resource owner password credentials grant using JWTs and refresh tokens

    Note that native mobile applications can also use the OAuth authorization code grant to exchange an authorization code for an access token. This workflow works with many IdPs and is essentially the same as described in the preceding traditional web application and single-page application sections. The main difference is that the native application pulls the JWT and refresh tokens from the web view at the end of the OAuth workflow.

    Authentication System Best Practices

    The workflows listed above should give you a baseline for following authentication system best practices and architecting a sound login and authentication system for your applications. While these examples use FusionAuth as the IdP, any IdP can be used. Most IdPs are capable of a wide variety of login and authentication workflows, and the examples here are not meant to be exhaustive.

    As you’re designing an authentication system for traditional web applications, single-page applications or native mobile applications, keep in mind that some IdP login workflows can pose serious security risks. As with all things having to do with digital identities and user and data security, it’s important to choose both your IdP and your authentication workflow wisely.

  • Best of 2021 – How to Revoke JSON Web Tokens (JWTs)

    Best of 2021 – How to Revoke JSON Web Tokens (JWTs)

    As we close out 2021, we at devopsy.kinsta.cloud wanted to highlight the most popular articles of the year. Following is the seventeenth in our series of the Best of 2021.

    One of the most common questions about JSON Web Tokens (JWTs): Once they’re issued, how can they be revoked?

    What Are JWTs?

    JSON Web Tokens are portable, industry-standard identity tokens. They are issued after a login request by a central identity server and used to identify and credential a user and grant access to resources. They can be presented by clients such as browsers and external programs. Applications and APIs can examine them to ensure the caller is properly authenticated and authorized.

    The Challenges Involved

    One of the most common questions is how to revoke them. The problem is that once they are issued, no further communication is needed with the identity server. That’s one major benefit of JWTs decentralization.

    Let’s say you use RSA public/private key signing for secure data transmission. After the IdP signs a JWT using the private key, any service that has the public key can verify the integrity of the token.

    Let’s use the Todo-Backend API as an example. The architecture might look something like this:

    Todo API

    Now, Todo-Backend can use JWT and the public key to verify the user’s ID and other attributes, and then use that ID to perform operations on that user’s data. Once the JWT has been issued, Todo-Backend doesn’t communicate with the identity provider at all. As a result, if an administrator has locked or deleted that user’s account in the identity provider, Todo-Backend won’t know about it.

    Managing Revocations Using a Distributed Event System

    The most common way to revoke access to resources protected by a JWT involves setting its duration to a short period of time and revoking the refresh token so that the user can’t generate a new token. This does not revoke the JWT per se; it does solve the root issue, which is to limit access.

    In other words, you can set the JWT’s expiration duration to a short period (e.g., anywhere from a few seconds to, say, ten minutes) and set the refresh token’s expiration duration to a longer period (e.g., a two-week or two-month window).

    During the normal flow, the Todo API would accept the JWT until it expires, at which time access would be denied. At that time the client could present the refresh token to the identity provider, which would send a new JWT to the client. That new JWT would be valid for another ten minutes.

    An administrator can, at the identity provider, revoke the refresh token at any time. Any subsequent request for a new JWT by a client holding that refresh token would fail and access to the Todo API would be lost.

    However, while ten minutes isn’t long, this timeframe still comes with risks.

    One strategic way to handle this challenge is to set up a distributed event system that notifies services when refresh tokens have been revoked. Upon receiving this event broadcast, backends/services would update a local cache that lists users with revoked refresh tokens. After a JWT is verified, this cache would then be checked to determine whether or not access should be revoked.

    This distributed event method truly revokes the JWT, rather than simply waiting for it to expire, as mentioned above.

    An Example of Revoking JWTs

    Here’s a sample solution that provides support for events and webhooks that can be used to implement this revocation strategy. In this example, when a user logs out or has their refresh token otherwise revoked, a jwt.refresh-token.revoke event is emitted. This includes the user ID and the application for which the revocation occurred. It also includes the JWT lifespan for this application (in the below case, 600 seconds). Any JWT for this user that was issued before 600 seconds from the point in time when this event was received is thus revoked.

    For example:

    • User logs in, and JWT ‘abc’ is issued at 1:11pm. JWT is good until 1:21
    • User logs out at 1:15. Entry is added stating that any JWT for this application and user expiring before 1:25 is revoked.
    • Application tries to use JWT ‘abc’ at 1:16. Todo-Backend does not deliver data because this JWT is on the denylist.
    • User logs in, and a new JWT ‘def’ is issued at 1:18. JWT is good until 1:28.
    • Application tries to use JWT ‘def’ at 1:19. Todo-Backend delivers data because this JWT is good until 1:28 and is therefore not on the denylist.

    JWT Revoke

    What you need to do is write a simple webhook that will receive this event and inform JWTManager that the refresh token for applicationId for this user has been revoked.

    JWT webhook

    JWTManager maintains a list of user IDs whose JWTs are revoked. You could also use JWT IDs (the `jti` claim), which, in some cases, might be simpler. JWTManager also launches a thread to clean up the cache to remove expired users and avoid running out of memory.

    Is valid

    For each API call, in addition to all the other checks that should be performed against a JWT (verifying the signature, expiration, issuer and so on), the backend needs to check validity with JWTManager.

    configure webhook

    As a final step, configure the webhook:

    JWT webhook

    The Revocation Process, Simplified

    Using the process described above, you can revoke a user’s refresh token and broadcast the event using a webhook. The webhook receivers then update JWTManager, which will render JWTs for that user unusable.

    The good news is that you can use a webhook and event system to build this feature into your application quickly. You can also write JWTManager implementations into Java, Node and other client libraries for future use. Other languages, such as Ruby, have denylist implementations already written.

    Ultimately, all that’s required are the use of refresh tokens, an API that enables revocation of refresh tokens and a system for distributing the revocation event. This solution should work well with most systems, even large systems with numerous backends.