EndPointBlank.TokenUnavailableError exception (end_point_blank_elixir v0.9.0)

Copy Markdown View Source

Raised by EndPointBlank.Authorization.header!/1 when no access token could be obtained for an outbound call to a provider (sc-1469).

Until sc-1469 the SDK fell back to HTTP Basic client_id:client_secret here, which handed this service's own credential to whichever provider it was calling -- during every intake outage, timeout or revoked credential. It now refuses instead. Do not rescue this and send Basic yourself: the provider is not EndPointBlank and must never see the credential.

Fields:

  • :base_url -- the URL a token was requested for, stripped to scheme, host, port and path by EndPointBlank.OutboundUrl.strip/1, or nil when there was no URL or OutboundUrl.strip/1 refused it. Userinfo, query and fragment can carry a secret, and error reporters capture an exception's fields as well as its message, so they are not kept anywhere on the exception; the caller already has the URL it passed.
  • :reason -- a EndPointBlank.Authorization.reason/0, kept exactly as it was returned. Branch on it to decide whether to retry: {:transport_error, _}, {:server_error, _}, :invalid_token and :token_cache_unavailable may clear on their own; :credential_rejected, {:request_rejected, _}, :missing_base_url, :invalid_base_url and :missing_credentials will not. A mint that raised, threw, or got a non-transport error back from the HTTP client is {:unexpected, _} carrying what was raised ({kind, term} for a throw or exit). EndPointBlank.Authorization.header!/1 raises EndPointBlank.ConfigurationError, not this, for :missing_credentials.
  • :unexpected -- true when the mint failed unexpectedly rather than intake reporting a failure: {:unexpected, _}, or a {:transport_error, _} whose term is not a transport failure. The Ruby SDK's TokenUnavailableError#unexpected?. false otherwise.
  • :status -- the HTTP status intake answered the token request with, when there was one: 401 for :credential_rejected, the status carried by {:request_rejected, status} or {:server_error, status}, and nil for every other reason (no response, or no status to report).
  • :message -- says what failed, why, and that credentials are never sent to providers.

The message is built from fixed phrases only, the same ones every EndPointBlank SDK uses. It never inspects the reason and never repeats intake's response body, an exception's message or its module name: a transport error can carry request data, and this message is the kind of thing that ends up in a log line. The full term is still on :reason for a caller that needs it.

Summary

Functions

The explanation carried by an exception for base_url and reason, for a caller that used the non-raising EndPointBlank.Authorization.header/1 and wants the same wording in its own log line or error.

The HTTP status intake answered the token request with for reason, or nil when there was none. The same value an exception carries as :status.

Whether reason means the mint failed unexpectedly -- it raised, threw, or the HTTP client answered something that is not a transport failure -- rather than intake reporting why. The same value an exception carries as :unexpected.

Functions

message(base_url, reason)

@spec message(term(), term()) :: String.t()

The explanation carried by an exception for base_url and reason, for a caller that used the non-raising EndPointBlank.Authorization.header/1 and wants the same wording in its own log line or error.

status(arg1)

@spec status(term()) :: pos_integer() | nil

The HTTP status intake answered the token request with for reason, or nil when there was none. The same value an exception carries as :status.

unexpected?(arg1)

@spec unexpected?(term()) :: boolean()

Whether reason means the mint failed unexpectedly -- it raised, threw, or the HTTP client answered something that is not a transport failure -- rather than intake reporting why. The same value an exception carries as :unexpected.