+10
-4
atproto/auth/jwt.go
+10
-4
atproto/auth/jwt.go
···
20
20
21
21
type ServiceAuthValidator struct {
22
22
// Service DID reference for this validator: a DID with optional #-separated fragment
23
-
Audience string
24
-
Dir identity.Directory
23
+
Audience string
24
+
Dir identity.Directory
25
+
TimestampLeeway time.Duration
25
26
}
26
27
27
28
type serviceAuthClaims struct {
···
32
33
33
34
func (s *ServiceAuthValidator) Validate(ctx context.Context, tokenString string, lexMethod *syntax.NSID) (syntax.DID, error) {
34
35
36
+
leeway := s.TimestampLeeway
37
+
if leeway == 0 {
38
+
leeway = 5 * time.Second
39
+
}
40
+
35
41
opts := []jwt.ParserOption{
36
42
jwt.WithValidMethods(supportedAlgs),
37
43
jwt.WithAudience(s.Audience),
38
44
jwt.WithExpirationRequired(),
39
45
jwt.WithIssuedAt(),
40
-
jwt.WithLeeway(5 * time.Second), // TODO: configurable? better default?
46
+
jwt.WithLeeway(leeway),
41
47
}
42
48
43
49
token, err := jwt.ParseWithClaims(tokenString, &serviceAuthClaims{}, s.fetchIssuerKeyFunc(ctx), opts...)
···
73
79
}
74
80
claims, ok := token.Claims.(*serviceAuthClaims)
75
81
if !ok {
76
-
// TODO: is this the best error here?
82
+
// TODO: is the error message returned descriptive enough?
77
83
return "", jwt.ErrTokenInvalidClaims
78
84
}
79
85