feat: add well-known jwks.json endpoint

This commit is contained in:
Lakhan Samani 2022-02-26 18:14:43 +05:30
parent ad46210112
commit 145091dce1
13 changed files with 156 additions and 58 deletions

View File

@ -20,8 +20,6 @@ const (
EnvKeyAuthorizerURL = "AUTHORIZER_URL" EnvKeyAuthorizerURL = "AUTHORIZER_URL"
// EnvKeyPort key for env variable PORT // EnvKeyPort key for env variable PORT
EnvKeyPort = "PORT" EnvKeyPort = "PORT"
// EnvKeyClientID key for env variable CLIENT_ID
EnvKeyClientID = "CLIENT_ID"
// EnvKeyAdminSecret key for env variable ADMIN_SECRET // EnvKeyAdminSecret key for env variable ADMIN_SECRET
EnvKeyAdminSecret = "ADMIN_SECRET" EnvKeyAdminSecret = "ADMIN_SECRET"
@ -95,8 +93,14 @@ const (
EnvKeyOrganizationName = "ORGANIZATION_NAME" EnvKeyOrganizationName = "ORGANIZATION_NAME"
// EnvKeyOrganizationLogo key for env variable ORGANIZATION_LOGO // EnvKeyOrganizationLogo key for env variable ORGANIZATION_LOGO
EnvKeyOrganizationLogo = "ORGANIZATION_LOGO" EnvKeyOrganizationLogo = "ORGANIZATION_LOGO"
// EnvKeyIsProd key for env variable IS_PROD
EnvKeyIsProd = "IS_PROD"
// EnvKeyCustomAccessTokenScript key for env variable CUSTOM_ACCESS_TOKEN_SCRIPT // EnvKeyCustomAccessTokenScript key for env variable CUSTOM_ACCESS_TOKEN_SCRIPT
EnvKeyCustomAccessTokenScript = "CUSTOM_ACCESS_TOKEN_SCRIPT" EnvKeyCustomAccessTokenScript = "CUSTOM_ACCESS_TOKEN_SCRIPT"
// Not Exposed Keys
// EnvKeyClientID key for env variable CLIENT_ID
EnvKeyClientID = "CLIENT_ID"
// EnvKeyJWK key for env variable JWK
EnvKeyJWK = "JWK"
// EnvKeyIsProd key for env variable IS_PROD
EnvKeyIsProd = "IS_PROD"
) )

29
server/crypto/common.go Normal file
View File

@ -0,0 +1,29 @@
package crypto
import (
"crypto/x509"
"gopkg.in/square/go-jose.v2"
)
// GetPubJWK returns JWK for given keys
func GetPubJWK(algo, keyID string, publicKey interface{}) (string, error) {
jwk := &jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
Algorithm: algo,
Key: publicKey,
Use: "sig",
KeyID: keyID,
Certificates: []*x509.Certificate{},
CertificateThumbprintSHA1: []uint8{},
CertificateThumbprintSHA256: []uint8{},
},
},
}
jwkPublicKey, err := jwk.Keys[0].MarshalJSON()
if err != nil {
return "", err
}
return string(jwkPublicKey), nil
}

View File

@ -10,18 +10,24 @@ import (
) )
// NewECDSAKey to generate new ECDSA Key if env is not set // NewECDSAKey to generate new ECDSA Key if env is not set
func NewECDSAKey() (*ecdsa.PrivateKey, string, string, error) { // returns key instance, private key string, public key string, jwk string, error
func NewECDSAKey(algo, keyID string) (*ecdsa.PrivateKey, string, string, string, error) {
key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
if err != nil { if err != nil {
return nil, "", "", err return nil, "", "", "", err
} }
privateKey, publicKey, err := AsECDSAStr(key, &key.PublicKey) privateKey, publicKey, err := AsECDSAStr(key, &key.PublicKey)
if err != nil { if err != nil {
return nil, "", "", err return nil, "", "", "", err
} }
return key, privateKey, publicKey, err jwkPublicKey, err := GetPubJWK(algo, keyID, &key.PublicKey)
if err != nil {
return nil, "", "", "", err
}
return key, privateKey, publicKey, string(jwkPublicKey), err
} }
// IsECDSA checks if given string is valid ECDSA algo // IsECDSA checks if given string is valid ECDSA algo

View File

@ -1,11 +1,18 @@
package crypto package crypto
import "github.com/google/uuid" import (
"github.com/google/uuid"
)
// NewHMAC key returns new key that can be used to ecnrypt data using HMAC algo // NewHMAC key returns new key that can be used to ecnrypt data using HMAC algo
func NewHMACKey() string { // returns key, string, error
func NewHMACKey(algo, keyID string) (string, string, error) {
key := uuid.New().String() key := uuid.New().String()
return key jwkPublicKey, err := GetPubJWK(algo, keyID, []byte(key))
if err != nil {
return "", "", err
}
return key, string(jwkPublicKey), nil
} }
// IsHMACValid checks if given string is valid HMCA algo // IsHMACValid checks if given string is valid HMCA algo

View File

@ -9,18 +9,24 @@ import (
) )
// NewRSAKey to generate new RSA Key if env is not set // NewRSAKey to generate new RSA Key if env is not set
func NewRSAKey() (*rsa.PrivateKey, string, string, error) { // returns key instance, private key string, public key string, jwk string, error
func NewRSAKey(algo, keyID string) (*rsa.PrivateKey, string, string, string, error) {
key, err := rsa.GenerateKey(rand.Reader, 2048) key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil { if err != nil {
return nil, "", "", err return nil, "", "", "", err
} }
privateKey, publicKey, err := AsRSAStr(key, &key.PublicKey) privateKey, publicKey, err := AsRSAStr(key, &key.PublicKey)
if err != nil { if err != nil {
return nil, "", "", err return nil, "", "", "", err
} }
return key, privateKey, publicKey, err jwkPublicKey, err := GetPubJWK(algo, keyID, &key.PublicKey)
if err != nil {
return nil, "", "", "", err
}
return key, privateKey, publicKey, string(jwkPublicKey), err
} }
// IsRSA checks if given string is valid RSA algo // IsRSA checks if given string is valid RSA algo
@ -46,11 +52,8 @@ func ExportRsaPrivateKeyAsPemStr(privkey *rsa.PrivateKey) string {
} }
// ExportRsaPublicKeyAsPemStr to get RSA public key as pem string // ExportRsaPublicKeyAsPemStr to get RSA public key as pem string
func ExportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) (string, error) { func ExportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) string {
pubkeyBytes, err := x509.MarshalPKIXPublicKey(pubkey) pubkeyBytes := x509.MarshalPKCS1PublicKey(pubkey)
if err != nil {
return "", err
}
pubkeyPem := pem.EncodeToMemory( pubkeyPem := pem.EncodeToMemory(
&pem.Block{ &pem.Block{
Type: "RSA PUBLIC KEY", Type: "RSA PUBLIC KEY",
@ -58,7 +61,7 @@ func ExportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) (string, error) {
}, },
) )
return string(pubkeyPem), nil return string(pubkeyPem)
} }
// ParseRsaPrivateKeyFromPemStr to parse RSA private key from pem string // ParseRsaPrivateKeyFromPemStr to parse RSA private key from pem string
@ -83,28 +86,19 @@ func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) {
return nil, errors.New("failed to parse PEM block containing the key") return nil, errors.New("failed to parse PEM block containing the key")
} }
pub, err := x509.ParsePKIXPublicKey(block.Bytes) pub, err := x509.ParsePKCS1PublicKey(block.Bytes)
if err != nil { if err != nil {
return nil, err return nil, err
} }
switch pub := pub.(type) {
case *rsa.PublicKey:
return pub, nil return pub, nil
default:
break // fall through
}
return nil, errors.New("Key type is not RSA")
} }
// AsRSAStr returns private, public key string or error // AsRSAStr returns private, public key string or error
func AsRSAStr(privateKey *rsa.PrivateKey, publickKey *rsa.PublicKey) (string, string, error) { func AsRSAStr(privateKey *rsa.PrivateKey, publickKey *rsa.PublicKey) (string, string, error) {
// Export the keys to pem string // Export the keys to pem string
privPem := ExportRsaPrivateKeyAsPemStr(privateKey) privPem := ExportRsaPrivateKeyAsPemStr(privateKey)
pubPem, err := ExportRsaPublicKeyAsPemStr(publickKey) pubPem := ExportRsaPublicKeyAsPemStr(publickKey)
if err != nil {
return "", "", err
}
// Import the keys from pem string // Import the keys from pem string
privParsed, err := ParseRsaPrivateKeyFromPemStr(privPem) privParsed, err := ParseRsaPrivateKeyFromPemStr(privPem)
@ -118,10 +112,7 @@ func AsRSAStr(privateKey *rsa.PrivateKey, publickKey *rsa.PublicKey) (string, st
// Export the newly imported keys // Export the newly imported keys
privParsedPem := ExportRsaPrivateKeyAsPemStr(privParsed) privParsedPem := ExportRsaPrivateKeyAsPemStr(privParsed)
pubParsedPem, err := ExportRsaPublicKeyAsPemStr(pubParsed) pubParsedPem := ExportRsaPublicKeyAsPemStr(pubParsed)
if err != nil {
return "", "", err
}
return privParsedPem, pubParsedPem, nil return privParsedPem, pubParsedPem, nil
} }

45
server/env/env.go vendored
View File

@ -11,6 +11,7 @@ import (
"github.com/authorizerdev/authorizer/server/envstore" "github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/utils" "github.com/authorizerdev/authorizer/server/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/joho/godotenv" "github.com/joho/godotenv"
) )
@ -77,6 +78,13 @@ func InitAllEnv() error {
envData = envstore.EnvInMemoryStoreObj.GetEnvStoreClone() envData = envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
} }
clientID := envData.StringEnv[constants.EnvKeyClientID]
// unique client id for each instance
if clientID == "" {
clientID = uuid.New().String()
envData.StringEnv[constants.EnvKeyClientID] = clientID
}
if envData.StringEnv[constants.EnvKeyEnv] == "" { if envData.StringEnv[constants.EnvKeyEnv] == "" {
envData.StringEnv[constants.EnvKeyEnv] = os.Getenv(constants.EnvKeyEnv) envData.StringEnv[constants.EnvKeyEnv] = os.Getenv(constants.EnvKeyEnv)
if envData.StringEnv[constants.EnvKeyEnv] == "" { if envData.StringEnv[constants.EnvKeyEnv] == "" {
@ -126,8 +134,8 @@ func InitAllEnv() error {
envData.StringEnv[constants.EnvKeySenderEmail] = os.Getenv(constants.EnvKeySenderEmail) envData.StringEnv[constants.EnvKeySenderEmail] = os.Getenv(constants.EnvKeySenderEmail)
} }
algo := "" algo := envData.StringEnv[constants.EnvKeyJwtType]
if envData.StringEnv[constants.EnvKeyJwtType] == "" { if algo == "" {
envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv(constants.EnvKeyJwtType) envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv(constants.EnvKeyJwtType)
if envData.StringEnv[constants.EnvKeyJwtType] == "" { if envData.StringEnv[constants.EnvKeyJwtType] == "" {
envData.StringEnv[constants.EnvKeyJwtType] = "RS256" envData.StringEnv[constants.EnvKeyJwtType] = "RS256"
@ -143,12 +151,21 @@ func InitAllEnv() error {
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" && crypto.IsHMACA(algo) { if envData.StringEnv[constants.EnvKeyJwtSecret] == "" && crypto.IsHMACA(algo) {
envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv(constants.EnvKeyJwtSecret) envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv(constants.EnvKeyJwtSecret)
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" { if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
envData.StringEnv[constants.EnvKeyJwtSecret] = crypto.NewHMACKey() envData.StringEnv[constants.EnvKeyJwtSecret], envData.StringEnv[constants.EnvKeyJWK], err = crypto.NewHMACKey(algo, clientID)
if err != nil {
return err
}
} else {
envData.StringEnv[constants.EnvKeyJWK], err = crypto.GetPubJWK(algo, clientID, []byte(envData.StringEnv[constants.EnvKeyJwtSecret]))
if err != nil {
return err
}
} }
} }
if crypto.IsRSA(algo) || crypto.IsECDSA(algo) { if crypto.IsRSA(algo) || crypto.IsECDSA(algo) {
privateKey, publicKey := "", "" privateKey, publicKey, jwk := "", "", ""
if envData.StringEnv[constants.EnvKeyJwtPrivateKey] == "" { if envData.StringEnv[constants.EnvKeyJwtPrivateKey] == "" {
privateKey = os.Getenv(constants.EnvKeyJwtPrivateKey) privateKey = os.Getenv(constants.EnvKeyJwtPrivateKey)
@ -162,12 +179,12 @@ func InitAllEnv() error {
// if either of them is not present generate new keys // if either of them is not present generate new keys
if privateKey == "" || publicKey == "" { if privateKey == "" || publicKey == "" {
if crypto.IsRSA(algo) { if crypto.IsRSA(algo) {
_, privateKey, publicKey, err = crypto.NewRSAKey() _, privateKey, publicKey, jwk, err = crypto.NewRSAKey(algo, clientID)
if err != nil { if err != nil {
return err return err
} }
} else if crypto.IsECDSA(algo) { } else if crypto.IsECDSA(algo) {
_, privateKey, publicKey, err = crypto.NewECDSAKey() _, privateKey, publicKey, jwk, err = crypto.NewECDSAKey(algo, clientID)
if err != nil { if err != nil {
return err return err
} }
@ -180,7 +197,12 @@ func InitAllEnv() error {
return err return err
} }
_, err = crypto.ParseRsaPublicKeyFromPemStr(publicKey) publicKeyInstance, err := crypto.ParseRsaPublicKeyFromPemStr(publicKey)
if err != nil {
return err
}
jwk, err = crypto.GetPubJWK(algo, clientID, publicKeyInstance)
if err != nil { if err != nil {
return err return err
} }
@ -190,15 +212,22 @@ func InitAllEnv() error {
return err return err
} }
_, err = crypto.ParseEcdsaPublicKeyFromPemStr(publicKey) publicKeyInstance, err := crypto.ParseEcdsaPublicKeyFromPemStr(publicKey)
if err != nil {
return err
}
jwk, err = crypto.GetPubJWK(algo, clientID, publicKeyInstance)
if err != nil { if err != nil {
return err return err
} }
} }
} }
envData.StringEnv[constants.EnvKeyJWK] = jwk
envData.StringEnv[constants.EnvKeyJwtPrivateKey] = privateKey envData.StringEnv[constants.EnvKeyJwtPrivateKey] = privateKey
envData.StringEnv[constants.EnvKeyJwtPublicKey] = publicKey envData.StringEnv[constants.EnvKeyJwtPublicKey] = publicKey
} }
if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" { if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" {

View File

@ -178,9 +178,5 @@ func PersistEnv() error {
} }
} }
// ID of env is used to identify the config and declared as client id
// this client id can be used in `aud` section of JWT token
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyClientID, env.ID)
return nil return nil
} }

View File

@ -30,6 +30,7 @@ require (
google.golang.org/protobuf v1.27.1 // indirect google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/mail.v2 v2.3.1 gopkg.in/mail.v2 v2.3.1
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gorm.io/driver/mysql v1.2.1 gorm.io/driver/mysql v1.2.1
gorm.io/driver/postgres v1.2.3 gorm.io/driver/postgres v1.2.3

View File

@ -69,6 +69,9 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4= github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d h1:1iy2qD6JEhHKKhUOA9IWs7mjco7lnw2qx8FsRI2wirE=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL/7ND8HI= github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL/7ND8HI=
github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
@ -106,6 +109,8 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/goccy/go-json v0.9.4 h1:L8MLKG2mvVXiQu07qB6hmfqeSYQdOnqPot2GhsIwIaI=
github.com/goccy/go-json v0.9.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@ -256,6 +261,18 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4=
github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc=
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
github.com/lestrrat-go/iter v1.0.1 h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A=
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
github.com/lestrrat-go/jwx v1.2.19 h1:qxxLmAXNwZpTTvjc4PH21nT7I4wPK6lVv3lVNcZPnUk=
github.com/lestrrat-go/jwx v1.2.19/go.mod h1:bWTBO7IHHVMtNunM8so9MT8wD+euEY1PzGEyCnuI2qM=
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@ -386,6 +403,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
@ -684,6 +702,8 @@ gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

21
server/handlers/jwks.go Normal file
View File

@ -0,0 +1,21 @@
package handlers
import (
"encoding/json"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/gin-gonic/gin"
)
func JWKsHandler() gin.HandlerFunc {
var data map[string]string
json.Unmarshal([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJWK)), &data)
return func(c *gin.Context) {
c.JSON(200, gin.H{
"keys": []map[string]string{
data,
},
})
}
}

View File

@ -1,8 +1,6 @@
package handlers package handlers
import ( import (
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
@ -13,11 +11,6 @@ import (
// OpenIDConfigurationHandler handler for open-id configurations // OpenIDConfigurationHandler handler for open-id configurations
func OpenIDConfigurationHandler() gin.HandlerFunc { func OpenIDConfigurationHandler() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
if strings.Contains(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType), "HS") {
c.JSON(400, gin.H{"error": "openid not supported for HSA algorithm"})
return
}
issuer := utils.GetHost(c) issuer := utils.GetHost(c)
jwtType := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType) jwtType := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
@ -26,7 +19,7 @@ func OpenIDConfigurationHandler() gin.HandlerFunc {
"authorization_endpoint": issuer + "/authorize", "authorization_endpoint": issuer + "/authorize",
"token_endpoint": issuer + "/oauth/token", "token_endpoint": issuer + "/oauth/token",
"userinfo_endpoint": issuer + "/userinfo", "userinfo_endpoint": issuer + "/userinfo",
"jwks_uri": issuer + "/jwks.json", "jwks_uri": issuer + "/.well-known/jwks.json",
"response_types_supported": []string{"code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token"}, "response_types_supported": []string{"code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token"},
"scopes_supported": []string{"openid", "email", "profile", "email_verified", "given_name", "family_name", "nick_name", "picture"}, "scopes_supported": []string{"openid", "email", "profile", "email_verified", "given_name", "family_name", "nick_name", "picture"},
"response_modes_supported": []string{"query", "fragment", "form_post"}, "response_modes_supported": []string{"query", "fragment", "form_post"},

View File

@ -22,6 +22,7 @@ func InitRouter() *gin.Engine {
router.GET("/verify_email", handlers.VerifyEmailHandler()) router.GET("/verify_email", handlers.VerifyEmailHandler())
// OPEN ID routes // OPEN ID routes
router.GET("/.well-known/openid-configuration", handlers.OpenIDConfigurationHandler()) router.GET("/.well-known/openid-configuration", handlers.OpenIDConfigurationHandler())
router.GET("/.well-known/jwks.json", handlers.JWKsHandler())
router.LoadHTMLGlob("templates/*") router.LoadHTMLGlob("templates/*")
// login page app related routes. // login page app related routes.

View File

@ -98,7 +98,7 @@ func CreateAccessToken(user models.User, roles []string) (string, int64, error)
claimKey := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtRoleClaim) claimKey := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtRoleClaim)
customClaims := jwt.MapClaims{ customClaims := jwt.MapClaims{
"iss": "", "iss": "",
"aud": "", "aud": envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID),
"nonce": "", "nonce": "",
"sub": user.ID, "sub": user.ID,
"exp": expiresAt, "exp": expiresAt,