-
Notifications
You must be signed in to change notification settings - Fork 4
/
verifier.go
83 lines (67 loc) · 1.81 KB
/
verifier.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
package oidc
import (
"context"
"fmt"
"time"
"github.com/go-jose/go-jose/v3/jwt"
"github.com/pardot/oidc/discovery"
)
type Verifier struct {
md *discovery.ProviderMetadata
ks KeySource
}
func DiscoverVerifier(ctx context.Context, issuer string) (*Verifier, error) {
cl, err := discovery.NewClient(ctx, issuer)
if err != nil {
return nil, fmt.Errorf("creating discovery client: %v", err)
}
return &Verifier{
md: cl.Metadata(),
ks: cl,
}, nil
}
func NewVerifier(issuer string, keySource KeySource) *Verifier {
return &Verifier{
md: &discovery.ProviderMetadata{
Issuer: issuer,
},
ks: keySource,
}
}
type verifyCfg struct{}
type VerifyOpt func(v *verifyCfg)
func (v *Verifier) VerifyRaw(ctx context.Context, audience string, raw string, opts ...VerifyOpt) (*Claims, error) {
tok, err := jwt.ParseSigned(raw)
if err != nil {
return nil, fmt.Errorf("failed parsing raw: %v", err)
}
if len(tok.Headers) != 1 {
return nil, fmt.Errorf("header must contain 1 header, found %d", len(tok.Headers))
}
kid := tok.Headers[0].KeyID
if kid == "" {
return nil, fmt.Errorf("token missing kid header")
}
key, err := v.ks.GetKey(ctx, kid)
if err != nil {
return nil, fmt.Errorf("fetching key %s: %v", kid, err)
}
// parse it into the library claims so we can use their verification code
cl := jwt.Claims{}
if err := tok.Claims(key, &cl); err != nil {
return nil, fmt.Errorf("verifying token claims: %v", err)
}
if err := cl.Validate(jwt.Expected{
Issuer: v.md.Issuer,
Audience: jwt.Audience([]string{audience}),
Time: time.Now(),
}); err != nil {
return nil, fmt.Errorf("claim validation: %v", err)
}
// now parse it in to our type to return
idt := Claims{}
if err := tok.Claims(key, &idt); err != nil {
return nil, fmt.Errorf("verifying token claims: %v", err)
}
return &idt, nil
}