-
Notifications
You must be signed in to change notification settings - Fork 2
/
config.go
71 lines (65 loc) · 1.92 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package main
import (
"encoding/json"
"errors"
"fmt"
"net/url"
"os"
"strings"
"github.com/lstoll/oidc/core/staticclients"
)
type config struct {
Database string `json:"database"`
Issuer []issuerConfig `json:"issuers"`
}
type issuerConfig struct {
URL *url.URL `json:"-"`
RawURL string `json:"url"`
Clients []staticclients.Client `json:"clients"`
}
func loadConfig(file []byte, cfg *config) error {
dec := json.NewDecoder(strings.NewReader(os.Expand(string(file), getenvWithDefault)))
dec.DisallowUnknownFields()
if err := dec.Decode(cfg); err != nil {
return err
}
if cfg.Database == "" {
return errors.New("required field missing: database")
}
if len(cfg.Issuer) != 1 {
return errors.New("must configure exactly 1 issuer")
}
for i := range cfg.Issuer {
parsed, err := url.Parse(cfg.Issuer[i].RawURL)
if err != nil {
return fmt.Errorf("parse issuer url %d: %w", i, err)
}
cfg.Issuer[i].URL = parsed
var validErr error
for ii, c := range cfg.Issuer[i].Clients {
if c.ID == "" {
validErr = errors.Join(validErr, fmt.Errorf("issuer %s client %d must set clientID", parsed, ii))
}
if len(c.RedirectURLs) == 0 && !c.Public && !c.PermitLocalhostRedirect {
validErr = errors.Join(validErr, fmt.Errorf("issuer %s client %d requires a redirect URL when not public with localhost permitted", parsed, ii))
}
if len(c.Secrets) == 0 && !c.Public && c.RequiresPKCE != nil && !*c.RequiresPKCE {
validErr = errors.Join(validErr, fmt.Errorf("issuer %s client %d requires a client secret when PKCE not required", parsed, ii))
}
}
if validErr != nil {
return validErr
}
}
return nil
}
// getenvWithDefault maps FOO:-default to $FOO or default if $FOO is unset or
// null.
func getenvWithDefault(key string) string {
parts := strings.SplitN(key, ":-", 2)
val := os.Getenv(parts[0])
if val == "" && len(parts) == 2 {
val = parts[1]
}
return val
}