Developers

Availableapp.erp.io/api/shell/auth/module-token

Module tokens

A short-lived signed token, scoped to one module and one organisation, verified against a public key.

Signed by
The shell
Verified against
Public JWKS
Audience
Exactly one module
Lifetime
Short

What it is for

This is the internal mechanism behind single sign-on between the shell and its modules. It is documented here because integrators ask how it works and because understanding it explains several behaviours that otherwise look arbitrary.

It is not a general-purpose API credential. It cannot be used to call an API, it is not something you mint, and it exists only to carry an authenticated identity from the shell into one module.

What it carries and what is checked

ClaimCarriesRejected if
IssuerWhich shell minted it.It is not our shell.
AudienceExactly one module.It is presented to any other module.
SubjectThe person.The module will not provision them.
OrganisationThe tenant they are acting for.The organisation is not one this module accepts.
ExpiryA short lifetime.It has passed — a replay.

The signature is verified against a public key set the shell publishes. Modules fetch it; nothing shared and secret passes between them, which is why a module can be deployed and rotated independently of the shell.

app.erp.io/api/shell/auth/module-token?aud=crm
Token hand-off
Browser has the shell session cookie
Module has no session of its own → redirects to the mint
Shell mints a token: iss, aud=crm, sub, org, short exp
Module verifies signature against /.well-known/jwks.json
Module mirrors the person and mints its own session
The hand-off, end to end. The module never sees a password and never stores one.

Two consequences you can observe

A session with no current organisation cannot enter any module. The token needs an organisation to name, so the mint refuses. That is the cause of the "signed up and got thrown straight back out" report in Organisations.

Where the token is delivered varies by module. A module running its own authentication library may already own the obvious callback path, so a couple of modules take the token somewhere else. Delivering it to the wrong path produces an authentication error immediately after sign-in rather than a working session.

A module key is not always the module name

The audience claim uses the stored key, which for four modules differs from the product name — Accounting is finance, Phony is sdr, Chat is messaging, Projects is pm. Anything reading tokens or entitlement records sees the key. See Platform.

What this does not do

Not a general API credential

It authenticates a person into a module, nothing else.

Not mintable by you

The shell mints it. There is no endpoint for third parties.

No refresh

Short-lived and single-purpose. The module mints its own session afterwards.

Not usable across modules

One audience each, enforced.

Questions

Can we use erp.io as an identity provider?

No. The model is inbound only, to our own modules.

Where is the public key set?

Published by the shell at a well-known path and fetched by each module.

Does revoking a session revoke module sessions?

Revoking shell sessions is the reliable way to end access. See Security.