Service Access Tokens (SAT)
Every service instance in Eyevinn Open Source Cloud is protected by an ingress gate. The gate accepts a Service Access Token (SAT) that is scoped to the specific service. This page explains what SATs are, how to obtain one, and how to use them from scripts and applications.
How the Gate Works
The OSC ingress gate validates a SAT on every inbound request to a service instance. You can supply the SAT in two ways:
| Method | Format |
|---|---|
| HTTP header | Authorization: Bearer <sat> |
| Cookie | <serviceId>.sat=<sat> |
Validation is stateless: the gate performs a local HS256 HMAC check against a per-service shared secret and verifies the expiry claim. There is no per-request callback to the OSC platform on the hot path, so validation adds minimal latency and works even if the OSC control plane is momentarily unreachable.
There is no JWKS endpoint or .well-known/openid-configuration for SATs. They use HS256 with a secret provisioned automatically per service. Do not attempt out-of-band JWT verification; use the token as an opaque bearer credential.
SATs expire after 1 hour. Headless clients must re-exchange a PAT for a fresh SAT periodically (for example, every 50 minutes or lazily on receiving a 401 response).
Getting a PAT First
To obtain a SAT you first need an OSC Access Token, commonly called a Personal Access Token (PAT). There are two ways to get one depending on your client type.
Interactive applications (OAuth)
Browser-based apps should use the OAuth 2.0 authorization-code flow. This gives the user a 1-hour access token and a 30-day refresh token. See Act on Behalf of a User (OAuth) for the full flow.
Server-to-server / headless clients
Generate a long-lived PAT from the OSC console:
- Sign in to app.osaas.io.
- Go to Settings in the left sidebar.
- Click the { } API tab.
- Copy the personal access token.
Store the PAT in an environment variable or secret store. Never commit it to source control.
export OSC_ACCESS_TOKEN=<your-pat>
Exchanging a PAT for a SAT
Using the CLI
npx @osaas/cli service-access-token <service-id>
Example:
npx @osaas/cli service-access-token eyevinn-test-adserver
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXV...
The returned token is valid for 1 hour.
Using the TypeScript SDK
import { Context } from "@osaas/client-core";
const ctx = new Context(); // reads OSC_ACCESS_TOKEN from env
const sat = await ctx.getServiceAccessToken("eyevinn-test-adserver");
The Context object handles the exchange internally and the returned sat string is ready to use as a bearer token.
Using the HTTP API directly
POST https://token.svc.prod.osaas.io/servicetoken
x-pat-jwt: Bearer <pat>
Content-Type: application/json
{ "serviceId": "<instance-id>" }
Example with curl:
curl -s -X POST https://token.svc.prod.osaas.io/servicetoken \
-H "x-pat-jwt: Bearer $OSC_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"serviceId":"eyevinn-test-adserver"}'
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXV..."
}
Calling a Service Instance
Pass the SAT as a bearer token in the Authorization header:
curl -H "Authorization: Bearer <sat>" \
https://<tenant>-<instance>.eyevinn-test-adserver.auto.prod.osaas.io/api/v1/ads
Alternatively, set the <serviceId>.sat cookie for browser-based requests. This is handled automatically by the web console.
Refreshing SATs in Long-Running Processes
SATs expire after 1 hour. For server-side processes that run longer than that, re-exchange your PAT for a fresh SAT before the current one expires. A practical strategy is to refresh every 50 minutes or to catch any 401 response and retry once with a fresh token:
import { Context } from "@osaas/client-core";
let sat: string | undefined;
let satExpiresAt = 0;
async function getSat(serviceId: string): Promise<string> {
const now = Date.now();
if (!sat || now >= satExpiresAt) {
const ctx = new Context();
sat = await ctx.getServiceAccessToken(serviceId);
satExpiresAt = now + 50 * 60 * 1000; // refresh after 50 min
}
return sat;
}
Summary
| Step | What to do |
|---|---|
| 1. Get a PAT | OAuth flow (interactive) or Settings / API in the console (headless) |
| 2. Exchange for SAT | CLI, TypeScript SDK, or POST /servicetoken |
| 3. Call the service | Authorization: Bearer <sat> header |
| 4. Refresh | Re-exchange PAT every ~50 min or on 401 |