Make cert work.

This commit is contained in:
Yang Luo
2021-12-31 09:36:48 +08:00
parent ba1646a0c3
commit 5e8897e41b
18 changed files with 262 additions and 38 deletions

View File

@ -31,6 +31,7 @@ type Application struct {
HomepageUrl string `xorm:"varchar(100)" json:"homepageUrl"`
Description string `xorm:"varchar(100)" json:"description"`
Organization string `xorm:"varchar(100)" json:"organization"`
Cert string `xorm:"varchar(100)" json:"cert"`
EnablePassword bool `json:"enablePassword"`
EnableSignUp bool `json:"enableSignUp"`
EnableSigninSession bool `json:"enableSigninSession"`

View File

@ -124,6 +124,12 @@ func UpdateCert(id string, cert *Cert) bool {
}
func AddCert(cert *Cert) bool {
if cert.PublicKey == "" || cert.PrivateKey == "" {
publicKey, privateKey := generateRsaKeys(cert.BitSize, cert.ExpireInYears, cert.Name, cert.Owner)
cert.PublicKey = publicKey
cert.PrivateKey = privateKey
}
affected, err := adapter.Engine.Insert(cert)
if err != nil {
panic(err)
@ -144,3 +150,15 @@ func DeleteCert(cert *Cert) bool {
func (p *Cert) GetId() string {
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
}
func getCertByApplication(application *Application) *Cert {
if application.Cert != "" {
return getCert("admin", application.Cert)
} else {
return GetDefaultCert()
}
}
func GetDefaultCert() *Cert {
return getCert("admin", "cert-built-in")
}

View File

@ -14,12 +14,23 @@
package object
import "github.com/casbin/casdoor/util"
import (
_ "embed"
"github.com/casbin/casdoor/util"
)
//go:embed token_jwt_key.pem
var tokenJwtPublicKey string
//go:embed token_jwt_key.key
var tokenJwtPrivateKey string
func InitDb() {
initBuiltInOrganization()
initBuiltInUser()
initBuiltInApplication()
initBuiltInCert()
initBuiltInLdap()
}
@ -90,6 +101,7 @@ func initBuiltInApplication() {
Logo: "https://cdn.casbin.com/logo/logo_1024x256.png",
HomepageUrl: "https://casdoor.org",
Organization: "built-in",
Cert: "cert-built-in",
EnablePassword: true,
EnableSignUp: true,
Providers: []*ProviderItem{},
@ -109,6 +121,28 @@ func initBuiltInApplication() {
AddApplication(application)
}
func initBuiltInCert() {
cert := getCert("admin", "cert-built-in")
if cert != nil {
return
}
cert = &Cert{
Owner: "admin",
Name: "cert-built-in",
CreatedTime: util.GetCurrentTime(),
DisplayName: "Built-in Cert",
Scope: "JWT",
Type: "x509",
CryptoAlgorithm: "RSA",
BitSize: 4096,
ExpireInYears: 20,
PublicKey: tokenJwtPublicKey,
PrivateKey: tokenJwtPrivateKey,
}
AddCert(cert)
}
func initBuiltInLdap() {
ldap := GetLdap("ldap-built-in")
if ldap != nil {

View File

@ -72,13 +72,15 @@ func GetOidcDiscovery() OidcDiscovery {
return oidcDiscovery
}
func GetJSONWebKeySet() (jose.JSONWebKeySet, error) {
func GetJsonWebKeySet() (jose.JSONWebKeySet, error) {
cert := GetDefaultCert()
//follows the protocol rfc 7517(draft)
//link here: https://self-issued.info/docs/draft-ietf-jose-json-web-key.html
//or https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key
certPEMBlock := []byte(tokenJwtPublicKey)
certDERBlock, _ := pem.Decode(certPEMBlock)
x509Cert, _ := x509.ParseCertificate(certDERBlock.Bytes)
certPemBlock := []byte(cert.PublicKey)
certDerBlock, _ := pem.Decode(certPemBlock)
x509Cert, _ := x509.ParseCertificate(certDerBlock.Bytes)
var jwk jose.JSONWebKey
jwk.Key = x509Cert.PublicKey

View File

@ -332,7 +332,9 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
Code: "",
}
}
claims, err := ParseJwtToken(refreshToken)
cert := getCertByApplication(application)
claims, err := ParseJwtToken(refreshToken, cert)
if err != nil {
return &Code{
Message: "error: invalid refresh_token",

View File

@ -23,12 +23,6 @@ import (
"github.com/golang-jwt/jwt/v4"
)
//go:embed token_jwt_key.pem
var tokenJwtPublicKey string
//go:embed token_jwt_key.key
var tokenJwtPrivateKey string
type Claims struct {
*User
Name string `json:"name,omitempty"`
@ -68,9 +62,10 @@ func generateJwtToken(application *Application, user *User, nonce string) (strin
claims.ExpiresAt = jwt.NewNumericDate(refreshExpireTime)
refreshToken := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
// Use "token_jwt_key.key" as RSA private key
privateKey := tokenJwtPrivateKey
key, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(privateKey))
cert := getCertByApplication(application)
// RSA private key
key, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(cert.PrivateKey))
if err != nil {
return "", "", err
}
@ -84,14 +79,14 @@ func generateJwtToken(application *Application, user *User, nonce string) (strin
return tokenString, refreshTokenString, err
}
func ParseJwtToken(token string) (*Claims, error) {
func ParseJwtToken(token string, cert *Cert) (*Claims, error) {
t, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
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))
// RSA public key
publicKey, err := jwt.ParseRSAPublicKeyFromPEM([]byte(cert.PublicKey))
if err != nil {
return nil, err
}

View File

@ -20,19 +20,14 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"time"
"github.com/casbin/casdoor/util"
)
func generateRsaKeys(fileId string) {
func generateRsaKeys(bitSize int, expireInYears int, commonName string, organization string) (string, 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 {
@ -50,12 +45,12 @@ func generateRsaKeys(fileId string) {
tml := x509.Certificate{
// you can add any attr that you need
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(20, 0, 0),
NotAfter: time.Now().AddDate(expireInYears, 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"},
CommonName: commonName,
Organization: []string{organization},
},
BasicConstraintsValid: true,
}
@ -70,9 +65,5 @@ func generateRsaKeys(fileId string) {
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))
return string(certPem), string(privateKeyPem)
}

View File

@ -14,9 +14,20 @@
package object
import "testing"
import (
"fmt"
"testing"
"github.com/casbin/casdoor/util"
)
func TestGenerateRsaKeys(t *testing.T) {
fileId := "token_jwt_key"
generateRsaKeys(fileId)
publicKey, privateKey := generateRsaKeys(4096, 20, "Casdoor Cert", "Casdoor Organization")
// Write certificate (aka public key) to file.
util.WriteStringToPath(publicKey, fmt.Sprintf("%s.pem", fileId))
// Write private key to file.
util.WriteStringToPath(privateKey, fmt.Sprintf("%s.key", fileId))
}