-
-
Notifications
You must be signed in to change notification settings - Fork 367
/
introspector_jwt.go
88 lines (74 loc) · 2.15 KB
/
introspector_jwt.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
// Copyright © 2024 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package oauth2
import (
"context"
"time"
"github.com/ory/fosite"
"github.com/ory/fosite/token/jwt"
)
type StatelessJWTValidator struct {
jwt.Signer
Config interface {
fosite.ScopeStrategyProvider
}
}
// AccessTokenJWTToRequest tries to reconstruct fosite.Request from a JWT.
func AccessTokenJWTToRequest(token *jwt.Token) fosite.Requester {
mapClaims := token.Claims
claims := jwt.JWTClaims{}
claims.FromMapClaims(mapClaims)
requestedAt := claims.IssuedAt
requestedAtClaim, ok := mapClaims["rat"]
if ok {
switch at := requestedAtClaim.(type) {
case float64:
requestedAt = time.Unix(int64(at), 0).UTC()
case int64:
requestedAt = time.Unix(at, 0).UTC()
}
}
clientId := ""
clientIdClaim, ok := mapClaims["client_id"]
if ok {
switch cid := clientIdClaim.(type) {
case string:
clientId = cid
}
}
return &fosite.Request{
RequestedAt: requestedAt,
Client: &fosite.DefaultClient{
ID: clientId,
},
// We do not really know which scopes were requested, so we set them to granted.
RequestedScope: claims.Scope,
GrantedScope: claims.Scope,
Session: &JWTSession{
JWTClaims: &claims,
JWTHeader: &jwt.Headers{
Extra: token.Header,
},
ExpiresAt: map[fosite.TokenType]time.Time{
fosite.AccessToken: claims.ExpiresAt,
},
Subject: claims.Subject,
},
// We do not really know which audiences were requested, so we set them to granted.
RequestedAudience: claims.Audience,
GrantedAudience: claims.Audience,
}
}
func (v *StatelessJWTValidator) IntrospectToken(ctx context.Context, token string, tokenUse fosite.TokenUse, accessRequest fosite.AccessRequester, scopes []string) (fosite.TokenUse, error) {
t, err := validate(ctx, v.Signer, token)
if err != nil {
return "", err
}
// TODO: From here we assume it is an access token, but how do we know it is really and that is not an ID token?
requester := AccessTokenJWTToRequest(t)
if err := matchScopes(v.Config.GetScopeStrategy(ctx), requester.GetGrantedScopes(), scopes); err != nil {
return fosite.AccessToken, err
}
accessRequest.Merge(requester)
return fosite.AccessToken, nil
}