charbonnierg / caddy-nats

2 stars 0 forks source link

caddy-nats (EXPERIMENTAL)

Run nats-server as a caddy app with experimental oauth2 authentication.

Introduction

As of NATS v2.10.0, Auth Callout is an opt-in extension for delegating client authentication and authorization to an application-defined NATS service.

The reference for Auth Callout is in the ADR-26: NATS Authorization Callouts

As stated in the ADR, Authorization Callout aims to enable an external NATS service to generate NATS authorization and credentials by authenticating connection requests.

The documentation helps understanding the usecases:

The motivation for this extension is to support applications using an alternate identity and access management (IAM) backend as the source of truth for managing users/applications/machines credentials and permissions. This could be services that implement standard protocols such as LDAP, SAML, and OAuth, an ad-hoc database, or even a file on disk.

Since this feature is quite new, there isn't much documentation aside from the two links above (ADR-26 and NATS docs), but we can at least draw a few things:

Assuming that a project wants OAuth2 authenticated web users to connect to NATS using authorization callout, the following components are required:

The goal of this repository is to provide a single executable binary, which will act as:

It means that no additional software or components should be required in order to authenticate, authorize and allow users to connect to NATS.

Introduction to caddy

Caddy is ...

Introduction to oauth2-proxy

OAuth2 is not trivial to implement (even though lots of libraries exist to help developers integrate OAuth2 authorization into their applications). In order to avoid writing an OAuth2 middleware, I decided to reuse the existing project oauth2-proxy. This project is used by many companies or other open sources projects, has more than 300 contributors, and approximately 7600 stars on GitHub. Because this project is a server component, it cannot be integrated directly into an existing Go application. I had to make a fork to use oauth2-proxy in order to easily create a caddy module. This caddy module is an HTTP middleware which can be used before other caddy modules to authenticate and authorize an HTTP session.

Example usage

go build ./cmd/caddy
sudo setcap cap_net_bind_service=+ep ./caddy

Start the example:

./caddy run -c example.json
const nats = await import("https://cdn.jsdelivr.net/npm/nats.ws@1.18.0/esm/nats.js")

nc = await nats.connect(
    {"servers": "wss://localhost:10443", "user": "APP", "pass": document.cookie}
)

await nc.publish("test")
nats pub foo bar

An authorization error should be returned, because no username is provided.

nats server ls --username SYS --password "not used"

Note: password option is provided because NATS CLI does not send username if no password is provided. However, code using SDK from supported languages can send a connect request with username only.

The command should succeed, because the matcher for SYS username is configured to handle auth request with always_allow handler.

Caddyfile

No support for caddyfile at the moment.

JSON file

Checkout the file example.json to see how to configure an NATS server with TLS certificates managed by caddy and auth callout service running as caddy module.

Next steps