JWT

Cloud Agnostic
Open Source

Validates JSON Web Tokens against a JWKS endpoint. The recommended auth plugin for production deployments. The plugin extracts the user ID from the sub claim by default, configurable via NameClaimType.

Source code: Notiway.Plugins.Portable.Auth.JWT

Compatibility

Compatible withAll Buffer, Broker, Storage, and Host plugins
ProductNotiway Notify

Installation

Environment Variables

Required

VariableDescription
Infra__Plugins__Auth__NameSet to JWT
Infra__Plugins__Auth__VersionPlugin version (e.g., 0.9.0)
Infra__Plugins__Auth__Settings__IssuerExpected token issuer (e.g., https://auth.example.com)
Infra__Plugins__Auth__Settings__AudienceExpected token audience (e.g., notiway-notify)
Infra__Plugins__Auth__Settings__JwksUriURL of the JWKS endpoint for key discovery (e.g., https://auth.example.com/.well-known/jwks.json)

Optional

VariableDefaultDescription
Infra__Plugins__Auth__Settings__ValidateIssuertrueValidate the token issuer
Infra__Plugins__Auth__Settings__ValidateAudiencetrueValidate the token audience
Infra__Plugins__Auth__Settings__ValidateLifetimetrueValidate the token expiration
Infra__Plugins__Auth__Settings__ValidateIssuerSigningKeytrueValidate the signing key
Infra__Plugins__Auth__Settings__ClockSkewSeconds30Allowed clock skew in seconds for token expiration
Infra__Plugins__Auth__Settings__NameClaimTypesubJWT claim used as the user ID for routing notifications

Infrastructure

  1. JWKS endpoint must be accessible from the Notiway instance at the configured URL.
  2. Tokens must contain a user ID claim — by default this is the sub claim, configurable via NameClaimType.

Docker Compose

docker-compose.yml
services:
  notiway:
    image: notiway/notify:portable-0.5.0
    ports:
      - "5000:8080"
    environment:
      - Infra__Plugins__Auth__Name=JWT
      - Infra__Plugins__Auth__Version=0.9.0
      - Infra__Plugins__Auth__Settings__Issuer=https://auth.example.com
      - Infra__Plugins__Auth__Settings__Audience=notiway-notify
      - Infra__Plugins__Auth__Settings__JwksUri=https://auth.example.com/.well-known/jwks.json

Usage

SignalR clients pass the JWT via the accessTokenFactory. The factory is called on every connection attempt, including automatic reconnects, so returning a fresh token each time avoids expired credentials.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("https://your-gateway/notifications", {
        accessTokenFactory: () => getAccessToken()
    })
    .withAutomaticReconnect()
    .build();
var connection = new HubConnectionBuilder()
    .WithUrl("https://your-gateway/notifications", options =>
    {
        options.AccessTokenProvider = () => Task.FromResult(GetAccessToken());
    })
    .WithAutomaticReconnect()
    .Build();
final connection = HubConnectionBuilder()
    .withUrl(
        "https://your-gateway/notifications",
        options: HttpConnectionOptions(
            accessTokenFactory: () async => getAccessToken(),
        ),
    )
    .withAutomaticReconnect()
    .build();
let connection = HubConnectionBuilder()
    .withUrl(url: "https://your-gateway/notifications",
             options: HttpConnectionOptions(
                accessTokenFactory: { getAccessToken() }
             ))
    .withAutoReconnect()
    .build()
val connection = HubConnectionBuilder.create("https://your-gateway/notifications")
    .withAccessTokenProvider { getAccessToken() }
    .withAutoReconnect()
    .build()