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
| Answer | Means |
|---|---|
401 | No token, or an expired or unknown one: get a new token |
403 | The 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.