1
0
Fork 0
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:
Knut Ahlers 2019-04-21 19:36:28 +02:00
parent 8d968ce29d
commit 282a95c2e9
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
6 changed files with 48 additions and 39 deletions

11
core.go
View file

@ -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
View file

@ -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",
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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]
}
}