12
12
13
13
// Builder is used to create a new token.
14
14
type Builder struct {
15
- signer Signer
16
- header Header
15
+ signer Signer
16
+ header Header
17
+ headerRaw []byte
17
18
}
18
19
19
20
// BuildBytes is used to create and encode JWT with a provided claims.
@@ -30,12 +31,12 @@ func Build(signer Signer, claims interface{}) (*Token, error) {
30
31
func NewBuilder (signer Signer ) * Builder {
31
32
b := & Builder {
32
33
signer : signer ,
33
-
34
34
header : Header {
35
35
Algorithm : signer .Algorithm (),
36
36
Type : "JWT" ,
37
37
},
38
38
}
39
+ b .headerRaw = encodeHeader (& b .header )
39
40
return b
40
41
}
41
42
@@ -49,72 +50,116 @@ func (b *Builder) BuildBytes(claims interface{}) ([]byte, error) {
49
50
}
50
51
51
52
// Build used to create and encode JWT with a provided claims.
53
+ // If claims param is of type []byte then we treat it as a marshaled JSON.
54
+ // In other words you can pass already marshaled claims.
52
55
func (b * Builder ) Build (claims interface {}) (* Token , error ) {
53
- rawClaims , encodedClaims , err := encodeClaims (claims )
56
+ rawClaims , err := encodeClaims (claims )
54
57
if err != nil {
55
58
return nil , err
56
59
}
57
60
58
- encodedHeader := encodeHeader (& b .header )
59
- payload := concatParts (encodedHeader , encodedClaims )
61
+ lenH := len (b .headerRaw )
62
+ lenC := base64EncodedLen (len (rawClaims ))
63
+ lenS := base64EncodedLen (b .signer .SignSize ())
64
+
65
+ raw := make ([]byte , lenH + 1 + lenC + 1 + lenS )
66
+ idx := 0
67
+ idx += copy (raw [idx :], b .headerRaw )
68
+ raw [idx ] = '.'
69
+ idx ++
70
+ base64Encode (raw [idx :], rawClaims )
71
+ idx += lenC
60
72
61
- raw , signature , err := signPayload ( b .signer , payload )
73
+ signature , err := b .signer . Sign ( raw [: idx ] )
62
74
if err != nil {
63
75
return nil , err
64
76
}
77
+ raw [idx ] = '.'
78
+ idx ++
79
+ base64Encode (raw [idx :], signature )
80
+ idx += lenS
65
81
66
82
token := & Token {
67
83
raw : raw ,
68
- payload : payload ,
84
+ payload : raw [: lenH + 1 + lenC ] ,
69
85
signature : signature ,
70
86
header : b .header ,
71
87
claims : rawClaims ,
72
88
}
73
89
return token , nil
74
90
}
75
91
76
- func encodeClaims (claims interface {}) (raw , encoded []byte , err error ) {
77
- raw , err = json .Marshal (claims )
78
- if err != nil {
79
- return nil , nil , err
92
+ func encodeClaims (claims interface {}) ([]byte , error ) {
93
+ switch claims := claims .(type ) {
94
+ case []byte :
95
+ return claims , nil
96
+ default :
97
+ return json .Marshal (claims )
80
98
}
81
-
82
- encoded = make ([]byte , base64EncodedLen (len (raw )))
83
- base64Encode (encoded , raw )
84
-
85
- return raw , encoded , nil
86
99
}
87
100
88
101
func encodeHeader (header * Header ) []byte {
102
+ if header .Type == "JWT" && header .ContentType == "" {
103
+ switch header .Algorithm {
104
+ case EdDSA :
105
+ return []byte (encHeaderEdDSA )
106
+
107
+ case HS256 :
108
+ return []byte (encHeaderHS256 )
109
+ case HS384 :
110
+ return []byte (encHeaderHS384 )
111
+ case HS512 :
112
+ return []byte (encHeaderHS512 )
113
+
114
+ case RS256 :
115
+ return []byte (encHeaderRS256 )
116
+ case RS384 :
117
+ return []byte (encHeaderRS384 )
118
+ case RS512 :
119
+ return []byte (encHeaderRS512 )
120
+
121
+ case ES256 :
122
+ return []byte (encHeaderES256 )
123
+ case ES384 :
124
+ return []byte (encHeaderES384 )
125
+ case ES512 :
126
+ return []byte (encHeaderES512 )
127
+
128
+ case PS256 :
129
+ return []byte (encHeaderPS256 )
130
+ case PS384 :
131
+ return []byte (encHeaderPS384 )
132
+ case PS512 :
133
+ return []byte (encHeaderPS512 )
134
+
135
+ default :
136
+ // another algorithm? encode below
137
+ }
138
+ }
89
139
// returned err is always nil, see *Header.MarshalJSON
90
- buf , _ := header . MarshalJSON ( )
140
+ buf , _ := json . Marshal ( header )
91
141
92
142
encoded := make ([]byte , base64EncodedLen (len (buf )))
93
143
base64Encode (encoded , buf )
94
-
95
144
return encoded
96
145
}
97
146
98
- func signPayload (signer Signer , payload []byte ) (signed , signature []byte , err error ) {
99
- signature , err = signer .Sign (payload )
100
- if err != nil {
101
- return nil , nil , err
102
- }
147
+ const (
148
+ encHeaderEdDSA = "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9"
103
149
104
- encodedSignature := make ([]byte , base64EncodedLen (len (signature )))
105
- base64Encode (encodedSignature , signature )
150
+ encHeaderHS256 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
151
+ encHeaderHS384 = "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9"
152
+ encHeaderHS512 = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9"
106
153
107
- signed = concatParts (payload , encodedSignature )
108
-
109
- return signed , signature , nil
110
- }
154
+ encHeaderRS256 = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9"
155
+ encHeaderRS384 = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9"
156
+ encHeaderRS512 = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9"
111
157
112
- func concatParts ( a , b [] byte ) [] byte {
113
- buf := make ([] byte , len ( a ) + 1 + len ( b ))
114
- buf [ len ( a )] = '.'
158
+ encHeaderES256 = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9"
159
+ encHeaderES384 = "eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9"
160
+ encHeaderES512 = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9"
115
161
116
- copy (buf [:len (a )], a )
117
- copy (buf [len (a )+ 1 :], b )
118
-
119
- return buf
120
- }
162
+ encHeaderPS256 = "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9"
163
+ encHeaderPS384 = "eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9"
164
+ encHeaderPS512 = "eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9"
165
+ )
0 commit comments