Connect Infisical with OIDC
Give Unirail read-only access to one folder of your Infisical through OIDC federation, so provider credentials never leave your vault.
Unirail never stores your provider credentials. Instead, a machine identity in your Infisical trusts Unirail's OIDC issuer, and Unirail logs in as that identity whenever it needs to call a provider. You grant it read access to one folder, and you can revoke it by deleting the identity.
You'll do this once per Unirail environment: sandbox reads your test credentials, production reads your live ones.
How it works
- Unirail signs a JWT for your organisation and environment with its own key, published at its JWKS URI. The token lives for five minutes.
- Infisical checks the token against the issuer, subject and audience you configure on the identity, then returns a short-lived access token for that identity.
- Unirail reads the folder with that token and keeps the values in memory only, for at most five minutes. They are never written to Unirail's database, KV, logs or traces, and there is no client secret or vault token in Unirail to leak.
Before you start
- An Infisical project (Infisical Cloud in the US or EU, or self-hosted) and permission to create machine identities and project roles in it.
- A Unirail organisation, and the environment you're connecting open in the dashboard.
Lay out the folder
In the Infisical environment this Unirail environment should read (for example dev for sandbox, prod for production), create a /unirail folder with one sub-folder per provider. Each provider's keys go in its folder, named exactly as below:
| Provider | Path | Holds |
|---|---|---|
| Enable Banking | /unirail/enablebanking/APPLICATION_ID | Enable Banking application id (the JWT kid) |
| /unirail/enablebanking/PRIVATE_KEY_PEM | The application's RSA private key, PKCS#8 PEMsecret | |
| Plaid | /unirail/plaid/CLIENT_ID | Plaid client id for this environment |
| /unirail/plaid/SECRET | Plaid secret for the matching Plaid environment (sandbox or production)secret | |
| Yapily | /unirail/yapily/APPLICATION_ID | Yapily application id |
| /unirail/yapily/APPLICATION_SECRET | Yapily application secretsecret |
The general shape is <basePath>/<railId>/<KEY>. /unirail is the default base path; you can choose another when you bind the environment.
Add Infisical as a secret source
In the dashboard, open Secrets and add an Infisical source with:
- Name: anything that tells you which project it is.
- Site URL:
https://app.infisical.com,https://eu.infisical.com, or your self-hosted URL. - Project ID: from the project's settings in Infisical.
A source belongs to the organisation, so every environment can use it.
Copy the federation values
Still on Secrets, the environment shows the values Infisical needs to trust Unirail:
| Value | Looks like |
|---|---|
| Issuer | https://api.unirail.dev/oidc |
| Discovery URL | https://api.unirail.dev/oidc (Infisical appends /.well-known/openid-configuration itself) |
| JWKS URI | https://api.unirail.dev/oidc/jwks.json |
| Subject | org:<orgId>:env:<envId>, unique to this environment |
| Audience | https://api.unirail.dev/oidc |
Copy them from the dashboard rather than typing them: the subject is what stops one environment's token from reading another environment's folder.
Create a machine identity
In Infisical, open Organization → Access Control → Identities and create an identity named after the environment, for example unirail-sandbox, with no organisation role. It only needs access to one project.
Add OIDC auth to the identity
On the identity, add the OIDC Auth method and fill in:
- OIDC Discovery URL: the discovery URL.
- Issuer: the issuer.
- Subject: the subject, exactly.
- Audiences: the audience.
- Leave Claims empty, and keep the access token TTL short. Unirail logs in again whenever it needs to.
If Infisical added another auth method to the identity by default, such as Universal Auth, remove it so the identity has no client secret.
Give it read access to /unirail
In the project, create a custom role, for example unirail-read, that can only read secrets, with two conditions:
- Environment is the one you laid out in the first step (for example
dev). - Secret path matches
/unirail/**.
Then add the identity to the project under Access Control → Machine Identities with that role. Nothing else: no write, no other environments, no other paths.
Bind and verify in Unirail
Back on the environment's Secrets page, bind it with:
- Machine identity ID: the identity's id from Infisical.
- Infisical environment: the environment slug, such as
dev. - Base path:
/unirail, unless you chose another.
Press Bind environment, then Verify access. Unirail logs in with its OIDC token, lists the base path and reports the key names it found. It never shows or stores the values.
Add connections
Open Connections and add each provider with the matching provider environment: sandbox in a test environment, production in a live one. Unirail looks under <basePath>/<railId>/ and its check reports how many of the required keys it found.
Revoking access
Delete the identity in Infisical, or remove its OIDC auth method. Unirail's next login fails, cached values expire within five minutes, and new provider calls stop until you bind a new identity.
Things to know
- Cold starts. The first provider call on a fresh Unirail worker adds one round trip to Infisical before it can call the provider.
- Availability. If Infisical is unreachable, workers that already hold credentials keep working until they expire, and new operations on fresh workers fail closed rather than falling back to anything stored.
- In memory is still in use. Unirail holds credential values in memory while it calls a provider. "Never stored" means never persisted, never logged, and only ever read through a grant you can revoke.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Verify access says login failed | The issuer, subject or audience on the identity doesn't match the dashboard exactly, or the identity has no OIDC auth. |
| Verify access says forbidden | The identity isn't in the project, or its role lacks read on that environment or path. |
| Verify access finds no keys | The source environment or base path is wrong, or the folder is empty. |
| A connection finds some keys but not all | A key name differs from the table above. Names are case-sensitive. |
| Verify access can't reach Infisical | The site URL is wrong, or your self-hosted Infisical isn't reachable from the internet. |