Live video on the AT Protocol
1package statedb
2
3import (
4 "context"
5 "crypto/rand"
6 "encoding/json"
7 "fmt"
8
9 "github.com/lestrrat-go/jwx/v2/jwk"
10 "stream.place/streamplace/pkg/log"
11)
12
13// EnsureServiceAuthKey ensures a shared symmetric key exists in the config table
14// for intra-service JWT authentication. All nodes sharing the same database will
15// use the same key, enabling mutual authentication within a station.
16func (state *StatefulDB) EnsureServiceAuthKey(ctx context.Context) (jwk.Key, error) {
17 conf, err := state.GetConfig("service-auth-key")
18 if err != nil {
19 return nil, fmt.Errorf("failed to get service auth key: %w", err)
20 }
21
22 if conf != nil {
23 key, err := jwk.ParseKey(conf.Value)
24 if err != nil {
25 return nil, fmt.Errorf("failed to parse service auth key: %w", err)
26 }
27 return key, nil
28 }
29
30 log.Warn(ctx, "no service auth key found, generating new one")
31
32 secret := make([]byte, 32)
33 if _, err := rand.Read(secret); err != nil {
34 return nil, fmt.Errorf("failed to generate random bytes: %w", err)
35 }
36
37 key, err := jwk.FromRaw(secret)
38 if err != nil {
39 return nil, fmt.Errorf("failed to create symmetric key: %w", err)
40 }
41
42 b, err := json.Marshal(key)
43 if err != nil {
44 return nil, fmt.Errorf("failed to marshal service auth key: %w", err)
45 }
46
47 if err := state.PutConfig("service-auth-key", b); err != nil {
48 return nil, fmt.Errorf("failed to save service auth key: %w", err)
49 }
50
51 return key, nil
52}