Skip to main content

Testing Auth

Testing with Authress follows the test pyramid. We'll start at the base level and work our way up to the top.

The Test Pyramid

Scenariosโ€‹

Below are listed different testing scenarios along with their recommended strategy for accomplishing that. There are multiple different levels of the test pyramid, so we'll enumerate through each one of them.

Unit Testingโ€‹

Usage: Function under test

You have the Authress SDK or HTTP client in your code base making calls to Authress. In your unit tests you only need to validate the SDK of your data models matches. For these tests you'll mock Authress and return success or failure where appropriate. Your standard unit testing tools and the Authress SDK models are sufficient for this test.

Component Level Testingโ€‹

Usage: Component under test

Like unit testing, while whole components will be validated for behavior, external communication should still be mocked directly, using the same tools as the ones you use for unit testing. Other than the functionality under test and the expectations on responses to be validated there is very little about these tests that need to be further validated.

Service Level Testingโ€‹

Usage: Pull Requests and local developer testing

At the next level up, you don't want to mock your service functionality, but other services, such as the database (optional) and Authress should be still mocked. We are essentially mocking API calls. Under these circumstances, the appropriate tool to use is the Authress Local container. The container is a thin mock of Authress as a service which already implements most necessary SDK and Authress API integrations.

This way you can fully test the complexities of your service without needing a valid Authress account or make unnecessary API calls to Authress. Especially at scale this proves a cost effective and performance optimized interaction.

Run Authress Local on your machine
# Download the package
podman pull ghcr.io/authress/authress-local:latest

# Run the package as a daemon (-d) on port 8888 (-p 8888:8888)
podman run -d -p 8888:8888 authress/authress-local:latest

Integration Testingโ€‹

Usage: Non-ephemeral long lived environments

At the integration level between multiple accounts, we recommend standing up a shared dedicated Authress account. This is in line with our environment management recommendations. A separate dedicated Authress account helps to ensure automated testing that requires the use of components across your whole platform are using a shared instance. Aspects such as Infrastructure as Code (IaC) can be validated here by running your IaC scripts against this shared Authress environment.

If you need third party services or cloud providers to interact with Authress as part of your testing, Authress supports Open ID Connect (OIDC) as a mechanism for token acceptance. You can configure Authress to trust JWTs that are generated by other systems via the Trusted Connection Providers configuration options.

Manual Exploratory Testingโ€‹

Usage: Human validation tests

In some cases, you might want to have someone review a flow, or validate an endpoint works from a developer tool such as Insomnia, curl, or your Open API explorer. To do this, you'll need a valid JWT likely from your production environment. Depending on the scale of your tests, rather than having a user manually change the saved user configuration, you can bypass the Authress Login, and directly generate a JWT. There are two ways generate JWTs directly:

  1. Use the Authress SDK Service Client Provider and pass in the Access Key. The SDK will automatically generate a valid JWT that can be used by your services, correctly validated by the Authress SDK verifyToken() method, as well as the Authress API. This allows you to bypass the UI login process. You can easily inject this into your UIs as well when necessary for UIs under test running on localhost (locally or in your CI/CD process).
  2. Alternatively if you need a JWT that represents a specific user ID, the OAuth Login token API is also available. You can call the API to generate a JWT that can be injected into your UIs for testing.

Both of these strategies are effective for human triggered tests as well as automated tests running against a UI that is available on localhost or in a headless browser instance. Many headless browser technologies allow injecting in variables. For example Puppeteer support directly setting cookies like this:

Set an override JWT cookie using puppeteer
await page.setCookie({
name: 'custom-jwt-token-override',
value: JWT
});

Then in your UI code you can add a wrapper for the Authress Login SDK to utilize this cookie instead of the JWT found from Authress:

Allow the injected override JWT
async function getAccessToken() {
const accessTokenOverride = document.cookie.split(';').map(c => c.split('=')).find(c => c[0] === 'custom-jwt-token-override')?.[1];
return accessTokenOverride ?? await loginClient.ensureToken();
}

Production Testingโ€‹

Usage: Validating user flows in your production App

When you want to do production validation tests, you'll need a strategy that works exactly the same as your users go through and can generate tokens in a safe way. This means requiring a call in your UI to the Authress Login SDK. Fundamentally there is no automated solution that is both safe for automation but can protect against bots without extensively added complexity.

As such, this strategy should be avoided unless it is your last result. There are a number of different options here, but as you actually want the full authentication experience, you'll need to actually automate the full flow and have it completed:

  1. Set up an email address in your SMTP server to receive Authress generated login emails. If you select the user email magic link option or the username and password option, then you'll need a server that can receive emails and click the link in these emails. This of course is non trivial and our recommendation is to avoid if possible. As part of the log in, Authress will send an email to the registered user email address, and thus you'll need to be able to receive it and process that email.

  2. Use an OAuth provider, most OAuth providers protect against bots and automation. For instance, attempting to log into Authress using a Google workspace account via Headless Chrome is likely going to be blocked. However, if you have your own OAuth server then you can hook that up to Authress to generate tokens. Since Authress supports every standardized OAuth providers out of the box, you can add in a new connection with the relevant connection information and you'll be good to go.

  3. Using an Authress Service Client to generate an JWT scoped to that specific service client as the user ID. The generated token can be easily inserted into your automation running your test via Headless Chrome. More details about generating tokens in this away is available in the Solutions section below.

  4. Use the Custom Authentication flow via a service client.

This last way allows you to intercept the auth request at Authress and generate a token. This is very similar to the previous option but Authress provides first class integration for this. In short as part of login, your automation user will be sent from your UI directly to your custom auth UI. From there your custom auth API will verify the request and return success back to Authress. Then Authress will generate a JWT for this user and pass the result back to your UI. Remember, since this mechanism is open, you'll want to verify that the automation user has been sufficiently validated before returning success to Authress. More details about how to set up this flow are available in the Custom Auth Connection Guide.

Solutionsโ€‹

To wrap up this article we'll review the different suggested solutions to help you pick the appropriate one and take the next steps for testing your flow.

Authress Localโ€‹

Authress Local provides a shim of the Authress API to be used in either offline scenarios or in cases when you would normally want to mock the service. In most testing scenarios above the unit test, this is probably the solution. As a reminder there is a dedicated article for Authress Local available with more details.

As a quick reminder, the setup requires only pulling the container and running it. You can use docker, podman, or something else:

Run Authress Local on your machine
# Download the package
podman pull ghcr.io/authress/authress-local:latest

# Run the package as a daemon (-d) on port 8888 (-p 8888:8888)
podman run -d -p 8888:8888 authress/authress-local:latest

Service Client generate JWTโ€‹

Every service client has the capability to generate JWTs that can be used in almost every other testing scenario. These are real JWTs and thus represent the service client User ID, which means permissions can also be assigned to them. You will generate tokens the same way you would generate a token for a Machine-To-Machine authentication flow.

Use an Authress SDK to generate a service client JWT for testing.
import { ServiceClientTokenProvider } from '@authress/sdk';

// Configure the custom domain: https://authress.io/app/#/settings?focus=domain
const serviceClientSecretAccessKey = 'sc_aaa.acc_001.secret';
const authressCustomDomainUrl = 'https://auth.yourdomain.com';

class TestSetup {
async generateJWT() {
const serviceClient = new ServiceClientTokenProvider(serviceClientSecretAccessKey, authressCustomDomainUrl);
const token = await serviceClient.getToken();
return token;
}
}

Depending on the SDK there may be additional recommend parameters to be used to get your token to exactly match your needs. However in most case, no additional configuration should be necessary beyond the creation of a Service Client and an associated access key.

Custom Authentication Flowโ€‹

The Custom authentication flow exists to provide a mechanism to generate tokens for your users during their log in. It exists in case you have a mechanism which is not OpenID, OAuth, or SAML compatible, or just want to generate tokens for a specific user for a test. When logging the user in, make sure to select the appropriate custom Authress Identity Connection and follow the flow that you set up for that connection.

This is fairly involved, and thus is not the recommended path, but there are some scenarios that require it. Since it is complex, the recommended starting place is the guide on Creating a custom authentication connection.