Builds Authorization header values.
Two audiences, kept apart on purpose (sc-1469):
- Outbound calls to a provider -- another service protected by
EndPointBlank -- use
header/1orheader!/1. They only ever produce aBeareraccess token. When no token can be obtained they refuse, with{:error, reason}orEndPointBlank.TokenUnavailableError, and the call must not be made. They never fall back to this service's ownclient_id/client_secret: a provider is not EndPointBlank and must never be handed the credential. - Calls to this SDK's own intake -- authorize, token minting, endpoint
updates and the log/request/response/error writers -- use
intake_header/0. intake already holds this service's credential, so presenting it there reveals nothing. It refuses, and nothing is sent, whenclient_idorclient_secretis nil or empty.
There is deliberately no no-argument header/0. It used to answer Basic, and
so did header/1 whenever a mint failed, which handed the credential to
whichever provider was being called during every intake outage, timeout or
revoked credential.
Summary
Functions
Returns Base64-encoded client_id:client_secret. See basic_header/0.
Returns an HTTP Basic Authorization header value built from this service's
own client_id/client_secret, whether or not they are set.
Returns a Bearer Authorization header value for an outbound call to a
provider, or says why there is none.
Like header/1, but returns the Bearer header value itself and raises
when there is none
Returns {:ok, "Basic <credentials>"} for a call to this SDK's own intake,
or {:error, :missing_credentials} when client_id or client_secret is
nil or empty (sc-1469).
Like intake_header/0, but returns the header value itself and raises
EndPointBlank.ConfigurationError, naming what is missing, when
client_id or client_secret is nil or empty.
The credential settings that are nil or empty right now: some of
[:client_id, :client_secret], in that order, or [].
Types
@type reason() :: :missing_base_url | :invalid_base_url | :token_cache_unavailable | :invalid_token | :missing_credentials | {:unexpected, term()} | EndPointBlank.AccessTokens.failure()
Why no Bearer header could be produced for an outbound call.
:missing_base_url-- the URL passed was not a non-empty string, so there is nothing to mint a token for.:invalid_base_url-- the URL is not an absolutehttporhttpsURL with a host and, if one is written, a port from 1 to 65535 (seeEndPointBlank.OutboundUrl.strip/1). Refused locally: nothing is sent to intake.:token_cache_unavailable--EndPointBlank.AccessTokensdid not answer: it was not running, or a mint against a hung intake outlasted the call.:invalid_token-- the cache answered{:ok, _}with something that is not a non-empty token string.EndPointBlank.AccessTokensguarantees it does not, so this is a defensive refusal for a broken guarantee rather than an outcome to plan for; treat it as transient.:missing_credentials--client_idorclient_secretis not configured (nil or empty). Nothing is sent and retrying cannot help: configure both.header!/1raisesEndPointBlank.ConfigurationErrorfor it, notEndPointBlank.TokenUnavailableError.{:unexpected, reason}-- the mint raised, threw, or the HTTP client answered something that is not a transport failure: a bug or a bad setting, not intake being out of reach.reasonis what was raised,{kind, term}for a throw or exit, or the client's error term. The Ruby SDK'sTokenUnavailableError#unexpected?marks the same case.- Any
EndPointBlank.AccessTokens.failure/0-- the mint itself failed.:credential_rejected(intake answered 401) and{:request_rejected, status}are permanent;{:server_error, status}and{:transport_error, reason}(including a timeout) are transient.
Functions
Returns Base64-encoded client_id:client_secret. See basic_header/0.
Returns an HTTP Basic Authorization header value built from this service's
own client_id/client_secret, whether or not they are set.
Prefer intake_header/0, which refuses when either is nil or empty instead
of answering Basic Og==; the SDK itself no longer calls this. Only for
calls to this SDK's own intake. Never use it for a call to a provider: use
header/1, which refuses rather than sending the credential.
Returns a Bearer Authorization header value for an outbound call to a
provider, or says why there is none.
base_url is the URL you are about to call. Its userinfo, query and
fragment are removed before the token request (see
EndPointBlank.OutboundUrl.strip/1); they are never sent to intake, logged,
or kept on the error. A token is minted if no usable one covers it yet:
nothing else mints the first token, so asking for one here, rather than
first checking whether one exists, is what makes the Bearer path reachable.
Returns {:ok, "Bearer <token>"}, or {:error, reason} (see reason/0)
when no token could be obtained -- :missing_credentials when client_id
or client_secret is not configured, without a request. Never raises, and
never returns HTTP Basic: on an error, do not make the call.
TokenUnavailableError.message/2 turns a reason into a human-readable
explanation; header!/1 raises one.
Like header/1, but returns the Bearer header value itself and raises
when there is none:
EndPointBlank.ConfigurationErrorwhenclient_idorclient_secretis not configured (:missing_credentials); nothing is sent.EndPointBlank.TokenUnavailableErrorfor every other reason, including a missing or unparseable URL (the Ruby SDK raisesArgumentErrorfor those) and a mint that failed unexpectedly (its:unexpectedistrue). The exception's:base_urlis the stripped URL, never the one passed in.
Never returns HTTP Basic.
@spec intake_header() :: {:ok, String.t()} | {:error, :missing_credentials}
Returns {:ok, "Basic <credentials>"} for a call to this SDK's own intake,
or {:error, :missing_credentials} when client_id or client_secret is
nil or empty (sc-1469).
Only for calls to this SDK's own intake (the configured :base_url and
:log_base_url): the token request, authorize, the endpoint update and the
writers. intake already holds this service's credential, so presenting it
there discloses nothing. Never use it for a call to a provider: use
header/1, which refuses rather than sending the credential.
On an error, make no request. Building the header anyway would send
Basic Og== (base64 of ":"), which intake answers with a 401 that reads
as a revoked credential. The SDK's own callers log
EndPointBlank.ConfigurationError's message and return without sending.
@spec intake_header!() :: String.t()
Like intake_header/0, but returns the header value itself and raises
EndPointBlank.ConfigurationError, naming what is missing, when
client_id or client_secret is nil or empty.
@spec missing_credentials() :: [:client_id | :client_secret]
The credential settings that are nil or empty right now: some of
[:client_id, :client_secret], in that order, or [].