📖 2 min read (~ 400 words).

Basic & API-key auth

This is the starting point for security in a generated server. A securityDefinition in the spec becomes a generated authenticator hook you implement, and — when you generate with a typed principal — every protected handler receives that principal as a typed argument.

Tip

Source: authentication/. Generated with swagger generate server --name AuthSample --spec ./swagger.yml --principal models.Principal.

Declaring the scheme

The authentication example uses a single API-key scheme, carried in the x-token header, and applies it to every endpoint via a top-level security requirement:

securityDefinitions:
  key:
    type: apiKey
    in: header
    name: x-token
security:
  - key: []

Full source: authentication/swagger.yml

The generated authenticator hook

Because the spec names one apiKey scheme called key, the generated API exposes an api.KeyAuth hook. The --principal models.Principal flag makes it return a typed *models.Principal; the scaffold leaves it returning NotImplemented:

if api.KeyAuth == nil {
	api.KeyAuth = func(token string) (*models.Principal, error) {
		_ = token

		return nil, errors.NotImplemented("api key auth (key) x-token from header param [x-token] has not yet been implemented")
	}
}

Full source: authentication/restapi/configure_auth_sample.go

You replace the body with your token check. On success return a principal; on failure return an errors.New(401, …):

api.KeyAuth = func(token string) (*models.Principal, error) {
    if token == "abcdefuvwxyz" {
        prin := models.Principal(token)
        return &prin, nil
    }
    return nil, errors.New(401, "incorrect api key auth")
}

The returned principal is then passed to every handler protected by this scheme:

api.CustomersGetIDHandler = customers.GetIDHandlerFunc(
    func(params customers.GetIDParams, principal *models.Principal) middleware.Responder {
        // principal is the value your KeyAuth hook returned
        ...
    })

Basic auth is the same shape

A type: basic scheme works identically, except the runtime decodes the Authorization: Basic header for you and the hook receives a username/password pair instead of a single token:

api.MyBasicAuth = func(user, pass string) (*models.Principal, error) { ... }

For a worked basic-auth authenticator — plus mixing several schemes — see Composed auth.

Trying it

$ curl -i -H 'X-Token: abcdefuvwxyz' http://127.0.0.1:35307/api/customers
HTTP/1.1 501 Not Implemented          # authenticated, handler not implemented

$ curl -i -H 'X-Token: wrong' http://127.0.0.1:35307/api/customers
HTTP/1.1 401 Unauthorized
{"code":401,"message":"incorrect api key auth"}