-
-
Notifications
You must be signed in to change notification settings - Fork 20
/
caddyfile.go
112 lines (97 loc) · 2.98 KB
/
caddyfile.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package caddyjwt
import (
"fmt"
"strings"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig"
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
"github.com/caddyserver/caddy/v2/modules/caddyhttp/caddyauth"
)
func init() {
httpcaddyfile.RegisterHandlerDirective("jwtauth", parseCaddyfile)
}
// parseCaddyfile sets up the handler from Caddyfile. Syntax:
//
// jwtauth [<matcher>] {
// sign_key <sign_key>
// ...
// }
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
var ja JWTAuth
for h.Next() {
for h.NextBlock(0) {
opt := h.Val()
switch opt {
case "sign_key":
if !h.AllArgs(&ja.SignKey) {
return nil, h.Errf("invalid sign_key: %q", ja.SignKey)
}
case "sign_alg":
if !h.AllArgs(&ja.SignAlgorithm) {
return nil, h.Errf("invalid sign_alg: %q", ja.SignAlgorithm)
}
case "jwk_url":
if !h.AllArgs(&ja.JWKURL) {
return nil, h.Errf("invalid jwk_url: %q", ja.JWKURL)
}
case "skip_verification":
ja.SkipVerification = true
case "from_query":
ja.FromQuery = h.RemainingArgs()
case "from_header":
ja.FromHeader = h.RemainingArgs()
case "from_cookies":
ja.FromCookies = h.RemainingArgs()
case "audience_whitelist":
ja.AudienceWhitelist = h.RemainingArgs()
case "issuer_whitelist":
ja.IssuerWhitelist = h.RemainingArgs()
case "user_claims":
ja.UserClaims = h.RemainingArgs()
case "meta_claims":
ja.MetaClaims = make(map[string]string)
for _, metaClaim := range h.RemainingArgs() {
claim, placeholder, err := parseMetaClaim(metaClaim)
if err != nil {
return nil, h.Errf("invalid meta_claims: %w", err)
}
if _, ok := ja.MetaClaims[claim]; ok {
return nil, h.Errf("invalid meta_claims: duplicate claim: %s", claim)
}
ja.MetaClaims[claim] = placeholder
}
case "header_first":
return nil, h.Err("option header_first deprecated, the priority now defaults to from_query > from_header > from_cookies")
default:
return nil, h.Errf("unrecognized option: %s", opt)
}
}
}
return caddyauth.Authentication{
ProvidersRaw: caddy.ModuleMap{
"jwt": caddyconfig.JSON(ja, nil),
},
}, nil
}
// parseMetaClaim parses key to get the claim and corresponding placeholder.
// e.g "IsAdmin -> is_admin" as { Claim: "IsAdmin", Placeholder: "is_admin" }.
func parseMetaClaim(key string) (claim, placeholder string, err error) {
parts := strings.Split(key, "->")
if len(parts) == 1 {
claim = strings.TrimSpace(parts[0])
placeholder = strings.TrimSpace(parts[0])
} else if len(parts) == 2 {
claim = strings.TrimSpace(parts[0])
placeholder = strings.TrimSpace(parts[1])
} else {
return "", "", fmt.Errorf("too many delimiters (->) in key %q", key)
}
if claim == "" {
return "", "", fmt.Errorf("empty claim in key %q", key)
}
if placeholder == "" {
return "", "", fmt.Errorf("empty placeholder in key %q", key)
}
return
}