Repository: appleboy/gin-jwt
Pull request #263 (2020-12-22 08:29:40)

Allow asymmetric key in []byte
# What does it do?
This pull request allows us to add public and private key's using ```[]byte``` rather than file path
# Why
1. In serverless environments, file system access is not always available.
2. Will allow support for hosted secrets storage, i.e Google Secrets Manager, Azure Key Vault
3. Resolves a [query](https://github.com/appleboy/gin-jwt/pull/80#issuecomment-353788381) from the original pull request
# Notes
We decided to extend the API to maintain backward compatibility and we give file path option priority over ```[]byte``` option.


Patch:
diff --git a/auth_jwt.go b/auth_jwt.go
index c8f663d..165afcf 100644
--- a/auth_jwt.go
+++ b/auth_jwt.go
@@ -99,9 +99,19 @@ type GinJWTMiddleware struct {
 	// Private key file for asymmetric algorithms
 	PrivKeyFile string
 
+	// Private Key bytes for asymmetric algorithms
+	//
+	// Note: PrivKeyFile takes precedence over PrivKeyBytes if both are set
+	PrivKeyBytes []byte
+
 	// Public key file for asymmetric algorithms
 	PubKeyFile string
 
+	// Public key bytes for asymmetric algorithms.
+	//
+	// Note: PubKeyFile takes precedence over PubKeyBytes if both are set
+	PubKeyBytes []byte
+
 	// Private key
 	privKey *rsa.PrivateKey
 
@@ -220,10 +230,17 @@ func (mw *GinJWTMiddleware) readKeys() error {
 }
 
 func (mw *GinJWTMiddleware) privateKey() error {
-	keyData, err := ioutil.ReadFile(mw.PrivKeyFile)
-	if err != nil {
-		return ErrNoPrivKeyFile
+	var keyData []byte
+	if mw.PrivKeyFile == "" {
+		keyData = mw.PrivKeyBytes
+	} else {
+		filecontent, err := ioutil.ReadFile(mw.PrivKeyFile)
+		if err != nil {
+			return ErrNoPrivKeyFile
+		}
+		keyData = filecontent
 	}
+
 	key, err := jwt.ParseRSAPrivateKeyFromPEM(keyData)
 	if err != nil {
 		return ErrInvalidPrivKey
@@ -233,10 +250,17 @@ func (mw *GinJWTMiddleware) privateKey() error {
 }
 
 func (mw *GinJWTMiddleware) publicKey() error {
-	keyData, err := ioutil.ReadFile(mw.PubKeyFile)
-	if err != nil {
-		return ErrNoPubKeyFile
+	var keyData []byte
+	if mw.PubKeyFile == "" {
+		keyData = mw.PubKeyBytes
+	} else {
+		filecontent, err := ioutil.ReadFile(mw.PubKeyFile)
+		if err != nil {
+			return ErrNoPubKeyFile
+		}
+		keyData = filecontent
 	}
+
 	key, err := jwt.ParseRSAPublicKeyFromPEM(keyData)
 	if err != nil {
 		return ErrInvalidPubKey


Test patch:
diff --git a/auth_jwt_test.go b/auth_jwt_test.go
index 5c648ee..8bb9402 100644
--- a/auth_jwt_test.go
+++ b/auth_jwt_test.go
@@ -110,6 +110,18 @@ func TestInvalidPrivKey(t *testing.T) {
 	assert.Equal(t, ErrInvalidPrivKey, err)
 }
 
+func TestInvalidPrivKeyBytes(t *testing.T) {
+	_, err := New(&GinJWTMiddleware{
+		Realm:            "zone",
+		SigningAlgorithm: "RS256",
+		PrivKeyBytes:     []byte("Invalid_Private_Key"),
+		PubKeyFile:       "testdata/jwtRS256.key.pub",
+	})
+
+	assert.Error(t, err)
+	assert.Equal(t, ErrInvalidPrivKey, err)
+}
+
 func TestInvalidPubKey(t *testing.T) {
 	_, err := New(&GinJWTMiddleware{
 		Realm:            "zone",
@@ -122,6 +134,18 @@ func TestInvalidPubKey(t *testing.T) {
 	assert.Equal(t, ErrInvalidPubKey, err)
 }
 
+func TestInvalidPubKeyBytes(t *testing.T) {
+	_, err := New(&GinJWTMiddleware{
+		Realm:            "zone",
+		SigningAlgorithm: "RS256",
+		PrivKeyFile:      "testdata/jwtRS256.key",
+		PubKeyBytes:      []byte("Invalid_Private_Key"),
+	})
+
+	assert.Error(t, err)
+	assert.Equal(t, ErrInvalidPubKey, err)
+}
+
 func TestMissingTimeOut(t *testing.T) {
 	authMiddleware, err := New(&GinJWTMiddleware{
 		Realm:         "test zone",