-
Notifications
You must be signed in to change notification settings - Fork 151
Expand file tree
/
Copy pathcommand_jwt.go
More file actions
134 lines (115 loc) · 3.73 KB
/
Copy pathcommand_jwt.go
File metadata and controls
134 lines (115 loc) · 3.73 KB
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main
import (
"crypto"
"crypto/rand"
"crypto/x509"
"fmt"
"strings"
"time"
"github.com/gofrs/uuid"
"github.com/golang-jwt/jwt/v4"
"github.com/pkg/errors"
)
func commandJwt() error {
userIdent, err := findUserIdentity()
if err != nil {
return errors.Wrap(err, "failed to get identity matching specified user-id")
}
if userIdent == nil {
return fmt.Errorf("could not find identity matching specified user-id: %s", *localUserOpt)
}
cert, err := userIdent.Certificate()
if err != nil {
return errors.Wrap(err, "failed to get identity certificate")
}
signer, err := userIdent.Signer()
if err != nil {
return errors.Wrap(err, "failed to get identity signer")
}
method, hash, err := getX509JwtSigningMethod(cert)
if err != nil {
return errors.Wrap(err, "failed to get JWT signing method")
}
id, err := uuid.NewV7()
if err != nil {
return errors.New("failed to create new UUID for JWT")
}
issuedAt := time.Now()
expireSeconds := 600
token := jwt.NewWithClaims(method, jwt.RegisteredClaims{
Issuer: cert.Issuer.CommonName,
Subject: cert.Subject.CommonName,
Audience: []string{},
ExpiresAt: &jwt.NumericDate{Time: issuedAt.Add(time.Second * time.Duration(expireSeconds))},
NotBefore: &jwt.NumericDate{Time: issuedAt},
IssuedAt: &jwt.NumericDate{Time: issuedAt},
ID: id.String(),
})
signingString, err := token.SigningString()
if err != nil {
return errors.New("failed to generate JWT signing string")
}
if !hash.Available() {
return fmt.Errorf("hash function not available: %s", hash)
}
hasher := hash.New()
_, err = hasher.Write([]byte(signingString))
if err != nil {
return errors.Wrap(err, "failed to create digest")
}
sigBytes, err := signer.Sign(rand.Reader, hasher.Sum(nil), hash)
if err != nil {
return errors.Wrap(err, "failed to sign JWT")
}
signedJwt := strings.Join([]string{signingString, jwt.EncodeSegment(sigBytes)}, ".")
_, err = stdout.Write([]byte(signedJwt))
if err != nil {
return errors.Wrap(err, "failed to write out JWT")
}
return nil
}
// convert x509.SignatureAlgorithm to jwt.SigningMethod
func getX509JwtSigningMethod(cert *x509.Certificate) (method jwt.SigningMethod, hash crypto.Hash, err error) {
switch cert.SignatureAlgorithm {
case x509.SHA256WithRSA:
method = jwt.SigningMethodRS256
hash = jwt.SigningMethodRS256.Hash
case x509.SHA384WithRSA:
method = jwt.SigningMethodRS384
hash = jwt.SigningMethodRS384.Hash
case x509.SHA512WithRSA:
method = jwt.SigningMethodRS512
hash = jwt.SigningMethodRS512.Hash
case x509.SHA256WithRSAPSS:
method = jwt.SigningMethodPS256
hash = jwt.SigningMethodPS256.Hash
case x509.SHA384WithRSAPSS:
method = jwt.SigningMethodPS384
hash = jwt.SigningMethodPS384.Hash
case x509.SHA512WithRSAPSS:
method = jwt.SigningMethodPS512
hash = jwt.SigningMethodPS512.Hash
case x509.ECDSAWithSHA256:
method = jwt.SigningMethodES256
hash = jwt.SigningMethodES256.Hash
case x509.ECDSAWithSHA384:
method = jwt.SigningMethodES384
hash = jwt.SigningMethodES384.Hash
case x509.ECDSAWithSHA512:
method = jwt.SigningMethodES512
hash = jwt.SigningMethodES512.Hash
case x509.PureEd25519:
// Ed25519 does not implement crypto.Hash, so it is more difficult to implement
// method = jwt.SigningMethodEdDSA
err = errors.New("the Ed25519 algorithm is not currently supported by smimesign")
case x509.DSAWithSHA1, x509.DSAWithSHA256:
err = errors.New("the DSA algorithm is not supported by JWT")
case x509.SHA1WithRSA, x509.ECDSAWithSHA1:
err = errors.New("the SHA1 hashing algorithm is not supported by JWT")
case x509.MD2WithRSA, x509.MD5WithRSA:
err = errors.New("the MD hashing algorithm family is not supported by JWT")
default:
err = errors.New("could not parse the x509 signature algorithm")
}
return
}