Contents

swift-microservices/swift-authentication-hummingbird

Binding who is calling on Hummingbird: a bearer token, proved and set on the request context.

The middleware

BearerAuthenticationMiddleware reads the Authorization header, proves the token with an Authenticator<String, Identity> from swift-authentication, and sets the identity in two places:

  • the request context's identity, which HummingbirdAuth's IsAuthenticatedMiddleware and

route handlers read;

  • the task's ServiceContext, as a Principal<Identity, String> under

PrincipalKey<Identity, String>, which everything downstream reads, including outgoing gRPC calls that present the same token onward through swift-authentication-grpc.

let router = Router(context: BasicAuthRequestContext<AppToken>.self)
router.add(middleware: BearerAuthenticationMiddleware(authenticator: JWTAuthenticator<AppToken>(keys: keys)))

router.group("/account")
    .add(middleware: IsAuthenticatedMiddleware())
    .get("/") { _, context in context.identity! }

A request with no token continues anonymously, which is what an open route needs: signing in mints the first token and has no caller yet. A token the authenticator declines continues unbound. A token it refuses is 401 Unauthorized, because absent and invalid are not the same thing. Requiring a caller is a route's decision, made with IsAuthenticatedMiddleware.

Requirements

Swift 6.3, macOS 15 or Linux. Hummingbird 2.26, HummingbirdAuth 2.3.

Development

swift test
swift-format lint --strict --recursive Sources Tests    # what the soundness check runs

Contributing

Pull requests are welcome. Keep a change focused, prove new behaviour with a test, and label the pull request with its semantic version impact.

License

MIT. See LICENSE.

Package Metadata

Repository: swift-microservices/swift-authentication-hummingbird

Default branch: main

README: README.md