|
| 1 | +# OAuth 2.0 client-credentials token cache with auto-refresh |
| 2 | + |
| 3 | +## What this solves |
| 4 | +When integrating with external APIs, teams often re-implement the OAuth 2.0 client-credentials flow and forget to cache tokens or handle 401 refreshes. This helper: |
| 5 | +- Requests an access token from your token endpoint |
| 6 | +- Caches the token in a system property with an expiry timestamp |
| 7 | +- Adds the Bearer token to RESTMessageV2 requests |
| 8 | +- If the call returns 401 (expired token), refreshes once and retries |
| 9 | + |
| 10 | +## Where to use |
| 11 | +Script Include in global or scoped apps. Call from Business Rules, Scheduled Jobs, Flow Actions, or Background Scripts. |
| 12 | + |
| 13 | +## How it works |
| 14 | +- `getToken(options)` fetches or retrieves a cached token; stores `access_token` and `expires_at` (epoch ms) in system properties. |
| 15 | +- `request(options)` executes a resource call with Authorization header; on HTTP 401 it refreshes the token and retries once. |
| 16 | +- Token expiry has a 60-second buffer to avoid race on near-expiry tokens. |
| 17 | + |
| 18 | +## Security notes |
| 19 | +- For production, store `client_secret` in a secure location (Credentials table or encrypted system property) and **do not** hardcode secrets in scripts. |
| 20 | +- This snippet reads/writes system properties under a chosen prefix. Ensure only admins can read/write them. |
| 21 | + |
| 22 | +## Options |
| 23 | +For `getToken` and `request`: |
| 24 | +- `tokenUrl`: OAuth token endpoint URL |
| 25 | +- `clientId`: OAuth client id |
| 26 | +- `clientSecret`: OAuth client secret |
| 27 | +- `scope`: optional scope string |
| 28 | +- `audience`: optional audience parameter (some providers require it) |
| 29 | +- `propPrefix`: system property prefix for cache (e.g. `x_acme.oauth.sample`) |
| 30 | +- `resource` (request only): target API URL |
| 31 | +- `method` (request only): GET/POST/etc (default GET) |
| 32 | +- `headers` (request only): object of extra headers |
| 33 | +- `body` (request only): request body for POST/PUT/PATCH |
| 34 | + |
| 35 | +## References |
| 36 | +- RESTMessageV2 API |
| 37 | + https://www.servicenow.com/docs/bundle/zurich-api-reference/page/app-store/dev_portal/API_reference/RESTMessageV2/concept/c_RESTMessageV2API.html |
| 38 | +- Direct RESTMessageV2 example |
| 39 | + https://www.servicenow.com/docs/bundle/zurich-api-reference/page/app-store/dev_portal/API_reference/RESTMessageV2/reference/r_DirectRESTMessageV2Example.html |
| 40 | +- OAuth 2.0 profiles in ServiceNow (concept) |
| 41 | + https://www.servicenow.com/docs/bundle/zurich-integrate-applications/page/integrate/outbound-rest/concept/c_oauth2-authentication.html |
0 commit comments