Skip to content

Commit ad7086c

Browse files
einrobinkixelated
andauthored
JWK sets (#809)
Co-authored-by: Luke Curley <kixelated@gmail.com>
1 parent d61d1da commit ad7086c

File tree

8 files changed

+844
-89
lines changed

8 files changed

+844
-89
lines changed

Cargo.lock

Lines changed: 66 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/guide/authentication.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
title: moq-authentication
3+
description: Authentication for the moq-relay
4+
---
5+
6+
# MoQ authentication
7+
8+
The MoQ Relay authenticates via JWT-based tokens. Generally there are two different approaches you can choose from:
9+
- asymmetric keys: using a public and private key to separate signing and verifying keys for more security
10+
- symmetric key: using a single secret key for signing and verifying, less secure
11+
12+
## Symmetric key
13+
14+
1. Generate a secret key:
15+
```bash
16+
moq-token --key root.jwk generate --algorithm HS256
17+
```
18+
:::details You can also choose a different algorithm
19+
- HS256
20+
- HS384
21+
- HS512
22+
:::
23+
24+
2. Configure relay:
25+
:::code-group
26+
```toml [relay.toml]
27+
[auth]
28+
# public = "anon" # Optional: allow anonymous access to anon/**
29+
key = "root.jwk" # JWT key for authenticated paths
30+
```
31+
:::
32+
33+
3. Generate tokens:
34+
```bash
35+
moq-token --key root.jwk sign \
36+
--root "rooms/123" \
37+
--publish "alice" \
38+
--subscribe "" \
39+
--expires 1735689600 > alice.jwt
40+
```
41+
42+
## Asymmetric keys
43+
44+
Generally asymmetric keys can be more secure because you don't need to distribute the signing key to every relay instance, the relays only need to verifying (public) key.
45+
46+
1. Generate a public and private key:
47+
```bash
48+
moq-token --key private.jwk generate --public public.jwk --algorithm RS256
49+
```
50+
:::details You can also choose a different algorithm
51+
- RS256
52+
- RS384
53+
- RS512
54+
- PS256
55+
- PS384
56+
- PS512
57+
- EC256
58+
- EC384
59+
- EdDSA
60+
:::
61+
62+
2. Now the relay only requires the public key:
63+
:::code-group
64+
```toml [relay.toml]
65+
[auth]
66+
# public = "anon" # Optional: allow anonymous access to anon/**
67+
key = "public.jwk" # JWT key for authenticated paths
68+
```
69+
:::
70+
71+
3. Generate tokens using the private key:
72+
```bash
73+
moq-token --key private.jwk sign \
74+
--root "rooms/123" \
75+
--publish "alice" \
76+
--subscribe "" \
77+
--expires 1735689600 > alice.jwt
78+
```
79+
80+
## JWK set authentication
81+
82+
Instead of storing a public key locally in a file, it may also be retrieved from a server hosting a JWK set. This can be a simple static site serving a JSON file, or a fully OIDC compliant Identity Provider. That way you can easily implement automatic key rotation.
83+
84+
::: info
85+
This approach only works with asymmetric authentication.
86+
:::
87+
88+
To set this up, you need to have an HTTPS server hosting a JWK set that looks like this:
89+
```json
90+
{
91+
"keys": [
92+
{
93+
"kid": "2026-01-01",
94+
"alg": "RS256",
95+
"key_ops": [
96+
"verify"
97+
],
98+
"kty": "RSA",
99+
"n": "zMsjX1oDV2SMQKZFTx4_qCaD3iIek9s1lvVaymr8bEGzO4pe6syCwBwLmFwaixRv7MMsuZ0nIpoR3Slpo-ZVyRxOc8yc3DcBZx49S_UQcM76E4MYbH6oInrEP8QL2bsstHrYTqTyPPjGwQJVp_sZdkjKlF5N-v5ohpn36sI8PXELvfRY3O3bad-RmSZ8ZOG8CYnJvMj_g2lYtGMMThnddnJ49560ahUNqAbH6ru---sHtdYHcjTIaWX4HYP6Y_KjA6siDZTGTThpaEW45LKcDQWM9sYvx_eAstaC-1rz8Z_6fDgKFWr7qcP5U2NmJ0c-IGSu_8OkftgRH4--Z5mzBQ",
100+
"e": "AQAB"
101+
},
102+
{
103+
"kid": "2025-12-01",
104+
"alg": "EdDSA",
105+
"key_ops": [
106+
"verify"
107+
],
108+
"kty": "OKP",
109+
"crv": "Ed25519",
110+
"x": "2FSK2q_o_d5ernBmNQLNMFxiA4-ypBSa4LsN30ZjUeU"
111+
}
112+
]
113+
}
114+
```
115+
116+
:::tip The following must be considered:
117+
- Every JWK MUST be public and contain no private key information
118+
- If your JWK set contains more than one key:
119+
1. Every JWK MUST have a `kid` so they can be identified on verification
120+
2. Your JWT tokens MUST contain a `kid` in their header
121+
3. `kid` can be an arbitrary string
122+
:::
123+
124+
Configure the relay:
125+
:::code-group
126+
```toml [relay.toml]
127+
[auth]
128+
# public = "anon" # Optional: allow anonymous access to anon/**
129+
130+
key = "https://auth.example.com/keys.json" # JWK set URL for authenticated paths
131+
refresh_interval = 86400 # Optional: refresh the JWK set every N seconds, no refreshing if omitted
132+
```
133+
:::

rs/moq-relay/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ futures = "0.3"
3030
http-body = "1"
3131
moq-lite = { workspace = true, features = ["serde"] }
3232
moq-native = { workspace = true, features = ["aws-lc-rs"] }
33-
moq-token = { workspace = true }
33+
moq-token = { workspace = true, features = ["jwks-loader"] }
3434
rustls = { version = "0.23", features = [
3535
"aws-lc-rs",
3636
], default-features = false }

0 commit comments

Comments
 (0)