Acquire an outbound access token¶
Returns a cached OAuth client-credentials access token, refreshing it from the configured token endpoint when it is missing or near expiry.
| Field | Value |
|---|---|
| Operation ID | OP-13 |
| Trigger | Consumer code calls IAccessTokenClient.GetToken() before calling a downstream API. |
| Inputs | TokenUrl, ClientId, ClientSecret, GrantType, Scopes (all code-set properties), and the current HttpContext only on the refresh path. |
| Outputs | An OAuth access token string, returned from cache or from a fresh refresh; there is no post-refresh validity check before returning or caching it**. |
| Primary components | OktaTokenClient.GetToken() |
| Entry point | src/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/Clients/OktaTokenClient.cs |
Steps¶
- If the cached token is missing or not
IsValidAndNotExpiring(empty token, or expiring within 30 seconds), callGetNewAccessToken()(BR-AUTH-017) GetNewAccessToken: create a newHttpClient; setAuthorization: Basic base64(ClientId:ClientSecret); POST a form body ofgrant_type,scope, andredirect_uri = {Request.Scheme}://{Request.Host}toTokenUrl(BR-AUTH-018)response.EnsureSuccessStatusCode(), which throws on a non-2xx response; deserialize with Newtonsoft and setExpiresAt = UtcNow + ExpiresInseconds.- Return
AccessToken.
Process flow¶
The following diagram visualizes this operation's control flow.
flowchart TD
Start([GetToken called]) --> Valid{Cached token valid and not expiring?}
Valid -->|Yes| Return([Return cached AccessToken])
Valid -->|No| New[GetNewAccessToken]
New --> Post["POST TokenUrl with Basic auth + form body"]
Post --> Success{2xx response?}
Success -->|Yes| Cache["Deserialize, cache token, set ExpiresAt"]
Success -->|No| Throw([EnsureSuccessStatusCode throws])
Cache --> Return
Failure and edge-case behavior¶
- A non-2xx response from the token endpoint throws from
EnsureSuccessStatusCode(). HttpContextis only read when buildingredirect_urion the refresh path (step 2); a cache hit (step 1) returns without touchingHttpContextat all. Calling this outside a request only throwsNullReferenceExceptionwhen a refresh is actually needed*.- After a successful refresh, the deserialized token value is cached and returned without any additional validity check — the response is trusted as-is once
EnsureSuccessStatusCode()passes.
Related documentation¶
Note: Statements marked with
*were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with**could not be confirmed; treat as unknown until verified.
Sources¶
src/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/SAIF.NetCore.AuthService/Clients/OktaTokenClient.cs