mirror of
https://github.com/Luzifer/nginx-sso.git
synced 2024-12-20 04:41:17 +00:00
Move MFA plugins to own modules
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
8d968ce29d
commit
282a95c2e9
6 changed files with 48 additions and 39 deletions
11
core.go
11
core.go
|
@ -1,7 +1,16 @@
|
|||
package main
|
||||
|
||||
import "github.com/Luzifer/nginx-sso/plugins/auth/google"
|
||||
import (
|
||||
"github.com/Luzifer/nginx-sso/plugins/auth/google"
|
||||
"github.com/Luzifer/nginx-sso/plugins/mfa/duo"
|
||||
"github.com/Luzifer/nginx-sso/plugins/mfa/totp"
|
||||
mfa_yubikey "github.com/Luzifer/nginx-sso/plugins/mfa/yubikey"
|
||||
)
|
||||
|
||||
func registerModules() {
|
||||
registerAuthenticator(google.New(cookieStore))
|
||||
|
||||
registerMFAProvider(duo.New())
|
||||
registerMFAProvider(totp.New())
|
||||
registerMFAProvider(mfa_yubikey.New())
|
||||
}
|
||||
|
|
4
mfa.go
4
mfa.go
|
@ -10,11 +10,9 @@ import (
|
|||
"github.com/Luzifer/nginx-sso/plugins"
|
||||
)
|
||||
|
||||
const mfaLoginFieldName = "mfa-token"
|
||||
|
||||
var mfaLoginField = plugins.LoginField{
|
||||
Label: "MFA Token",
|
||||
Name: mfaLoginFieldName,
|
||||
Name: plugins.MFALoginFieldName,
|
||||
Placeholder: "(optional)",
|
||||
Type: "text",
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package plugins
|
|||
|
||||
import "net/http"
|
||||
|
||||
const MFALoginFieldName = "mfa-token"
|
||||
|
||||
type MFAProvider interface {
|
||||
// ProviderID needs to return an unique string to identify
|
||||
// this special MFA provider
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package duo
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
@ -21,29 +21,29 @@ const (
|
|||
|
||||
var mfaDuoTrustedIPHeaders = []string{"X-Forwarded-For", "X-Real-IP"}
|
||||
|
||||
func init() {
|
||||
registerMFAProvider(&mfaDuo{})
|
||||
}
|
||||
|
||||
type mfaDuo struct {
|
||||
type MFADuo struct {
|
||||
IKey string `yaml:"ikey"`
|
||||
SKey string `yaml:"skey"`
|
||||
Host string `yaml:"host"`
|
||||
UserAgent string `yaml:"user_agent"`
|
||||
}
|
||||
|
||||
func New() *MFADuo {
|
||||
return &MFADuo{}
|
||||
}
|
||||
|
||||
// ProviderID needs to return an unique string to identify
|
||||
// this special MFA provider
|
||||
func (m mfaDuo) ProviderID() (id string) { return "duo" }
|
||||
func (m MFADuo) ProviderID() (id string) { return "duo" }
|
||||
|
||||
// Configure loads the configuration for the Authenticator from the
|
||||
// global config.yaml file which is passed as a byte-slice.
|
||||
// If no configuration for the Authenticator is supplied the function
|
||||
// needs to return the plugins.ErrProviderUnconfigured
|
||||
func (m *mfaDuo) Configure(yamlSource []byte) (err error) {
|
||||
func (m *MFADuo) Configure(yamlSource []byte) (err error) {
|
||||
envelope := struct {
|
||||
MFA struct {
|
||||
Duo *mfaDuo `yaml:"duo"`
|
||||
Duo *MFADuo `yaml:"duo"`
|
||||
} `yaml:"mfa"`
|
||||
}{}
|
||||
|
||||
|
@ -64,7 +64,7 @@ func (m *mfaDuo) Configure(yamlSource []byte) (err error) {
|
|||
|
||||
// ValidateMFA takes the user from the login cookie and performs a
|
||||
// validation against the provided MFA configuration for this user
|
||||
func (m mfaDuo) ValidateMFA(res http.ResponseWriter, r *http.Request, user string, mfaCfgs []plugins.MFAConfig) error {
|
||||
func (m MFADuo) ValidateMFA(res http.ResponseWriter, r *http.Request, user string, mfaCfgs []plugins.MFAConfig) error {
|
||||
var keyInput string
|
||||
|
||||
// Look for mfaConfigs with own provider name
|
||||
|
@ -81,7 +81,7 @@ func (m mfaDuo) ValidateMFA(res http.ResponseWriter, r *http.Request, user strin
|
|||
duo := authapi.NewAuthApi(*duoapi.NewDuoApi(m.IKey, m.SKey, m.Host, m.UserAgent, duoapi.SetTimeout(mfaDuoRequestTimeout)))
|
||||
|
||||
for key, values := range r.Form {
|
||||
if strings.HasSuffix(key, mfaLoginFieldName) && len(values[0]) > 0 {
|
||||
if strings.HasSuffix(key, plugins.MFALoginFieldName) && len(values[0]) > 0 {
|
||||
keyInput = values[0]
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ func (m mfaDuo) ValidateMFA(res http.ResponseWriter, r *http.Request, user strin
|
|||
return plugins.ErrNoValidUserFound
|
||||
}
|
||||
|
||||
func (m mfaDuo) findIP(r *http.Request) (string, error) {
|
||||
func (m MFADuo) findIP(r *http.Request) (string, error) {
|
||||
for _, hdr := range mfaDuoTrustedIPHeaders {
|
||||
if value := r.Header.Get(hdr); value != "" {
|
||||
return m.parseIP(value)
|
||||
|
@ -118,7 +118,7 @@ func (m mfaDuo) findIP(r *http.Request) (string, error) {
|
|||
return m.parseIP(r.RemoteAddr)
|
||||
}
|
||||
|
||||
func (m mfaDuo) parseIP(s string) (string, error) {
|
||||
func (m MFADuo) parseIP(s string) (string, error) {
|
||||
ip, _, err := net.SplitHostPort(s)
|
||||
if err == nil {
|
||||
return ip, nil
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package totp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
@ -12,27 +12,27 @@ import (
|
|||
"github.com/Luzifer/nginx-sso/plugins"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerMFAProvider(&mfaTOTP{})
|
||||
}
|
||||
|
||||
type mfaTOTP struct{}
|
||||
type MFATOTP struct{}
|
||||
|
||||
// ProviderID needs to return an unique string to identify
|
||||
// this special MFA provider
|
||||
func (m mfaTOTP) ProviderID() (id string) {
|
||||
func (m MFATOTP) ProviderID() (id string) {
|
||||
return "totp"
|
||||
}
|
||||
|
||||
func New() *MFATOTP {
|
||||
return &MFATOTP{}
|
||||
}
|
||||
|
||||
// Configure loads the configuration for the Authenticator from the
|
||||
// global config.yaml file which is passed as a byte-slice.
|
||||
// If no configuration for the Authenticator is supplied the function
|
||||
// needs to return the plugins.ErrProviderUnconfigured
|
||||
func (m mfaTOTP) Configure(yamlSource []byte) (err error) { return nil }
|
||||
func (m MFATOTP) Configure(yamlSource []byte) (err error) { return nil }
|
||||
|
||||
// ValidateMFA takes the user from the login cookie and performs a
|
||||
// validation against the provided MFA configuration for this user
|
||||
func (m mfaTOTP) ValidateMFA(res http.ResponseWriter, r *http.Request, user string, mfaCfgs []plugins.MFAConfig) error {
|
||||
func (m MFATOTP) ValidateMFA(res http.ResponseWriter, r *http.Request, user string, mfaCfgs []plugins.MFAConfig) error {
|
||||
// Look for mfaConfigs with own provider name
|
||||
for _, c := range mfaCfgs {
|
||||
// Provider has been renamed, keep "google" for backwards compatibility
|
||||
|
@ -46,7 +46,7 @@ func (m mfaTOTP) ValidateMFA(res http.ResponseWriter, r *http.Request, user stri
|
|||
}
|
||||
|
||||
for key, values := range r.Form {
|
||||
if strings.HasSuffix(key, mfaLoginFieldName) && values[0] == token {
|
||||
if strings.HasSuffix(key, plugins.MFALoginFieldName) && values[0] == token {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ func (m mfaTOTP) ValidateMFA(res http.ResponseWriter, r *http.Request, user stri
|
|||
return plugins.ErrNoValidUserFound
|
||||
}
|
||||
|
||||
func (m mfaTOTP) exec(c plugins.MFAConfig) (string, error) {
|
||||
func (m MFATOTP) exec(c plugins.MFAConfig) (string, error) {
|
||||
secret := c.AttributeString("secret")
|
||||
|
||||
// By default use Google Authenticator compatible settings
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package yubikey
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
@ -11,27 +11,27 @@ import (
|
|||
"github.com/Luzifer/nginx-sso/plugins"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerMFAProvider(&mfaYubikey{})
|
||||
}
|
||||
|
||||
type mfaYubikey struct {
|
||||
type MFAYubikey struct {
|
||||
ClientID string `yaml:"client_id"`
|
||||
SecretKey string `yaml:"secret_key"`
|
||||
}
|
||||
|
||||
func New() *MFAYubikey {
|
||||
return &MFAYubikey{}
|
||||
}
|
||||
|
||||
// ProviderID needs to return an unique string to identify
|
||||
// this special MFA provider
|
||||
func (m mfaYubikey) ProviderID() (id string) { return "yubikey" }
|
||||
func (m MFAYubikey) ProviderID() (id string) { return "yubikey" }
|
||||
|
||||
// Configure loads the configuration for the Authenticator from the
|
||||
// global config.yaml file which is passed as a byte-slice.
|
||||
// If no configuration for the Authenticator is supplied the function
|
||||
// needs to return the plugins.ErrProviderUnconfigured
|
||||
func (m *mfaYubikey) Configure(yamlSource []byte) (err error) {
|
||||
func (m *MFAYubikey) Configure(yamlSource []byte) (err error) {
|
||||
envelope := struct {
|
||||
MFA struct {
|
||||
Yubikey *mfaYubikey `yaml:"yubikey"`
|
||||
Yubikey *MFAYubikey `yaml:"yubikey"`
|
||||
} `yaml:"mfa"`
|
||||
}{}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func (m *mfaYubikey) Configure(yamlSource []byte) (err error) {
|
|||
|
||||
// ValidateMFA takes the user from the login cookie and performs a
|
||||
// validation against the provided MFA configuration for this user
|
||||
func (m mfaYubikey) ValidateMFA(res http.ResponseWriter, r *http.Request, user string, mfaCfgs []plugins.MFAConfig) error {
|
||||
func (m MFAYubikey) ValidateMFA(res http.ResponseWriter, r *http.Request, user string, mfaCfgs []plugins.MFAConfig) error {
|
||||
var keyInput string
|
||||
|
||||
yubiAuth, err := yubigo.NewYubiAuth(m.ClientID, m.SecretKey)
|
||||
|
@ -65,7 +65,7 @@ func (m mfaYubikey) ValidateMFA(res http.ResponseWriter, r *http.Request, user s
|
|||
}
|
||||
|
||||
for key, values := range r.Form {
|
||||
if strings.HasSuffix(key, mfaLoginFieldName) && strings.HasPrefix(values[0], c.AttributeString("device")) {
|
||||
if strings.HasSuffix(key, plugins.MFALoginFieldName) && strings.HasPrefix(values[0], c.AttributeString("device")) {
|
||||
keyInput = values[0]
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue