Use RS256 to sign JWT token.

This commit is contained in:
Gucheng Wang 2021-10-15 16:27:10 +08:00
parent 795240687d
commit 5526286ad8
8 changed files with 247 additions and 10 deletions

3
go.mod
View File

@ -1,6 +1,6 @@
module github.com/casbin/casdoor module github.com/casbin/casdoor
go 1.15 go 1.16
require ( require (
github.com/aliyun/aliyun-oss-go-sdk v2.1.6+incompatible // indirect github.com/aliyun/aliyun-oss-go-sdk v2.1.6+incompatible // indirect
@ -23,6 +23,7 @@ require (
github.com/satori/go.uuid v1.2.0 // indirect github.com/satori/go.uuid v1.2.0 // indirect
github.com/smartystreets/goconvey v1.6.4 // indirect github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/thanhpk/randstr v1.0.4 github.com/thanhpk/randstr v1.0.4
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect

1
go.sum
View File

@ -104,7 +104,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw= github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8= github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=

View File

@ -15,12 +15,18 @@
package object package object
import ( import (
_ "embed"
"fmt"
"time" "time"
"github.com/golang-jwt/jwt/v4" "github.com/golang-jwt/jwt/v4"
) )
var jwtSecret = []byte("CasdoorSecret") //go:embed token_jwt_key.pem
var tokenJwtPublicKey string
//go:embed token_jwt_key.key
var tokenJwtPrivateKey string
type Claims struct { type Claims struct {
User User
@ -46,19 +52,37 @@ func generateJwtToken(application *Application, user *User) (string, error) {
}, },
} }
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
tokenString, err := token.SignedString(jwtSecret)
// Use "token_jwt_key.key" as RSA private key
privateKey := tokenJwtPrivateKey
key, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(privateKey))
if err != nil {
return "", err
}
tokenString, err := token.SignedString(key)
return tokenString, err return tokenString, err
} }
func ParseJwtToken(tokenString string) (*Claims, error) { func ParseJwtToken(token string) (*Claims, error) {
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) { t, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return jwtSecret, nil if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
// Use "token_jwt_key.pem" as RSA public key
publicKey, err := jwt.ParseRSAPublicKeyFromPEM([]byte(tokenJwtPublicKey))
if err != nil {
return nil, err
}
return publicKey, nil
}) })
if token != nil { if t != nil {
if claims, ok := token.Claims.(*Claims); ok && token.Valid { if claims, ok := t.Claims.(*Claims); ok && t.Valid {
return claims, nil return claims, nil
} }
} }

78
object/token_jwt_key.go Normal file
View File

@ -0,0 +1,78 @@
// Copyright 2021 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package object
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"time"
"github.com/casbin/casdoor/util"
)
func generateRsaKeys(fileId string) {
// https://stackoverflow.com/questions/64104586/use-golang-to-get-rsa-key-the-same-way-openssl-genrsa
// https://stackoverflow.com/questions/43822945/golang-can-i-create-x509keypair-using-rsa-key
bitSize := 4096
// Generate RSA key.
key, err := rsa.GenerateKey(rand.Reader, bitSize)
if err != nil {
panic(err)
}
// Encode private key to PKCS#1 ASN.1 PEM.
privateKeyPem := pem.EncodeToMemory(
&pem.Block{
Type: "PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
},
)
tml := x509.Certificate{
// you can add any attr that you need
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(20, 0, 0),
// you have to generate a different serial number each execution
SerialNumber: big.NewInt(123456),
Subject: pkix.Name{
CommonName: "Casdoor Cert",
Organization: []string{"Casdoor Organization"},
},
BasicConstraintsValid: true,
}
cert, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key)
if err != nil {
panic(err)
}
// Generate a pem block with the certificate
certPem := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: cert,
})
// Write private key to file.
util.WriteBytesToPath(privateKeyPem, fmt.Sprintf("%s.key", fileId))
// Write certificate (aka public key) to file.
util.WriteBytesToPath(certPem, fmt.Sprintf("%s.pem", fileId))
}

51
object/token_jwt_key.key Normal file
View File

@ -0,0 +1,51 @@
-----BEGIN PRIVATE KEY-----
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
-----END PRIVATE KEY-----

29
object/token_jwt_key.pem Normal file
View File

@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE+TCCAuGgAwIBAgIDAeJAMA0GCSqGSIb3DQEBCwUAMDYxHTAbBgNVBAoTFENh
c2Rvb3IgT3JnYW5pemF0aW9uMRUwEwYDVQQDEwxDYXNkb29yIENlcnQwHhcNMjEx
MDE1MDgxMTUyWhcNNDExMDE1MDgxMTUyWjA2MR0wGwYDVQQKExRDYXNkb29yIE9y
Z2FuaXphdGlvbjEVMBMGA1UEAxMMQ2FzZG9vciBDZXJ0MIICIjANBgkqhkiG9w0B
AQEFAAOCAg8AMIICCgKCAgEAsInpb5E1/ym0f1RfSDSSE8IR7y+lw+RJjI74e5ej
rq4b8zMYk7HeHCyZr/hmNEwEVXnhXu1P0mBeQ5ypp/QGo8vgEmjAETNmzkI1NjOQ
CjCYwUrasO/f/MnI1C0j13vx6mV1kHZjSrKsMhYY1vaxTEP3+VB8Hjg3MHFWrb07
uvFMCJe5W8+0rKErZCKTR8+9VB3janeBz//zQePFVh79bFZate/hLirPK0Go9P1g
OvwIoC1A3sarHTP4Qm/LQRt0rHqZFybdySpyWAQvhNaDFE7mTstRSBb/wUjNCUBD
PTSLVjC04WllSf6Nkfx0Z7KvmbPstSj+btvcqsvRAGtvdsB9h62Kptjs1Yn7GAuo
I3qt/4zoKbiURYxkQJXIvwCQsEftUuk5ew5zuPSlDRLoLByQTLbx0JqLAFNfW3g/
pzSDjgd/60d6HTmvbZni4SmjdyFhXCDb1Kn7N+xTojnfaNkwep2REV+RMc0fx4Gu
hRsnLsmkmUDeyIZ9aBL9oj11YEQfM2JZEq+RVtUx+wB4y8K/tD1bcY+IfnG5rBpw
IDpS262boq4SRSvb3Z7bB0w4ZxvOfJ/1VLoRftjPbLIf0bhfr/AeZMHpIKOXvfz4
yE+hqzi68wdF0VR9xYc/RbSAf7323OsjYnjjEgInUtRohnRgCpjIk/Mt2Kt84Kb0
wn8CAwEAAaMQMA4wDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAn2lf
DKkLX+F1vKRO/5gJ+Plr8P5NKuQkmwH97b8CS2gS1phDyNgIc4/LSdzuf4Awe6ve
C06lVdWSIis8UPUPdjmT2uMPSNjwLxG3QsrimMURNwFlLTfRem/heJe0Zgur9J1M
8haawdSdJjH2RgmFoDeE2r8NVRfhbR8KnCO1ddTJKuS1N0/irHz21W4jt4rxzCvl
2nR42Fybap3O/g2JXMhNNROwZmNjgpsF7XVENCSuFO1jTywLaqjuXCg54IL7XVLG
omKNNNcc8h1FCeKj/nnbGMhodnFWKDTsJcbNmcOPNHo6ixzqMy/Hqc+mWYv7maAG
Jtevs3qgMZ8F9Qzr3HpUc6R3ZYYWDY/xxPisuKftOPZgtH979XC4mdf0WPnOBLqL
2DJ1zaBmjiGJolvb7XNVKcUfDXYw85ZTZQ5b9clI4e+6bmyWqQItlwt+Ati/uFEV
XzCj70B4lALX6xau1kLEpV9O1GERizYRz5P9NJNA7KoO5AVMp9w0DQTkt+LbXnZE
HHnWKy8xHQKZF9sR7YBPGLs/Ac6tviv5Ua15OgJ/8dLRZ/veyFfGo2yZsI+hKVU5
nCCJHBcAyFnm1hdvdwEdH33jDBjNB6ciotJZrf/3VYaIWSalADosHAgMWfXuWP+h
8XKXmzlxuHbTMQYtZPDgspS5aK+S4Q9wb8RRAYo=
-----END CERTIFICATE-----

View File

@ -0,0 +1,22 @@
// Copyright 2021 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package object
import "testing"
func TestGenerateRsaKeys(t *testing.T) {
fileId := "token_jwt_key"
generateRsaKeys(fileId)
}

View File

@ -19,6 +19,7 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"strconv" "strconv"
"strings" "strings"
@ -95,3 +96,35 @@ func GetMinLenStr(strs ...string) string {
} }
return strs[i] return strs[i]
} }
func ReadStringFromPath(path string) string {
data, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
return string(data)
}
func WriteStringToPath(s string, path string) {
err := ioutil.WriteFile(path, []byte(s), 0644)
if err != nil {
panic(err)
}
}
func ReadBytesFromPath(path string) []byte {
data, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
return data
}
func WriteBytesToPath(b []byte, path string) {
err := ioutil.WriteFile(path, b, 0644)
if err != nil {
panic(err)
}
}