-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Add asymmetric JWT signing #16010
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add asymmetric JWT signing #16010
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
c99a53c
Added asymmetric token signing.
KN4CK3R 0ae9106
lint
KN4CK3R 7e814d0
Load signing key from settings.
KN4CK3R e700002
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R 7518bd9
Added optional kid parameter.
KN4CK3R 2531f4b
Updated documentation.
KN4CK3R 3d61518
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R 25a213c
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R d9d4201
Merge branch 'main' into feature-jwt-asymmetric
techknowlogick a6c42be
Add "kid" to token header.
KN4CK3R 602c741
Merge branch 'main' into feature-jwt-asymmetric
techknowlogick 032c0ab
Fixed name.
KN4CK3R 0ac1771
Merge branch 'main' of https://github.com/go-gitea/gitea into feature…
KN4CK3R 3cfaecc
Merge branch 'main' into feature-jwt-asymmetric
techknowlogick a5d22ae
Merge branch 'main' into feature-jwt-asymmetric
techknowlogick 137a089
Merge branch 'main' into feature-jwt-asymmetric
6543 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
// Copyright 2021 The Gitea Authors. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package oauth2 | ||
|
||
import ( | ||
"crypto/ecdsa" | ||
"crypto/rsa" | ||
"encoding/base64" | ||
"fmt" | ||
"math/big" | ||
|
||
"code.gitea.io/gitea/modules/setting" | ||
|
||
"github.com/dgrijalva/jwt-go" | ||
) | ||
|
||
// ErrInvalidAlgorithmType represents an invalid algorithm error. | ||
type ErrInvalidAlgorithmType struct { | ||
Algorightm string | ||
} | ||
|
||
func (err ErrInvalidAlgorithmType) Error() string { | ||
return fmt.Sprintf("JWT signing algorithm is not supported: %s", err.Algorightm) | ||
} | ||
|
||
// JWTSigningKey represents a algorithm/key pair to sign JWTs | ||
type JWTSigningKey interface { | ||
IsSymmetric() bool | ||
SigningMethod() jwt.SigningMethod | ||
SignKey() interface{} | ||
VerifyKey() interface{} | ||
ToJSON() map[string]string | ||
} | ||
|
||
type hmacSingingKey struct { | ||
6543 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
signingMethod jwt.SigningMethod | ||
secret []byte | ||
} | ||
|
||
func (key hmacSingingKey) IsSymmetric() bool { | ||
return true | ||
} | ||
|
||
func (key hmacSingingKey) SigningMethod() jwt.SigningMethod { | ||
return key.signingMethod | ||
} | ||
|
||
func (key hmacSingingKey) SignKey() interface{} { | ||
return key.secret | ||
} | ||
|
||
func (key hmacSingingKey) VerifyKey() interface{} { | ||
return key.secret | ||
} | ||
|
||
func (key hmacSingingKey) ToJSON() map[string]string { | ||
return map[string]string{} | ||
} | ||
|
||
type rsaSingingKey struct { | ||
signingMethod jwt.SigningMethod | ||
key *rsa.PrivateKey | ||
} | ||
|
||
func (key rsaSingingKey) IsSymmetric() bool { | ||
return false | ||
} | ||
|
||
func (key rsaSingingKey) SigningMethod() jwt.SigningMethod { | ||
return key.signingMethod | ||
} | ||
|
||
func (key rsaSingingKey) SignKey() interface{} { | ||
return key.key | ||
} | ||
|
||
func (key rsaSingingKey) VerifyKey() interface{} { | ||
return key.key.Public() | ||
} | ||
|
||
func (key rsaSingingKey) ToJSON() map[string]string { | ||
pubKey := key.key.Public().(*rsa.PublicKey) | ||
|
||
return map[string]string { | ||
"kty": "RSA", | ||
"alg": key.SigningMethod().Alg(), | ||
"e": base64.RawURLEncoding.EncodeToString(big.NewInt(int64(pubKey.E)).Bytes()), | ||
"n": base64.RawURLEncoding.EncodeToString(pubKey.N.Bytes()), | ||
} | ||
} | ||
|
||
type ecdsaSingingKey struct { | ||
signingMethod jwt.SigningMethod | ||
key *ecdsa.PrivateKey | ||
} | ||
|
||
func (key ecdsaSingingKey) IsSymmetric() bool { | ||
return false | ||
} | ||
|
||
func (key ecdsaSingingKey) SigningMethod() jwt.SigningMethod { | ||
return key.signingMethod | ||
} | ||
|
||
func (key ecdsaSingingKey) SignKey() interface{} { | ||
return key.key | ||
} | ||
|
||
func (key ecdsaSingingKey) VerifyKey() interface{} { | ||
return key.key.Public() | ||
} | ||
|
||
func (key ecdsaSingingKey) ToJSON() map[string]string { | ||
pubKey := key.key.Public().(*ecdsa.PublicKey) | ||
|
||
return map[string]string { | ||
"kty": "EC", | ||
"alg": key.SigningMethod().Alg(), | ||
"crv": pubKey.Params().Name, | ||
"x": base64.RawURLEncoding.EncodeToString(pubKey.X.Bytes()), | ||
"y": base64.RawURLEncoding.EncodeToString(pubKey.Y.Bytes()), | ||
} | ||
} | ||
|
||
// CreateJWTSingingKey creates a signing key from an algorithm / key pair. | ||
func CreateJWTSingingKey(algorithm string, key interface{}) (JWTSigningKey, error) { | ||
var signingMethod jwt.SigningMethod | ||
switch algorithm { | ||
case "HS256": | ||
signingMethod = jwt.SigningMethodHS256 | ||
case "HS384": | ||
signingMethod = jwt.SigningMethodHS384 | ||
case "HS512": | ||
signingMethod = jwt.SigningMethodHS512 | ||
|
||
case "RS256": | ||
signingMethod = jwt.SigningMethodRS256 | ||
case "RS384": | ||
signingMethod = jwt.SigningMethodRS384 | ||
case "RS512": | ||
signingMethod = jwt.SigningMethodRS512 | ||
|
||
case "ES256": | ||
signingMethod = jwt.SigningMethodES256 | ||
case "ES384": | ||
signingMethod = jwt.SigningMethodES384 | ||
case "ES512": | ||
signingMethod = jwt.SigningMethodES512 | ||
default: | ||
return nil, ErrInvalidAlgorithmType{algorithm} | ||
} | ||
|
||
switch signingMethod.(type) { | ||
case *jwt.SigningMethodECDSA: | ||
privateKey, ok := key.(*ecdsa.PrivateKey) | ||
if !ok { | ||
return nil, jwt.ErrInvalidKeyType | ||
} | ||
return ecdsaSingingKey{signingMethod, privateKey}, nil | ||
case *jwt.SigningMethodRSA: | ||
privateKey, ok := key.(*rsa.PrivateKey) | ||
if !ok { | ||
return nil, jwt.ErrInvalidKeyType | ||
} | ||
return rsaSingingKey{signingMethod, privateKey}, nil | ||
default: | ||
secret, ok := key.([]byte) | ||
if !ok { | ||
return nil, jwt.ErrInvalidKeyType | ||
} | ||
return hmacSingingKey{signingMethod, secret}, nil | ||
} | ||
} | ||
|
||
// DefaultSigningKey is the default signing key for JWTs. | ||
var DefaultSigningKey JWTSigningKey | ||
|
||
// InitSigningKey creates the default signing key from settings or creates a random key. | ||
func InitSigningKey() error { | ||
key, err := CreateJWTSingingKey("HS256", setting.OAuth2.JWTSecretBytes) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
DefaultSigningKey = key | ||
|
||
return nil | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.