Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/public-api-server/pkg/jws/rsa256.go
2506 views
1
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package jws
6
7
import (
8
"crypto"
9
"crypto/rsa"
10
"errors"
11
"fmt"
12
13
"github.com/golang-jwt/jwt/v5"
14
)
15
16
func NewRSA256(keyset KeySet) (*RSA256, error) {
17
verifier, err := NewRSA256VerifierFromKeySet(keyset)
18
if err != nil {
19
return nil, err
20
}
21
22
return &RSA256{
23
RSA256Signer: &RSA256Signer{
24
Signing: keyset.Signing,
25
},
26
RSA256Verifier: verifier,
27
}, nil
28
}
29
30
type RSA256 struct {
31
*RSA256Signer
32
*RSA256Verifier
33
}
34
35
type RSA256Signer struct {
36
Signing Key
37
}
38
39
func (s *RSA256Signer) Sign(token *jwt.Token) (string, error) {
40
if token.Method != jwt.SigningMethodRS256 {
41
return "", errors.New("invalid signing method, token must use RSA256")
42
}
43
44
token.Header[KeyIDName] = s.Signing.ID
45
46
signed, err := token.SignedString(s.Signing.Private)
47
if err != nil {
48
return "", fmt.Errorf("failed to sign jwt: %w", err)
49
}
50
51
return signed, nil
52
}
53
54
func NewRSA256VerifierFromKeySet(keyset KeySet) (*RSA256Verifier, error) {
55
keys := map[string]*rsa.PrivateKey{
56
keyset.Signing.ID: keyset.Signing.Private,
57
}
58
59
for _, v := range keyset.Validating {
60
if _, found := keys[v.ID]; found {
61
return nil, errors.New("duplicate keys when constructing JWT")
62
}
63
64
keys[v.ID] = v.Private
65
}
66
67
return &RSA256Verifier{
68
Keys: keys,
69
}, nil
70
}
71
72
type RSA256Verifier struct {
73
// Keys by Key ID
74
Keys map[string]*rsa.PrivateKey
75
}
76
77
func (v *RSA256Verifier) Verify(token string, claims jwt.Claims, opts ...jwt.ParserOption) (*jwt.Token, error) {
78
parsed, err := jwt.ParseWithClaims(token, claims, jwt.Keyfunc(func(t *jwt.Token) (interface{}, error) {
79
return v.getPublicKeyFromKeyID(t)
80
}), opts...)
81
82
if err != nil {
83
return nil, fmt.Errorf("failed to parse jwt: %w", err)
84
}
85
86
return parsed, nil
87
}
88
89
func (v *RSA256Verifier) getPublicKeyFromKeyID(token *jwt.Token) (crypto.PublicKey, error) {
90
keyID, ok := token.Header[KeyIDName].(string)
91
if !ok {
92
return nil, fmt.Errorf("missing key id: %w", ErrInvalidKeyID)
93
}
94
95
key, ok := v.Keys[keyID]
96
if !ok {
97
return nil, fmt.Errorf("unknown key id %s: %w", keyID, ErrInvalidKeyID)
98
}
99
100
return key.Public(), nil
101
}
102
103