1
1
package jwt
2
2
3
3
import (
4
- "errors "
4
+ "fmt "
5
5
"time"
6
6
7
- "gopkg.in/square/go-jose.v2"
8
- "gopkg.in/square/go-jose.v2/jwt"
9
-
10
7
"github.com/shaj13/go-guardian/v2/auth"
8
+ "github.com/shaj13/go-guardian/v2/auth/claims"
9
+ "github.com/shaj13/go-guardian/v2/auth/internal/jwt"
11
10
)
12
11
13
- const headerKID = "kid"
14
-
15
12
const (
16
13
// EdDSA signature algorithm.
17
14
EdDSA = "EdDSA"
@@ -29,11 +26,11 @@ const (
29
26
RS512 = "RS512"
30
27
// ES256 signature algorithm -- ECDSA using P-256 and SHA-256.
31
28
ES256 = "ES256"
32
- // ES384 signature algorithm -- ECDSA using P-384 and SHA-384.
29
+ // ES384 signature algorithm -- ECDSA using P-384 and SHA-384.
33
30
ES384 = "ES384"
34
- // ES512 signature algorithm -- ECDSA using P-521 and SHA-512.
31
+ // ES512 signature algorithm -- ECDSA using P-521 and SHA-512.
35
32
ES512 = "ES512"
36
- // PS256 signature algorithm -- RSASSA-PSS using SHA256 and MGF1-SHA256.
33
+ // PS256 signature algorithm -- RSASSA-PSS using SHA256 and MGF1-SHA256.
37
34
PS256 = "PS256"
38
35
// PS384 signature algorithm -- RSASSA-PSS using SHA384 and MGF1-SHA384.
39
36
PS384 = "PS384"
@@ -44,24 +41,18 @@ const (
44
41
var (
45
42
// ErrMissingKID is returned by Authenticate Strategy method,
46
43
// when failed to retrieve kid from token header.
47
- ErrMissingKID = errors . New ( "strategies/ jwt: Token missing " + headerKID + " header" )
44
+ ErrMissingKID = jwt . ErrMissingKID
48
45
49
46
// ErrInvalidAlg is returned by Authenticate Strategy method,
50
47
// when jwt token alg header does not match key algorithm.
51
- ErrInvalidAlg = errors . New ( "strategies/ jwt: Invalid signing algorithm, token alg header does not match key algorithm" )
48
+ ErrInvalidAlg = jwt . ErrInvalidAlg
52
49
)
53
50
54
51
// IssueAccessToken issue jwt access token for the provided user info.
55
52
func IssueAccessToken (info auth.Info , s SecretsKeeper , opts ... auth.Option ) (string , error ) {
56
53
return newAccessToken (s , opts ... ).issue (info )
57
54
}
58
55
59
- type claims struct {
60
- UserInfo auth.Info `json:"info"`
61
- Scopes []string `json:"scp"`
62
- jwt.Claims
63
- }
64
-
65
56
type accessToken struct {
66
57
keeper SecretsKeeper
67
58
dur time.Duration
@@ -71,76 +62,51 @@ type accessToken struct {
71
62
}
72
63
73
64
func (at accessToken ) issue (info auth.Info ) (string , error ) {
74
- kid := at .keeper .KID ()
75
- secret , alg , err := at .keeper .Get (kid )
76
- if err != nil {
77
- return "" , err
78
- }
79
-
80
- opt := (& jose.SignerOptions {}).WithType ("JWT" ).WithHeader (headerKID , kid )
81
- key := jose.SigningKey {Algorithm : jose .SignatureAlgorithm (alg ), Key : secret }
82
- sig , err := jose .NewSigner (key , opt )
83
-
84
- if err != nil {
85
- return "" , err
86
- }
87
-
88
- now := time .Now ().UTC ()
65
+ now := time .Now ().UTC ().Add (- claims .DefaultLeeway )
89
66
exp := now .Add (at .dur )
90
67
91
- c := claims {
92
- UserInfo : info ,
93
- Scopes : at .scp ,
94
- Claims : jwt.Claims {
95
- Subject : info .GetID (),
96
- Issuer : at .iss ,
97
- Audience : jwt.Audience {at .aud },
98
- Expiry : jwt .NewNumericDate (exp ),
99
- IssuedAt : jwt .NewNumericDate (now ),
100
- NotBefore : jwt .NewNumericDate (now ),
101
- },
68
+ c := claims.Standard {
69
+ Subject : info .GetID (),
70
+ Issuer : at .iss ,
71
+ Audience : claims.StringOrList {at .aud },
72
+ ExpiresAt : (* claims .Time )(& exp ),
73
+ IssuedAt : (* claims .Time )(& now ),
74
+ NotBefore : (* claims .Time )(& now ),
75
+ Scope : at .scp ,
102
76
}
103
77
104
- return jwt .Signed (sig ).Claims (c ).CompactSerialize ()
105
- }
106
-
107
- func (at accessToken ) parse (tstr string ) (* claims , error ) {
108
- c := & claims {
109
- UserInfo : auth .NewUserInfo ("" , "" , nil , nil ),
110
- }
111
-
112
- jt , err := jwt .ParseSigned (tstr )
78
+ str , err := jwt .IssueToken (at .keeper , c , info )
113
79
if err != nil {
114
- return nil , err
80
+ return "" , fmt . Errorf ( "strategies/jwt: %w" , err )
115
81
}
116
82
117
- if len (jt .Headers ) == 0 {
118
- return nil , errors .New ("strategies/jwt: : No headers found in JWT token" )
119
- }
83
+ return str , nil
84
+ }
120
85
121
- if len (jt .Headers [0 ].KeyID ) == 0 {
122
- return nil , ErrMissingKID
86
+ func (at accessToken ) parse (tstr string ) (claims.Standard , auth.Info , error ) {
87
+ fail := func (err error ) (claims.Standard , auth.Info , error ) {
88
+ return claims.Standard {}, nil , fmt .Errorf ("strategies/jwt: %w" , err )
123
89
}
124
90
125
- secret , alg , err := at .keeper .Get (jt .Headers [0 ].KeyID )
126
-
127
- if err != nil {
128
- return nil , err
91
+ info := auth .NewUserInfo ("" , "" , nil , make (auth.Extensions ))
92
+ c := claims.Standard {}
93
+ opts := claims.VerifyOptions {
94
+ Audience : claims.StringOrList {at .aud },
95
+ Issuer : at .iss ,
96
+ Time : func () (t time.Time ) {
97
+ return time .Now ().UTC ().Add (- claims .DefaultLeeway )
98
+ },
129
99
}
130
100
131
- if jt . Headers [ 0 ]. Algorithm != alg {
132
- return nil , ErrInvalidAlg
101
+ if err := jwt . ParseToken ( at . keeper , tstr , & c , info ); err != nil {
102
+ return fail ( err )
133
103
}
134
104
135
- if err := jt . Claims ( secret , c ); err != nil {
136
- return nil , err
105
+ if err := c . Verify ( opts ); err != nil {
106
+ return fail ( err )
137
107
}
138
108
139
- return c , c .Validate (jwt.Expected {
140
- Time : time .Now ().UTC (),
141
- Issuer : at .iss ,
142
- Audience : jwt.Audience {at .aud },
143
- })
109
+ return c , info , nil
144
110
}
145
111
146
112
func newAccessToken (s SecretsKeeper , opts ... auth.Option ) * accessToken {
0 commit comments