3
0

Add ValidConfiguration and test for external auth provider

This commit is contained in:
Andre Perry 2021-07-24 05:43:19 +10:00 committed by Denis Arh
parent 9d272d5bda
commit 6977ade5df
6 changed files with 109 additions and 87 deletions

View File

@ -7,7 +7,6 @@ import (
"strings"
authService "github.com/cortezaproject/corteza-server/auth"
"github.com/cortezaproject/corteza-server/auth/external"
authHandlers "github.com/cortezaproject/corteza-server/auth/handlers"
"github.com/cortezaproject/corteza-server/auth/saml"
authSettings "github.com/cortezaproject/corteza-server/auth/settings"
@ -517,51 +516,37 @@ func (app *CortezaApp) initSystemEntities(ctx context.Context) (err error) {
}
func updateAuthSettings(svc authServicer, current *types.AppSettings) {
var (
// current auth settings
cas = current.Auth
providers []authSettings.Provider
)
for _, p := range cas.External.Providers {
if !p.Enabled || p.Handle == "" || p.Key == "" || p.Secret == "" {
continue
}
if strings.HasPrefix(p.Handle, external.OIDC_PROVIDER_PREFIX) {
if p.IssuerUrl == "" {
// OIDC IdPs need to have issuer URL
continue
}
} else {
// non-OIDC provider do not need issuer URL
p.IssuerUrl = ""
}
providers = append(providers, authSettings.Provider{
Handle: p.Handle,
Label: p.Label,
IssuerUrl: p.IssuerUrl,
Key: p.Key,
RedirectUrl: p.RedirectUrl,
Secret: p.Secret,
})
}
as := &authSettings.Settings{
LocalEnabled: cas.Internal.Enabled,
SignupEnabled: cas.Internal.Signup.Enabled,
EmailConfirmationRequired: cas.Internal.Signup.EmailConfirmationRequired,
PasswordResetEnabled: cas.Internal.PasswordReset.Enabled,
ExternalEnabled: cas.External.Enabled,
Providers: providers,
LocalEnabled: current.Auth.Internal.Enabled,
SignupEnabled: current.Auth.Internal.Signup.Enabled,
EmailConfirmationRequired: current.Auth.Internal.Signup.EmailConfirmationRequired,
PasswordResetEnabled: current.Auth.Internal.PasswordReset.Enabled,
ExternalEnabled: current.Auth.External.Enabled,
MultiFactor: authSettings.MultiFactor{
TOTP: authSettings.TOTP{
Enabled: current.Auth.MultiFactor.TOTP.Enabled,
Enforced: current.Auth.MultiFactor.TOTP.Enforced,
Issuer: current.Auth.MultiFactor.TOTP.Issuer,
},
EmailOTP: authSettings.EmailOTP{
Enabled: current.Auth.MultiFactor.EmailOTP.Enabled,
Enforced: current.Auth.MultiFactor.EmailOTP.Enforced,
},
},
}
as.MultiFactor.TOTP.Enabled = cas.MultiFactor.TOTP.Enabled
as.MultiFactor.TOTP.Enforced = cas.MultiFactor.TOTP.Enforced
as.MultiFactor.TOTP.Issuer = cas.MultiFactor.TOTP.Issuer
as.MultiFactor.EmailOTP.Enabled = cas.MultiFactor.EmailOTP.Enabled
as.MultiFactor.EmailOTP.Enforced = cas.MultiFactor.EmailOTP.Enforced
for _, p := range current.Auth.External.Providers {
if p.ValidConfiguration() {
as.Providers = append(as.Providers, authSettings.Provider{
Handle: p.Handle,
Label: p.Label,
IssuerUrl: p.IssuerUrl,
Key: p.Key,
RedirectUrl: p.RedirectUrl,
Secret: p.Secret,
})
}
}
// SAML
saml.UpdateSettings(current, as)

View File

@ -70,11 +70,10 @@ func Test_updateAuthSettings(t *testing.T) {
Secret: "sec",
},
{ // add (w/o issuer)
Enabled: true,
Handle: "google",
IssuerUrl: "issuer",
Key: "key",
Secret: "sec",
Enabled: true,
Handle: "google",
Key: "key",
Secret: "sec",
},
{ // add
Enabled: true,

View File

@ -6,7 +6,8 @@ import (
)
const (
OIDC_PROVIDER_PREFIX = "openid-connect."
OIDC_PROVIDER_PREFIX = "openid-connect." // must match const in "github.com/cortezaproject/corteza-server/system/types" app_settings.go
)
func Init(store sessions.Store) {

View File

@ -8,48 +8,53 @@ type (
PasswordResetEnabled bool
ExternalEnabled bool
Providers []Provider
Saml SAML
MultiFactor MultiFactor
}
Saml struct {
Enabled bool
SAML struct {
Enabled bool
// SAML certificate
Cert string
// SAML certificate
Cert string
// SAML certificate private key
Key string
// SAML certificate private key
Key string
// Identity provider hostname
IDP struct {
URL string
Name string
// Identity provider hostname
IDP struct {
URL string
Name string
// identifier payload from idp
IdentName string
IdentHandle string
IdentIdentifier string
}
// identifier payload from idp
IdentName string
IdentHandle string
IdentIdentifier string
}
}
MultiFactor struct {
EmailOTP struct {
// Can users use email for MFA
Enabled bool
MultiFactor struct {
EmailOTP EmailOTP
TOTP TOTP
}
// Is MFA with email enforced?
Enforced bool
}
EmailOTP struct {
// Can users use email for MFA
Enabled bool
TOTP struct {
// Can users use TOTP MFA?
Enabled bool
// Is MFA with email enforced?
Enforced bool
}
// Is TOTP MFA enforced?
Enforced bool
TOTP struct {
// Can users use TOTP MFA?
Enabled bool
// TOTP issuer
Issuer string
}
}
// Is TOTP MFA enforced?
Enforced bool
// TOTP issuer
Issuer string
}
Provider struct {

View File

@ -5,6 +5,10 @@ import (
"strings"
)
const (
oidcProviderPrefix = "openid-connect." // must match const in "github.com/cortezaproject/corteza-server/auth/external" external.go
)
type (
// AppSettings type is structured representation of all application settings
//
@ -157,6 +161,19 @@ type (
}
)
func (set *ExternalAuthProvider) ValidConfiguration() bool {
if !set.Enabled || set.Handle == "" || set.Key == "" || set.Secret == "" {
return false
}
if strings.HasPrefix(set.Handle, oidcProviderPrefix) && set.IssuerUrl == "" {
// OIDC IdPs need to have issuer URL
return false
}
return true
}
// DecodeKV translates settings' KV into internal system external auth settings
func (set *ExternalAuthProviderSet) DecodeKV(kv SettingsKV, prefix string) (err error) {
if *set == nil {
@ -170,13 +187,12 @@ func (set *ExternalAuthProviderSet) DecodeKV(kv SettingsKV, prefix string) (err
kv = kv.CutPrefix(prefix + ".")
// add all additional providers (prefixed with "openid-connect.")
oidcPrefix := "openid-connect."
for p := range kv {
if !strings.HasPrefix(p, oidcPrefix) {
if !strings.HasPrefix(p, oidcProviderPrefix) {
continue
}
l := len(oidcPrefix)
l := len(oidcProviderPrefix)
dotPos := strings.Index(p[l:], ".") + l
if dotPos > 0 {
providers[p[:dotPos]] = true
@ -207,8 +223,8 @@ func (set *ExternalAuthProviderSet) DecodeKV(kv SettingsKV, prefix string) (err
case "crust-iam", "crust", "crust-unify":
p.Label = "Crust IAM"
default:
if strings.HasPrefix(p.Handle, oidcPrefix) {
p.Label = strings.Title(p.Handle[len(oidcPrefix):])
if strings.HasPrefix(p.Handle, oidcProviderPrefix) {
p.Label = strings.Title(p.Handle[len(oidcProviderPrefix):])
} else {
p.Label = strings.Title(p.Handle)
}

View File

@ -1,14 +1,30 @@
package types
import (
sqlTypes "github.com/jmoiron/sqlx/types"
"github.com/stretchr/testify/require"
"sort"
"testing"
sqlTypes "github.com/jmoiron/sqlx/types"
"github.com/stretchr/testify/require"
)
// Hello! This file is auto-generated.
func Test_settingsExtAuthProvidersValidConfiguration(t *testing.T) {
var (
empty = ExternalAuthProvider{}
google = ExternalAuthProvider{Enabled: true, Handle: "google", Key: "some-guid", Secret: "s3cret"}
noIssuerOIDC = ExternalAuthProvider{Enabled: true, Handle: "openid-connect.bar", Key: "some-guid", Secret: "s3cret"}
goodOIDC = ExternalAuthProvider{Enabled: true, Handle: "openid-connect.bar", Key: "some-guid", Secret: "s3cret", IssuerUrl: "https://example.org"}
)
require.False(t, noIssuerOIDC.ValidConfiguration())
require.True(t, goodOIDC.ValidConfiguration())
require.False(t, empty.ValidConfiguration())
require.True(t, google.ValidConfiguration())
}
func Test_settingsExtAuthProvidersDecode(t *testing.T) {
type (
Dst struct {