-
Notifications
You must be signed in to change notification settings - Fork 153
/
jwt.go
91 lines (71 loc) · 2.61 KB
/
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
89
90
91
package auth
import (
"time"
"github.com/pkg/errors"
"github.com/weaveworks/weave-gitops/pkg/gitproviders"
"github.com/golang-jwt/jwt/v4"
)
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
// ExpirationTime jwt token expiration time
const ExpirationTime = time.Minute * 15
// ErrUnauthorizedToken unauthorized token error
var ErrUnauthorizedToken = errors.New("unauthorized token")
// Claims is a custom JWT claims that contains some token information
type Claims struct {
jwt.StandardClaims
Provider gitproviders.GitProviderName `json:"provider"`
ProviderToken string `json:"provider_token"`
}
// JWTClient represents a type that has methods to generate and verify JWT tokens.
//counterfeiter:generate . JWTClient
type JWTClient interface {
GenerateJWT(expirationTime time.Duration, providerName gitproviders.GitProviderName, providerToken string) (string, error)
VerifyJWT(accessToken string) (*Claims, error)
}
// NewJwtClient initialize JWTClient instance
func NewJwtClient(secretKey string) JWTClient {
return &internalJWTClient{secretKey: secretKey}
}
type internalJWTClient struct {
secretKey string
}
// GenerateJWT generates and signs a new token
func (i *internalJWTClient) GenerateJWT(expirationTime time.Duration, providerName gitproviders.GitProviderName, providerToken string) (string, error) {
claims := Claims{
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Add(expirationTime).Unix(),
},
Provider: providerName,
ProviderToken: providerToken,
}
if expirationTime == 0 {
// It is possible for the GitLab backend to specify an `expires_in` of 0.
// Edit the `Expire access tokens` setting to enable/disable expiring tokens.
// Gitlab defaults to 2 hour expiration, so replicate it here I guess?
claims.StandardClaims.ExpiresAt = time.Now().Add(2 * time.Hour).Unix()
}
token := jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
return token.SignedString([]byte(i.secretKey))
}
// VerifyJWT verifies the access token string and return a user claim if the token is valid
func (i *internalJWTClient) VerifyJWT(accessToken string) (*Claims, error) {
token, err := jwt.ParseWithClaims(
accessToken,
&Claims{},
func(token *jwt.Token) (interface{}, error) {
_, ok := token.Method.(*jwt.SigningMethodHMAC)
if !ok {
return nil, errors.New("unexpected token signing method")
}
return []byte(i.secretKey), nil
},
)
if err != nil {
return nil, errors.WithMessage(ErrUnauthorizedToken, err.Error())
}
claims, ok := token.Claims.(*Claims)
if !ok {
return nil, errors.New("invalid token claims")
}
return claims, nil
}