Download now
Preview: proposed, may change
What this page describes is not live yet. Build against it together with your YOU(th) contact, who tells you when it is.

Authentication

Get a short-lived token with OAuth2 client credentials, and call the API with it.

Your backend calls the API with a short-lived access token. It gets the token with the standard OAuth2 client-credentials grant: your client id and secret in, a token out. No person or browser is involved, and any OAuth2 library that supports the grant does it for you.

Get a token

curl https://auth.example.com/oauth2/token \  --data grant_type=client_credentials \  --data client_id="$YOUTH_CLIENT_ID" \  --data client_secret="$YOUTH_CLIENT_SECRET"

The answer holds the token and how many seconds it lasts:

{ "access_token": "eyJhbGciOiJSUzI1NiIs…", "expires_in": 300, "token_type": "Bearer" }

Call the API with it

Send the token in the Authorization header of every request:

curl https://api.example.com/v1/checkups \  --header "Authorization: Bearer $YOUTH_ACCESS_TOKEN"

A token lasts five minutes. Reuse it until shortly before it expires, then get a new one; do not get a token for every request.

In TypeScript

const TOKEN_URL = "https://auth.example.com/oauth2/token";let cached: { token: string; expiresAt: number } | undefined;/** A token for the API, reused until a minute before it expires. */export async function accessToken(now = Date.now()): Promise<string> {  if (cached && now < cached.expiresAt) return cached.token;  const response = await fetch(TOKEN_URL, {    method: "POST",    headers: { "Content-Type": "application/x-www-form-urlencoded" },    body: new URLSearchParams({      grant_type: "client_credentials",      client_id: process.env.YOUTH_CLIENT_ID ?? "",      client_secret: process.env.YOUTH_CLIENT_SECRET ?? "",    }),  });  if (!response.ok) throw new Error(`The token was refused: ${response.status}`);  const answer: { access_token: string; expires_in: number } = await response.json();  cached = { token: answer.access_token, expiresAt: now + (answer.expires_in - 60) * 1000 };  return cached.token;}

In Python

With requests-oauthlib:

import osfrom oauthlib.oauth2 import BackendApplicationClientfrom requests_oauthlib import OAuth2SessionTOKEN_URL = "https://auth.example.com/oauth2/token"client_id = os.environ["YOUTH_CLIENT_ID"]session = OAuth2Session(client=BackendApplicationClient(client_id=client_id))session.fetch_token(    token_url=TOKEN_URL,    client_id=client_id,    client_secret=os.environ["YOUTH_CLIENT_SECRET"],)response = session.get("https://api.example.com/v1/checkups")response.raise_for_status()

When the token has expired, the session raises TokenExpiredError: fetch a new token and try again.

When a token is refused

AnswerMeans
401No token, or an expired or unknown one: get a new token
403The token is valid, but this route is not open to your client

A token names your organization, and the API answers only its data: see Your organization.

Keep the secret safe

  • Keep the client secret on your server, never in an app or a browser.
  • Ask your YOU(th) contact for a new secret when one may have leaked. A token already issued keeps working until it expires, at most five minutes.

Not decided yet: the hosts of the API and of the token endpoint, which the examples show as api.example.com and auth.example.com, and a partner portal where your administrators would create and revoke credentials themselves. Until then, YOU(th) issues them.