Authentication
Client-side authentication is a pure encoding concern: take some
credentials, write the right header / query parameter on the outbound
request. It is decoupled from the server-side Authenticator /
Authorizer interfaces (core / interfaces)
— those answer “is this request allowed?”, these answer “how do I
sign it?”.
The interface — ClientAuthInfoWriter
See runtime.ClientAuthInfoWriter
for the authoritative definition. Anything with that signature can be
used as auth. The ClientRequest argument exposes SetHeaderParam,
SetQueryParam, SetBodyParam — i.e. the same surface generated
parameter types use to encode themselves.
Where to attach it
Two places, with predictable precedence:
// 1. Per operation — overrides the runtime default
op.AuthInfo = client.BearerToken(token)
// 2. Per runtime — used when the operation does not set its own
rt.DefaultAuthentication = client.BasicAuth("alice", "s3cret")Full source: docs/examples/client/auth/main.go
The runtime calls the operation’s AuthInfo if set, otherwise the
runtime’s DefaultAuthentication. Either may be nil for unauthenticated
endpoints.
Built-in helpers
All four return a ready-to-use ClientAuthInfoWriter.
BasicAuth(user, password) — RFC 7617
rt.DefaultAuthentication = client.BasicAuth("alice", "s3cret")Full source: docs/examples/client/auth/main.go
Sets Authorization: Basic <base64(user:password)>.
APIKeyAuth(name, in, value) — RFC-undefined but ubiquitous
// As an HTTP header
rt.DefaultAuthentication = client.APIKeyAuth("X-Api-Key", "header", apiKey)
// Or as a query parameter
rt.DefaultAuthentication = client.APIKeyAuth("api_key", "query", apiKey)Full source: docs/examples/client/auth/main.go
in must be "header" or "query". Anything else returns nil — at
which point you’ll silently send the request unauthenticated, so check
your spelling.
BearerToken(token) — RFC 6750 OAuth2 access tokens
rt.DefaultAuthentication = client.BearerToken(accessToken)Full source: docs/examples/client/auth/main.go
Sets Authorization: Bearer <token>. For OAuth2 client flows that
need to acquire and refresh the token, build the writer around an
oauth2.TokenSource from golang.org/x/oauth2 and re-attach it on
every call (or use a custom writer that calls Token()).
Compose(auths…) — combine multiple writers
For APIs that require more than one credential header on the same request — say an API key plus a bearer token — chain them:
rt.DefaultAuthentication = client.Compose(
client.APIKeyAuth("X-Api-Key", "header", apiKey),
client.BearerToken(accessToken),
)Full source: docs/examples/client/auth/main.go
Nil writers in the list are skipped silently. The first non-nil writer that returns an error short-circuits the chain.
PassThroughAuth — explicit “no auth”
A no-op writer. Use it when the operation requires some writer
(for instance because it’s defined as security: [[]] in the spec)
but no actual credential should be attached.
op.AuthInfo = client.PassThroughAuthFull source: docs/examples/client/auth/main.go
Writing your own
A common case: an HMAC-signed request that needs to compute the
signature over the body. Implement ClientAuthInfoWriter directly:
// HMACSignature returns a ClientAuthInfoWriter that signs the request
// body with the given HMAC-SHA256 key and attaches the signature plus
// key ID as headers.
func HMACSignature(keyID string, key []byte) runtime.ClientAuthInfoWriter {
return runtime.ClientAuthInfoWriterFunc(func(r runtime.ClientRequest, _ strfmt.Registry) error {
body := r.GetBody()
mac := hmac.New(sha256.New, key)
mac.Write(body)
sig := hex.EncodeToString(mac.Sum(nil))
if err := r.SetHeaderParam("X-Sig-Key", keyID); err != nil {
return err
}
return r.SetHeaderParam("X-Sig", sig)
})
}Full source: docs/examples/client/auth/main.go
The runtime calls AuthenticateRequest after the operation’s
parameters have been bound but before the request is sent — so
r.GetBody() returns the encoded body for buffered payloads. For
streaming bodies (multipart, raw streams) the runtime arranges a
body-copy closure so the signer sees the bytes that will go on the
wire; see BuildHTTPContext in
client/internal/request
for the gory details.