This repository has been archived by the owner on May 22, 2023. It is now read-only.
/
tokenparser.go
96 lines (85 loc) · 2.81 KB
/
tokenparser.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
package auth
import (
"errors"
"strconv"
"time"
"github.com/codeready-toolchain/devcluster/pkg/log"
"github.com/golang-jwt/jwt"
)
/****************************************************
This section is a temporary fix until formal leeway support is available in the next jwt-go release
*****************************************************/
const leeway = 5000
// TokenClaims represents access token claims
type TokenClaims struct {
Name string `json:"name"`
Username string `json:"preferred_username"`
GivenName string `json:"given_name"`
FamilyName string `json:"family_name"`
Email string `json:"email"`
EmailVerified bool `json:"email_verified"`
Company string `json:"company"`
jwt.StandardClaims
}
// Valid checks whether the token claims are valid
func (c *TokenClaims) Valid() error {
c.StandardClaims.IssuedAt -= leeway
now := time.Now().Unix()
err := c.StandardClaims.Valid()
if err != nil {
log.Error(nil, err, "Token validation failed")
log.Infof(nil, "Current time: %s", strconv.FormatInt(now, 10))
log.Infof(nil, "Token IssuedAt time: %s", strconv.FormatInt(c.StandardClaims.IssuedAt, 10))
}
c.StandardClaims.IssuedAt += leeway
return err
}
// TokenParser represents a parser for JWT tokens.
type TokenParser struct {
keyManager *KeyManager
}
// NewTokenParser creates a new TokenParser.
func NewTokenParser(keyManager *KeyManager) (*TokenParser, error) {
if keyManager == nil {
return nil, errors.New("no keyManager given when creating TokenParser")
}
return &TokenParser{
keyManager: keyManager,
}, nil
}
// FromString parses a JWT, validates the signaure and returns the claims struct.
func (tp *TokenParser) FromString(jwtEncoded string) (*TokenClaims, error) {
token, err := jwt.ParseWithClaims(jwtEncoded, &TokenClaims{}, func(token *jwt.Token) (interface{}, error) {
kid := token.Header["kid"]
if kid == nil {
return nil, errors.New("no key id given in the token")
}
kidStr, ok := kid.(string)
if !ok {
return nil, errors.New("given key id has unknown type")
}
// get the public key for kid from keyManager
publicKey, err := tp.keyManager.Key(kidStr)
if err != nil {
return nil, err
}
return publicKey, nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*TokenClaims); ok && token.Valid {
// we need username and email, so check if those are contained in the claims
if claims.Username == "" {
return nil, errors.New("token does not comply to expected claims: username missing")
}
if claims.Email == "" {
return nil, errors.New("token does not comply to expected claims: email missing")
}
if claims.Subject == "" {
return nil, errors.New("token does not comply to expected claims: subject missing")
}
return claims, nil
}
return nil, errors.New("token does not comply to expected claims")
}