Skip to navigation

Authentication

Getting a token, using it, and what it grants you
View as Markdown

Every endpoint in this API requires an access token. Tokens come from UAC’s Keycloak using the OAuth 2.0 client credentials grant. It’s a machine-to-machine flow, so there’s no user to redirect and no browser involved.

1. Get a token

curl -X POST \
https://keycloak-dev.uac.edu.au:8443/realms/advance_reload/protocol/openid-connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=advance_inst_api_unsw" \
-d "client_secret=$CLIENT_SECRET"

The response:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6...",
"expires_in": 1800,
"token_type": "Bearer"
}

2. Use it

Send the access_token as a bearer token on every request:

curl https://unsw-v6-test.advance-uac.com/institution-api/institution/catalogue/subjects \
-H "Authorization: Bearer $ACCESS_TOKEN"

3. Reuse it until it expires

expires_in is the lifetime in seconds, currently 1800 (30 minutes).

You should NOT:

  • Request a new token for every API call as it hammers Keycloak during bulk loads.
  • Cache a token forever and ignore its expiry.

Instead, hold the token in memory, note when it expires, and fetch a new one shortly before it does.

Read expires_in rather than hardcoding 1800. The realm’s token lifetime can change without the API changing.

What the token carries

Your identity travels in the token itself, which has two practical consequences:

  • You never pass an institutionId in a request. There is no parameter for it.
  • Writes are attributed automatically, so audit fields such as a document’s uploadedBy are filled in for you.

Credentials

UAC issues your client_id and client_secret. You can’t create them yourself, so contact UAC if you don’t have them or a secret needs rotating.

The client secret has full access to your institution’s data, and anything holding it can act as your institution. Keep it server-side. It should never appear in a browser, a mobile app, a public repository or a CI log.

Use an environment variable or a secrets manager, not a literal in source. In the examples above, $CLIENT_SECRET is read from the environment for exactly this reason.

Environments

Each environment has its own API host. The Keycloak realm is shared between them, so the same credentials work against both, and a token minted for one will be accepted by the other. Be deliberate about which host you point at.

EnvironmentAPI base URLSwagger UI
Testhttps://unsw-v6-test.advance-uac.com/institution-apiopen
Devhttps://unsw-v6-dev.advance-uac.com/institution-apiopen

Each environment also serves its raw OpenAPI document at /q/openapi.json under the same base URL, if you’d rather generate a client than read pages.

When it goes wrong

SymptomLikely cause
401 on every callToken missing, malformed, or expired
401 immediately after a token requestThe Bearer prefix is missing, or the whole JSON body was sent instead of just access_token
invalid_client from KeycloakWrong client_id/client_secret, or the secret has been rotated
404 on a record you believe existsThe code and year don’t match a record, or it hasn’t been created yet

For the endpoint reference, see Get access token.