1
0
Fork 0
mirror of https://github.com/Luzifer/nginx-sso.git synced 2024-12-20 04:41:17 +00:00

Export errors for usage in plugins

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2019-02-22 00:27:02 +01:00
parent 83fcc4d0fe
commit e9bff08810
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
14 changed files with 72 additions and 67 deletions

View file

@ -30,7 +30,7 @@ func (a authCrowd) AuthenticatorID() string { return "crowd" }
// Configure loads the configuration for the Authenticator from the // Configure loads the configuration for the Authenticator from the
// global config.yaml file which is passed as a byte-slice. // global config.yaml file which is passed as a byte-slice.
// If no configuration for the Authenticator is supplied the function // If no configuration for the Authenticator is supplied the function
// needs to return the errProviderUnconfigured // needs to return the plugins.ErrProviderUnconfigured
func (a *authCrowd) Configure(yamlSource []byte) error { func (a *authCrowd) Configure(yamlSource []byte) error {
envelope := struct { envelope := struct {
Providers struct { Providers struct {
@ -43,7 +43,7 @@ func (a *authCrowd) Configure(yamlSource []byte) error {
} }
if envelope.Providers.Crowd == nil { if envelope.Providers.Crowd == nil {
return errProviderUnconfigured return plugins.ErrProviderUnconfigured
} }
a.URL = envelope.Providers.Crowd.URL a.URL = envelope.Providers.Crowd.URL
@ -51,7 +51,7 @@ func (a *authCrowd) Configure(yamlSource []byte) error {
a.AppPassword = envelope.Providers.Crowd.AppPassword a.AppPassword = envelope.Providers.Crowd.AppPassword
if a.AppName == "" || a.AppPassword == "" { if a.AppName == "" || a.AppPassword == "" {
return errProviderUnconfigured return plugins.ErrProviderUnconfigured
} }
var err error var err error
@ -62,7 +62,7 @@ func (a *authCrowd) Configure(yamlSource []byte) error {
// DetectUser is used to detect a user without a login form from // DetectUser is used to detect a user without a login form from
// a cookie, header or other methods // a cookie, header or other methods
// If no user was detected the errNoValidUserFound needs to be // If no user was detected the plugins.ErrNoValidUserFound needs to be
// returned // returned
func (a authCrowd) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) { func (a authCrowd) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) {
cc, err := a.crowd.GetCookieConfig() cc, err := a.crowd.GetCookieConfig()
@ -76,7 +76,7 @@ func (a authCrowd) DetectUser(res http.ResponseWriter, r *http.Request) (string,
// Fine, we do have a cookie // Fine, we do have a cookie
case http.ErrNoCookie: case http.ErrNoCookie:
// Also fine, there is no cookie // Also fine, there is no cookie
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
default: default:
return "", nil, err return "", nil, err
} }
@ -85,7 +85,7 @@ func (a authCrowd) DetectUser(res http.ResponseWriter, r *http.Request) (string,
sess, err := a.crowd.GetSession(ssoToken) sess, err := a.crowd.GetSession(ssoToken)
if err != nil { if err != nil {
log.WithError(err).Debug("Getting crowd session failed") log.WithError(err).Debug("Getting crowd session failed")
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
user := sess.User.UserName user := sess.User.UserName
@ -106,7 +106,7 @@ func (a authCrowd) DetectUser(res http.ResponseWriter, r *http.Request) (string,
// to authenticate the user or throw an error. If the user has // to authenticate the user or throw an error. If the user has
// successfully logged in the persistent cookie should be written // successfully logged in the persistent cookie should be written
// in order to use DetectUser for the next login. // in order to use DetectUser for the next login.
// If the user did not login correctly the errNoValidUserFound // If the user did not login correctly the plugins.ErrNoValidUserFound
// needs to be returned // needs to be returned
func (a authCrowd) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) { func (a authCrowd) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) {
username := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "username"}, "-")) username := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "username"}, "-"))
@ -122,7 +122,7 @@ func (a authCrowd) Login(res http.ResponseWriter, r *http.Request) (string, []pl
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"username": username, "username": username,
}).WithError(err).Debug("Crowd authentication failed") }).WithError(err).Debug("Crowd authentication failed")
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
http.SetCookie(res, &http.Cookie{ http.SetCookie(res, &http.Cookie{

View file

@ -46,7 +46,7 @@ func (a authLDAP) AuthenticatorID() string { return "ldap" }
// Configure loads the configuration for the Authenticator from the // Configure loads the configuration for the Authenticator from the
// global config.yaml file which is passed as a byte-slice. // global config.yaml file which is passed as a byte-slice.
// If no configuration for the Authenticator is supplied the function // If no configuration for the Authenticator is supplied the function
// needs to return the errProviderUnconfigured // needs to return the plugins.ErrProviderUnconfigured
func (a *authLDAP) Configure(yamlSource []byte) error { func (a *authLDAP) Configure(yamlSource []byte) error {
envelope := struct { envelope := struct {
Providers struct { Providers struct {
@ -59,7 +59,7 @@ func (a *authLDAP) Configure(yamlSource []byte) error {
} }
if envelope.Providers.LDAP == nil { if envelope.Providers.LDAP == nil {
return errProviderUnconfigured return plugins.ErrProviderUnconfigured
} }
a.EnableBasicAuth = envelope.Providers.LDAP.EnableBasicAuth a.EnableBasicAuth = envelope.Providers.LDAP.EnableBasicAuth
@ -98,7 +98,7 @@ func (a *authLDAP) Configure(yamlSource []byte) error {
// DetectUser is used to detect a user without a login form from // DetectUser is used to detect a user without a login form from
// a cookie, header or other methods // a cookie, header or other methods
// If no user was detected the errNoValidUserFound needs to be // If no user was detected the plugins.ErrNoValidUserFound needs to be
// returned // returned
func (a authLDAP) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) { func (a authLDAP) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) {
var alias, user string var alias, user string
@ -118,17 +118,17 @@ func (a authLDAP) DetectUser(res http.ResponseWriter, r *http.Request) (string,
if user == "" { if user == "" {
sess, err := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-")) sess, err := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-"))
if err != nil { if err != nil {
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
var ok bool var ok bool
if user, ok = sess.Values["user"].(string); !ok { if user, ok = sess.Values["user"].(string); !ok {
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
if alias, ok = sess.Values["alias"].(string); !ok { if alias, ok = sess.Values["alias"].(string); !ok {
// Most likely an old cookie, force re-login // Most likely an old cookie, force re-login
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
// We had a cookie, lets renew it // We had a cookie, lets renew it
@ -147,7 +147,7 @@ func (a authLDAP) DetectUser(res http.ResponseWriter, r *http.Request) (string,
// to authenticate the user or throw an error. If the user has // to authenticate the user or throw an error. If the user has
// successfully logged in the persistent cookie should be written // successfully logged in the persistent cookie should be written
// in order to use DetectUser for the next login. // in order to use DetectUser for the next login.
// If the user did not login correctly the errNoValidUserFound // If the user did not login correctly the plugins.ErrNoValidUserFound
// needs to be returned // needs to be returned
func (a authLDAP) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) { func (a authLDAP) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) {
username := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "username"}, "-")) username := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "username"}, "-"))
@ -200,7 +200,7 @@ func (a authLDAP) Logout(res http.ResponseWriter, r *http.Request) (err error) {
} }
// checkLogin searches for the username using the specified UserSearchFilter // checkLogin searches for the username using the specified UserSearchFilter
// and returns the UserDN and an error (errNoValidUserFound / processing error) // and returns the UserDN and an error (plugins.ErrNoValidUserFound / processing error)
func (a authLDAP) checkLogin(username, password, aliasAttribute string) (string, string, error) { func (a authLDAP) checkLogin(username, password, aliasAttribute string) (string, string, error) {
l, err := a.dial() l, err := a.dial()
if err != nil { if err != nil {
@ -224,13 +224,13 @@ func (a authLDAP) checkLogin(username, password, aliasAttribute string) (string,
} }
if len(sres.Entries) != 1 { if len(sres.Entries) != 1 {
return "", "", errNoValidUserFound return "", "", plugins.ErrNoValidUserFound
} }
userDN := sres.Entries[0].DN userDN := sres.Entries[0].DN
if err := l.Bind(userDN, password); err != nil { if err := l.Bind(userDN, password); err != nil {
return "", "", errNoValidUserFound return "", "", plugins.ErrNoValidUserFound
} }
alias := sres.Entries[0].GetAttributeValue(aliasAttribute) alias := sres.Entries[0].GetAttributeValue(aliasAttribute)

View file

@ -29,7 +29,7 @@ func (a authSimple) AuthenticatorID() string { return "simple" }
// Configure loads the configuration for the Authenticator from the // Configure loads the configuration for the Authenticator from the
// global config.yaml file which is passed as a byte-slice. // global config.yaml file which is passed as a byte-slice.
// If no configuration for the Authenticator is supplied the function // If no configuration for the Authenticator is supplied the function
// needs to return the errProviderUnconfigured // needs to return the plugins.ErrProviderUnconfigured
func (a *authSimple) Configure(yamlSource []byte) error { func (a *authSimple) Configure(yamlSource []byte) error {
envelope := struct { envelope := struct {
Providers struct { Providers struct {
@ -42,7 +42,7 @@ func (a *authSimple) Configure(yamlSource []byte) error {
} }
if envelope.Providers.Simple == nil { if envelope.Providers.Simple == nil {
return errProviderUnconfigured return plugins.ErrProviderUnconfigured
} }
a.EnableBasicAuth = envelope.Providers.Simple.EnableBasicAuth a.EnableBasicAuth = envelope.Providers.Simple.EnableBasicAuth
@ -55,7 +55,7 @@ func (a *authSimple) Configure(yamlSource []byte) error {
// DetectUser is used to detect a user without a login form from // DetectUser is used to detect a user without a login form from
// a cookie, header or other methods // a cookie, header or other methods
// If no user was detected the errNoValidUserFound needs to be // If no user was detected the plugins.ErrNoValidUserFound needs to be
// returned // returned
func (a authSimple) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) { func (a authSimple) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) {
var user string var user string
@ -78,13 +78,13 @@ func (a authSimple) DetectUser(res http.ResponseWriter, r *http.Request) (string
if user == "" { if user == "" {
sess, err := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-")) sess, err := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-"))
if err != nil { if err != nil {
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
var ok bool var ok bool
user, ok = sess.Values["user"].(string) user, ok = sess.Values["user"].(string)
if !ok { if !ok {
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
// We had a cookie, lets renew it // We had a cookie, lets renew it
@ -108,7 +108,7 @@ func (a authSimple) DetectUser(res http.ResponseWriter, r *http.Request) (string
// to authenticate the user or throw an error. If the user has // to authenticate the user or throw an error. If the user has
// successfully logged in the persistent cookie should be written // successfully logged in the persistent cookie should be written
// in order to use DetectUser for the next login. // in order to use DetectUser for the next login.
// If the user did not login correctly the errNoValidUserFound // If the user did not login correctly the plugins.ErrNoValidUserFound
// needs to be returned // needs to be returned
func (a authSimple) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) { func (a authSimple) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) {
username := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "username"}, "-")) username := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "username"}, "-"))
@ -128,7 +128,7 @@ func (a authSimple) Login(res http.ResponseWriter, r *http.Request) (string, []p
return u, a.MFA[u], sess.Save(r, res) return u, a.MFA[u], sess.Save(r, res)
} }
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
// LoginFields needs to return the fields required for this login // LoginFields needs to return the fields required for this login

View file

@ -26,7 +26,7 @@ func (a authToken) AuthenticatorID() string { return "token" }
// Configure loads the configuration for the Authenticator from the // Configure loads the configuration for the Authenticator from the
// global config.yaml file which is passed as a byte-slice. // global config.yaml file which is passed as a byte-slice.
// If no configuration for the Authenticator is supplied the function // If no configuration for the Authenticator is supplied the function
// needs to return the errProviderUnconfigured // needs to return the plugins.ErrProviderUnconfigured
func (a *authToken) Configure(yamlSource []byte) error { func (a *authToken) Configure(yamlSource []byte) error {
envelope := struct { envelope := struct {
Providers struct { Providers struct {
@ -39,7 +39,7 @@ func (a *authToken) Configure(yamlSource []byte) error {
} }
if envelope.Providers.Token == nil { if envelope.Providers.Token == nil {
return errProviderUnconfigured return plugins.ErrProviderUnconfigured
} }
a.Tokens = envelope.Providers.Token.Tokens a.Tokens = envelope.Providers.Token.Tokens
@ -50,13 +50,13 @@ func (a *authToken) Configure(yamlSource []byte) error {
// DetectUser is used to detect a user without a login form from // DetectUser is used to detect a user without a login form from
// a cookie, header or other methods // a cookie, header or other methods
// If no user was detected the errNoValidUserFound needs to be // If no user was detected the plugins.ErrNoValidUserFound needs to be
// returned // returned
func (a authToken) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) { func (a authToken) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) {
authHeader := r.Header.Get("Authorization") authHeader := r.Header.Get("Authorization")
if !strings.HasPrefix(authHeader, "Token ") { if !strings.HasPrefix(authHeader, "Token ") {
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
tmp := strings.SplitN(authHeader, " ", 2) tmp := strings.SplitN(authHeader, " ", 2)
@ -74,7 +74,7 @@ func (a authToken) DetectUser(res http.ResponseWriter, r *http.Request) (string,
} }
if !userFound { if !userFound {
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
groups := []string{} groups := []string{}
@ -91,10 +91,10 @@ func (a authToken) DetectUser(res http.ResponseWriter, r *http.Request) (string,
// to authenticate the user or throw an error. If the user has // to authenticate the user or throw an error. If the user has
// successfully logged in the persistent cookie should be written // successfully logged in the persistent cookie should be written
// in order to use DetectUser for the next login. // in order to use DetectUser for the next login.
// If the user did not login correctly the errNoValidUserFound // If the user did not login correctly the plugins.ErrNoValidUserFound
// needs to be returned // needs to be returned
func (a authToken) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) { func (a authToken) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) {
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
// LoginFields needs to return the fields required for this login // LoginFields needs to return the fields required for this login

View file

@ -29,7 +29,7 @@ func (a authYubikey) AuthenticatorID() string { return "yubikey" }
// Configure loads the configuration for the Authenticator from the // Configure loads the configuration for the Authenticator from the
// global config.yaml file which is passed as a byte-slice. // global config.yaml file which is passed as a byte-slice.
// If no configuration for the Authenticator is supplied the function // If no configuration for the Authenticator is supplied the function
// needs to return the errProviderUnconfigured // needs to return the plugins.ErrProviderUnconfigured
func (a *authYubikey) Configure(yamlSource []byte) error { func (a *authYubikey) Configure(yamlSource []byte) error {
envelope := struct { envelope := struct {
Providers struct { Providers struct {
@ -42,7 +42,7 @@ func (a *authYubikey) Configure(yamlSource []byte) error {
} }
if envelope.Providers.Yubikey == nil { if envelope.Providers.Yubikey == nil {
return errProviderUnconfigured return plugins.ErrProviderUnconfigured
} }
a.ClientID = envelope.Providers.Yubikey.ClientID a.ClientID = envelope.Providers.Yubikey.ClientID
@ -55,17 +55,17 @@ func (a *authYubikey) Configure(yamlSource []byte) error {
// DetectUser is used to detect a user without a login form from // DetectUser is used to detect a user without a login form from
// a cookie, header or other methods // a cookie, header or other methods
// If no user was detected the errNoValidUserFound needs to be // If no user was detected the plugins.ErrNoValidUserFound needs to be
// returned // returned
func (a authYubikey) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) { func (a authYubikey) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) {
sess, err := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-")) sess, err := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-"))
if err != nil { if err != nil {
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
user, ok := sess.Values["user"].(string) user, ok := sess.Values["user"].(string)
if !ok { if !ok {
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
// We had a cookie, lets renew it // We had a cookie, lets renew it
@ -88,7 +88,7 @@ func (a authYubikey) DetectUser(res http.ResponseWriter, r *http.Request) (strin
// to authenticate the user or throw an error. If the user has // to authenticate the user or throw an error. If the user has
// successfully logged in the persistent cookie should be written // successfully logged in the persistent cookie should be written
// in order to use DetectUser for the next login. // in order to use DetectUser for the next login.
// If the user did not login correctly the errNoValidUserFound // If the user did not login correctly the plugins.ErrNoValidUserFound
// needs to be returned // needs to be returned
func (a authYubikey) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) { func (a authYubikey) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) {
keyInput := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "key-input"}, "-")) keyInput := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "key-input"}, "-"))
@ -105,13 +105,13 @@ func (a authYubikey) Login(res http.ResponseWriter, r *http.Request) (string, []
if !ok { if !ok {
// Not a valid authentication // Not a valid authentication
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
user, ok := a.Devices[keyInput[:12]] user, ok := a.Devices[keyInput[:12]]
if !ok { if !ok {
// We do not have a definition for that key // We do not have a definition for that key
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
sess, _ := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned sess, _ := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned

View file

@ -17,6 +17,7 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
"github.com/Luzifer/nginx-sso/plugins"
"github.com/Luzifer/rconfig" "github.com/Luzifer/rconfig"
) )
@ -157,7 +158,7 @@ func handleAuthRequest(res http.ResponseWriter, r *http.Request) {
user, groups, err := detectUser(res, r) user, groups, err := detectUser(res, r)
switch err { switch err {
case errNoValidUserFound: case plugins.ErrNoValidUserFound:
mainCfg.AuditLog.Log(auditEventValidate, r, map[string]string{"result": "no valid user found"}) // #nosec G104 - This is only logging mainCfg.AuditLog.Log(auditEventValidate, r, map[string]string{"result": "no valid user found"}) // #nosec G104 - This is only logging
http.Error(res, "No valid user found", http.StatusUnauthorized) http.Error(res, "No valid user found", http.StatusUnauthorized)
@ -194,7 +195,7 @@ func handleLoginRequest(res http.ResponseWriter, r *http.Request) {
// Simple authentication // Simple authentication
user, mfaCfgs, err := loginUser(res, r) user, mfaCfgs, err := loginUser(res, r)
switch err { switch err {
case errNoValidUserFound: case plugins.ErrNoValidUserFound:
auditFields["reason"] = "invalid credentials" auditFields["reason"] = "invalid credentials"
mainCfg.AuditLog.Log(auditEventLoginFailure, r, auditFields) // #nosec G104 - This is only logging mainCfg.AuditLog.Log(auditEventLoginFailure, r, auditFields) // #nosec G104 - This is only logging
http.Redirect(res, r, "/login?go="+url.QueryEscape(r.FormValue("go")), http.StatusFound) http.Redirect(res, r, "/login?go="+url.QueryEscape(r.FormValue("go")), http.StatusFound)
@ -213,7 +214,7 @@ func handleLoginRequest(res http.ResponseWriter, r *http.Request) {
// MFA validation against configs from login // MFA validation against configs from login
err = validateMFA(res, r, user, mfaCfgs) err = validateMFA(res, r, user, mfaCfgs)
switch err { switch err {
case errNoValidUserFound: case plugins.ErrNoValidUserFound:
auditFields["reason"] = "invalid credentials" auditFields["reason"] = "invalid credentials"
mainCfg.AuditLog.Log(auditEventLoginFailure, r, auditFields) // #nosec G104 - This is only logging mainCfg.AuditLog.Log(auditEventLoginFailure, r, auditFields) // #nosec G104 - This is only logging
res.Header().Del("Set-Cookie") // Remove login cookie res.Header().Del("Set-Cookie") // Remove login cookie

6
mfa.go
View file

@ -44,7 +44,7 @@ func initializeMFAProviders(yamlSource []byte) error {
case nil: case nil:
activeMFAProviders = append(activeMFAProviders, m) activeMFAProviders = append(activeMFAProviders, m)
log.WithFields(log.Fields{"mfa_provider": m.ProviderID()}).Debug("Activated MFA provider") log.WithFields(log.Fields{"mfa_provider": m.ProviderID()}).Debug("Activated MFA provider")
case errProviderUnconfigured: case plugins.ErrProviderUnconfigured:
log.WithFields(log.Fields{"mfa_provider": m.ProviderID()}).Debug("MFA provider unconfigured") log.WithFields(log.Fields{"mfa_provider": m.ProviderID()}).Debug("MFA provider unconfigured")
// This is okay. // This is okay.
default: default:
@ -70,7 +70,7 @@ func validateMFA(res http.ResponseWriter, r *http.Request, user string, mfaCfgs
case nil: case nil:
// Validated successfully // Validated successfully
return nil return nil
case errNoValidUserFound: case plugins.ErrNoValidUserFound:
// This is fine for now // This is fine for now
default: default:
return err return err
@ -78,5 +78,5 @@ func validateMFA(res http.ResponseWriter, r *http.Request, user string, mfaCfgs
} }
// No method could verify the user // No method could verify the user
return errNoValidUserFound return plugins.ErrNoValidUserFound
} }

View file

@ -39,7 +39,7 @@ func (m mfaDuo) ProviderID() (id string) { return "duo" }
// Configure loads the configuration for the Authenticator from the // Configure loads the configuration for the Authenticator from the
// global config.yaml file which is passed as a byte-slice. // global config.yaml file which is passed as a byte-slice.
// If no configuration for the Authenticator is supplied the function // If no configuration for the Authenticator is supplied the function
// needs to return the errProviderUnconfigured // needs to return the plugins.ErrProviderUnconfigured
func (m *mfaDuo) Configure(yamlSource []byte) (err error) { func (m *mfaDuo) Configure(yamlSource []byte) (err error) {
envelope := struct { envelope := struct {
MFA struct { MFA struct {
@ -52,7 +52,7 @@ func (m *mfaDuo) Configure(yamlSource []byte) (err error) {
} }
if envelope.MFA.Duo == nil { if envelope.MFA.Duo == nil {
return errProviderUnconfigured return plugins.ErrProviderUnconfigured
} }
m.IKey = envelope.MFA.Duo.IKey m.IKey = envelope.MFA.Duo.IKey
@ -105,7 +105,7 @@ func (m mfaDuo) ValidateMFA(res http.ResponseWriter, r *http.Request, user strin
} }
// Report this provider was not able to verify the MFA request // Report this provider was not able to verify the MFA request
return errNoValidUserFound return plugins.ErrNoValidUserFound
} }
func (m mfaDuo) findIP(r *http.Request) (string, error) { func (m mfaDuo) findIP(r *http.Request) (string, error) {

View file

@ -27,7 +27,7 @@ func (m mfaTOTP) ProviderID() (id string) {
// Configure loads the configuration for the Authenticator from the // Configure loads the configuration for the Authenticator from the
// global config.yaml file which is passed as a byte-slice. // global config.yaml file which is passed as a byte-slice.
// If no configuration for the Authenticator is supplied the function // If no configuration for the Authenticator is supplied the function
// needs to return the errProviderUnconfigured // 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 // ValidateMFA takes the user from the login cookie and performs a
@ -53,7 +53,7 @@ func (m mfaTOTP) ValidateMFA(res http.ResponseWriter, r *http.Request, user stri
} }
// Report this provider was not able to verify the MFA request // Report this provider was not able to verify the MFA request
return errNoValidUserFound return plugins.ErrNoValidUserFound
} }
func (m mfaTOTP) exec(c plugins.MFAConfig) (string, error) { func (m mfaTOTP) exec(c plugins.MFAConfig) (string, error) {

View file

@ -27,7 +27,7 @@ func (m mfaYubikey) ProviderID() (id string) { return "yubikey" }
// Configure loads the configuration for the Authenticator from the // Configure loads the configuration for the Authenticator from the
// global config.yaml file which is passed as a byte-slice. // global config.yaml file which is passed as a byte-slice.
// If no configuration for the Authenticator is supplied the function // If no configuration for the Authenticator is supplied the function
// needs to return the errProviderUnconfigured // needs to return the plugins.ErrProviderUnconfigured
func (m *mfaYubikey) Configure(yamlSource []byte) (err error) { func (m *mfaYubikey) Configure(yamlSource []byte) (err error) {
envelope := struct { envelope := struct {
MFA struct { MFA struct {
@ -40,7 +40,7 @@ func (m *mfaYubikey) Configure(yamlSource []byte) (err error) {
} }
if envelope.MFA.Yubikey == nil { if envelope.MFA.Yubikey == nil {
return errProviderUnconfigured return plugins.ErrProviderUnconfigured
} }
m.ClientID = envelope.MFA.Yubikey.ClientID m.ClientID = envelope.MFA.Yubikey.ClientID
@ -85,5 +85,5 @@ func (m mfaYubikey) ValidateMFA(res http.ResponseWriter, r *http.Request, user s
} }
// Not a valid authentication // Not a valid authentication
return errNoValidUserFound return plugins.ErrNoValidUserFound
} }

View file

@ -10,12 +10,12 @@ type Authenticator interface {
// Configure loads the configuration for the Authenticator from the // Configure loads the configuration for the Authenticator from the
// global config.yaml file which is passed as a byte-slice. // global config.yaml file which is passed as a byte-slice.
// If no configuration for the Authenticator is supplied the function // If no configuration for the Authenticator is supplied the function
// needs to return the errProviderUnconfigured // needs to return the ErrProviderUnconfigured
Configure(yamlSource []byte) (err error) Configure(yamlSource []byte) (err error)
// DetectUser is used to detect a user without a login form from // DetectUser is used to detect a user without a login form from
// a cookie, header or other methods // a cookie, header or other methods
// If no user was detected the errNoValidUserFound needs to be // If no user was detected the ErrNoValidUserFound needs to be
// returned // returned
DetectUser(res http.ResponseWriter, r *http.Request) (user string, groups []string, err error) DetectUser(res http.ResponseWriter, r *http.Request) (user string, groups []string, err error)
@ -26,7 +26,7 @@ type Authenticator interface {
// With the login result an array of mfaConfig must be returned. In // With the login result an array of mfaConfig must be returned. In
// case there is no MFA config or the provider does not support MFA // case there is no MFA config or the provider does not support MFA
// return nil. // return nil.
// If the user did not login correctly the errNoValidUserFound // If the user did not login correctly the ErrNoValidUserFound
// needs to be returned // needs to be returned
Login(res http.ResponseWriter, r *http.Request) (user string, mfaConfigs []MFAConfig, err error) Login(res http.ResponseWriter, r *http.Request) (user string, mfaConfigs []MFAConfig, err error)

8
plugins/errors.go Normal file
View file

@ -0,0 +1,8 @@
package plugins
import "errors"
var (
ErrProviderUnconfigured = errors.New("No valid configuration found for this provider")
ErrNoValidUserFound = errors.New("No valid users found")
)

View file

@ -10,7 +10,7 @@ type MFAProvider interface {
// Configure loads the configuration for the Authenticator from the // Configure loads the configuration for the Authenticator from the
// global config.yaml file which is passed as a byte-slice. // global config.yaml file which is passed as a byte-slice.
// If no configuration for the Authenticator is supplied the function // If no configuration for the Authenticator is supplied the function
// needs to return the errProviderUnconfigured // needs to return the ErrProviderUnconfigured
Configure(yamlSource []byte) (err error) Configure(yamlSource []byte) (err error)
// ValidateMFA takes the user from the login cookie and performs a // ValidateMFA takes the user from the login cookie and performs a

View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"errors"
"fmt" "fmt"
"net/http" "net/http"
"sync" "sync"
@ -12,9 +11,6 @@ import (
) )
var ( var (
errProviderUnconfigured = errors.New("No valid configuration found for this provider")
errNoValidUserFound = errors.New("No valid users found")
authenticatorRegistry = []plugins.Authenticator{} authenticatorRegistry = []plugins.Authenticator{}
authenticatorRegistryMutex sync.RWMutex authenticatorRegistryMutex sync.RWMutex
@ -40,7 +36,7 @@ func initializeAuthenticators(yamlSource []byte) error {
case nil: case nil:
tmp = append(tmp, a) tmp = append(tmp, a)
log.WithFields(log.Fields{"authenticator": a.AuthenticatorID()}).Debug("Activated authenticator") log.WithFields(log.Fields{"authenticator": a.AuthenticatorID()}).Debug("Activated authenticator")
case errProviderUnconfigured: case plugins.ErrProviderUnconfigured:
log.WithFields(log.Fields{"authenticator": a.AuthenticatorID()}).Debug("Authenticator unconfigured") log.WithFields(log.Fields{"authenticator": a.AuthenticatorID()}).Debug("Authenticator unconfigured")
// This is okay. // This is okay.
default: default:
@ -66,14 +62,14 @@ func detectUser(res http.ResponseWriter, r *http.Request) (string, []string, err
switch err { switch err {
case nil: case nil:
return user, groups, err return user, groups, err
case errNoValidUserFound: case plugins.ErrNoValidUserFound:
// This is okay. // This is okay.
default: default:
return "", nil, err return "", nil, err
} }
} }
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
func loginUser(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) { func loginUser(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) {
@ -85,14 +81,14 @@ func loginUser(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAC
switch err { switch err {
case nil: case nil:
return user, mfaCfgs, nil return user, mfaCfgs, nil
case errNoValidUserFound: case plugins.ErrNoValidUserFound:
// This is okay. // This is okay.
default: default:
return "", nil, err return "", nil, err
} }
} }
return "", nil, errNoValidUserFound return "", nil, plugins.ErrNoValidUserFound
} }
func logoutUser(res http.ResponseWriter, r *http.Request) error { func logoutUser(res http.ResponseWriter, r *http.Request) error {