Authentication
How an App verifies calls from VARIO Cloud and authenticates its own API requests.
An App authenticates in two directions, and it is important not to confuse them:
VARIO Cloud → your App
appToken
Is this incoming request really from VARIO Cloud?
Your App → VARIO Cloud
accessToken (obtained from an offlineToken)
May this App read/write data in this tenant?
The VARIO App Framework handles both for you. This page explains what it does, so you can debug it — and so you can implement it yourself if you don't use the framework.
The client configuration
Your App is identified by the four values you receive when creating the App. The demo app keeps them in app-client.js, exporting them as a module:
// app-client.js
module.exports = {
appIdentifier: '…',
clientId: '…',
clientSecret: '…',
appJWK: { keys: [ /* … */ ] },
};You pass this object when constructing the App:
const VarioCloudApp = require('@vario-software/vario-app-framework-backend/app.js');
const client = require('../app-client.js');
const app = new VarioCloudApp(client);
app.port = 8443;
app.uiPath = path.resolve(__dirname, '../frontend');
app.offlineToken.init().then(() => app.start());app.start() validates the configuration and throws if appIdentifier, clientId, clientSecret or appJWK is missing. appJWK must be valid JSON — a JSON string is parsed automatically, anything that isn't an object is rejected with appJWK is not a valid JSON.
Inbound: verifying the appToken
Every request VARIO Cloud sends to your App carries an appToken — a JWT signed with ES256. The framework installs an authentication middleware on the App's API router, so all your /api/* routes are protected automatically.
Verification checks that:
the signature matches the public key in your
appJWK,the
audclaim equals yourappIdentifier,the token has not expired.
If any check fails, the request is answered with 401 and never reaches your route.
The token is normally read from the Authorization: Bearer <appToken> header. There is one exception: for GET requests to /api/install and /api/uninstall, it is read from the appToken query parameter — this exists so Apps without a UI can be installed.
Outbound: from offlineToken to accessToken
To call the VARIO Cloud API, your App needs an access token per tenant.
During installation, VARIO Cloud hands your App an offlineToken for that tenant — long-lived, but not unlimited (see Lifetime).
Your App stores it, keyed by tenant.
On the first API call, the framework exchanges the offlineToken for a short-lived accessToken at the tenant's identity server.
The accessToken is cached until shortly before it expires, then refreshed.
The framework also derives the tenant's API base URL from the offlineToken itself: the token's issuer (iss) points at the tenant's identity server, and stripping the sso. prefix yields the tenant host. Requests are then sent to https://<tenant-host>/api/vario.
→ See REST API Introduction for how base URLs are structured.
Bootstrap: the install call
The offlineToken arrives when VARIO Cloud installs your App in a tenant: it calls your install endpoint with the token in the request body:
A typical install service does three things in order:
Losing the offlineToken means losing API access for that tenant until it is renewed. Persist it durably before you run anything else, and delete it again on uninstall.
Lifetime: 45 days, sliding
An offlineToken is valid for 45 days — but the clock restarts on every use. Each time your App exchanges it for an access token, its validity is extended to a fresh 45 days.
In practice that means a regularly active App never sees the token expire. It only becomes invalid after 45 consecutive days without a single API call for that tenant.
This bites Apps that are idle for long stretches — a seasonal integration, a tenant in a test environment, an App that only acts when the customer triggers something.
If that describes your App, make sure it touches the API at least once inside the window (a small scheduled call is enough), or accept that the customer will have to renew the token before the App works again.
Renewal: the install call happens again
An offlineToken is not permanent — it expires if unused, and the customer can replace it deliberately. In the Admin-Center, on the installed App's page, the action "Offline-Token erneuern" issues a fresh token and then opens your App's installation page (pcInstallationUrl) again with the new token attached — which hands it to your install endpoint exactly as it does on a first install.
In other words: install is not a one-shot event. The same endpoint that bootstrapped the App is also the renewal channel.
Two consequences for your implementation:
Overwrite unconditionally. Store the incoming token even when you already have one — otherwise renewal silently keeps the dead token.
Keep install idempotent. It will run again on an already-provisioned tenant. Migration steps that already ran are skipped for you, but anything you do outside a migration step must tolerate repetition.
Where the offlineToken is stored
Out of the box, app.offlineToken keeps tokens in a local JSON file (offlineToken.db) — convenient for development, but not suitable for a multi-instance production deployment. You can pass your own storage implementation (get, set, delete per tenant) via the App options and keep tokens in your own database or secrets store.
Changing or deleting a stored offlineToken also drops the cached accessToken for that tenant.
Making API calls
Once installed, you don't manage tokens at all — you use the ERP client on the App:
The framework attaches, on every request:
Authorization
Bearer <accessToken>
user-agent
your appIdentifier
Accept / Content-Type
application/json
If the API answers 401, the cached accessToken for that tenant is discarded so the next call fetches a fresh one.
Without the framework
Nothing here is magic — the App model sits on plain OAuth 2.0. If you implement it yourself, you must:
Verify the inbound appToken (ES256,
aud=appIdentifier, not expired) against yourappJWK.Store the offlineToken you receive on install, per tenant.
Exchange it for an accessToken using the refresh token grant with your
clientIdandclientSecret.Send
Authorization: Bearer <accessToken>and aUser-Agenton every request.Cache access tokens and refresh them before they expire.
The grant types and endpoints are documented in REST API Authentication.
Last updated
Was this helpful?