mirror of
https://github.com/Luzifer/nginx-sso.git
synced 2024-12-20 21:01:17 +00:00
Move auth plugins to own modules
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
282a95c2e9
commit
29beaa6fa3
6 changed files with 131 additions and 92 deletions
10
core.go
10
core.go
|
@ -1,14 +1,24 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/Luzifer/nginx-sso/plugins/auth/crowd"
|
||||||
"github.com/Luzifer/nginx-sso/plugins/auth/google"
|
"github.com/Luzifer/nginx-sso/plugins/auth/google"
|
||||||
|
"github.com/Luzifer/nginx-sso/plugins/auth/ldap"
|
||||||
|
"github.com/Luzifer/nginx-sso/plugins/auth/simple"
|
||||||
|
"github.com/Luzifer/nginx-sso/plugins/auth/token"
|
||||||
|
auth_yubikey "github.com/Luzifer/nginx-sso/plugins/auth/yubikey"
|
||||||
"github.com/Luzifer/nginx-sso/plugins/mfa/duo"
|
"github.com/Luzifer/nginx-sso/plugins/mfa/duo"
|
||||||
"github.com/Luzifer/nginx-sso/plugins/mfa/totp"
|
"github.com/Luzifer/nginx-sso/plugins/mfa/totp"
|
||||||
mfa_yubikey "github.com/Luzifer/nginx-sso/plugins/mfa/yubikey"
|
mfa_yubikey "github.com/Luzifer/nginx-sso/plugins/mfa/yubikey"
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerModules() {
|
func registerModules() {
|
||||||
|
registerAuthenticator(crowd.New())
|
||||||
|
registerAuthenticator(ldap.New(cookieStore))
|
||||||
registerAuthenticator(google.New(cookieStore))
|
registerAuthenticator(google.New(cookieStore))
|
||||||
|
registerAuthenticator(simple.New(cookieStore))
|
||||||
|
registerAuthenticator(token.New())
|
||||||
|
registerAuthenticator(auth_yubikey.New(cookieStore))
|
||||||
|
|
||||||
registerMFAProvider(duo.New())
|
registerMFAProvider(duo.New())
|
||||||
registerMFAProvider(totp.New())
|
registerMFAProvider(totp.New())
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package crowd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -11,11 +11,7 @@ import (
|
||||||
"github.com/Luzifer/nginx-sso/plugins"
|
"github.com/Luzifer/nginx-sso/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
type AuthCrowd struct {
|
||||||
registerAuthenticator(&authCrowd{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type authCrowd struct {
|
|
||||||
URL string `yaml:"url"`
|
URL string `yaml:"url"`
|
||||||
AppName string `yaml:"app_name"`
|
AppName string `yaml:"app_name"`
|
||||||
AppPassword string `yaml:"app_pass"`
|
AppPassword string `yaml:"app_pass"`
|
||||||
|
@ -23,18 +19,22 @@ type authCrowd struct {
|
||||||
crowd crowd.Crowd
|
crowd crowd.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func New() *AuthCrowd {
|
||||||
|
return &AuthCrowd{}
|
||||||
|
}
|
||||||
|
|
||||||
// AuthenticatorID needs to return an unique string to identify
|
// AuthenticatorID needs to return an unique string to identify
|
||||||
// this special authenticator
|
// this special authenticator
|
||||||
func (a authCrowd) AuthenticatorID() string { return "crowd" }
|
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 plugins.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 {
|
||||||
Crowd *authCrowd `yaml:"crowd"`
|
Crowd *AuthCrowd `yaml:"crowd"`
|
||||||
} `yaml:"providers"`
|
} `yaml:"providers"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ func (a *authCrowd) Configure(yamlSource []byte) error {
|
||||||
// a cookie, header or other methods
|
// a cookie, header or other methods
|
||||||
// If no user was detected the plugins.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()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
|
@ -108,7 +108,7 @@ func (a authCrowd) DetectUser(res http.ResponseWriter, r *http.Request) (string,
|
||||||
// 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 plugins.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"}, "-"))
|
||||||
password := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "password"}, "-"))
|
password := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "password"}, "-"))
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ func (a authCrowd) Login(res http.ResponseWriter, r *http.Request) (string, []pl
|
||||||
// LoginFields needs to return the fields required for this login
|
// LoginFields needs to return the fields required for this login
|
||||||
// method. If no login using this method is possible the function
|
// method. If no login using this method is possible the function
|
||||||
// needs to return nil.
|
// needs to return nil.
|
||||||
func (a authCrowd) LoginFields() (fields []plugins.LoginField) {
|
func (a AuthCrowd) LoginFields() (fields []plugins.LoginField) {
|
||||||
return []plugins.LoginField{
|
return []plugins.LoginField{
|
||||||
{
|
{
|
||||||
Label: "Username",
|
Label: "Username",
|
||||||
|
@ -160,7 +160,7 @@ func (a authCrowd) LoginFields() (fields []plugins.LoginField) {
|
||||||
|
|
||||||
// Logout is called when the user visits the logout endpoint and
|
// Logout is called when the user visits the logout endpoint and
|
||||||
// needs to destroy any persistent stored cookies
|
// needs to destroy any persistent stored cookies
|
||||||
func (a authCrowd) Logout(res http.ResponseWriter, r *http.Request) (err error) {
|
func (a AuthCrowd) Logout(res http.ResponseWriter, r *http.Request) (err error) {
|
||||||
cc, err := a.crowd.GetCookieConfig()
|
cc, err := a.crowd.GetCookieConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -184,4 +184,4 @@ func (a authCrowd) Logout(res http.ResponseWriter, r *http.Request) (err error)
|
||||||
// configuration return true. If this is true the login interface
|
// configuration return true. If this is true the login interface
|
||||||
// will display an additional field for this provider for the user
|
// will display an additional field for this provider for the user
|
||||||
// to fill in their MFA token.
|
// to fill in their MFA token.
|
||||||
func (a authCrowd) SupportsMFA() bool { return false }
|
func (a AuthCrowd) SupportsMFA() bool { return false }
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
@ -10,6 +10,8 @@ import (
|
||||||
ldap "gopkg.in/ldap.v2"
|
ldap "gopkg.in/ldap.v2"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
|
|
||||||
"github.com/Luzifer/nginx-sso/plugins"
|
"github.com/Luzifer/nginx-sso/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,11 +20,7 @@ const (
|
||||||
authLDAPProtoLDAPs = "ldaps"
|
authLDAPProtoLDAPs = "ldaps"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
type AuthLDAP struct {
|
||||||
registerAuthenticator(&authLDAP{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type authLDAP struct {
|
|
||||||
EnableBasicAuth bool `yaml:"enable_basic_auth"`
|
EnableBasicAuth bool `yaml:"enable_basic_auth"`
|
||||||
GroupMembershipFilter string `yaml:"group_membership_filter"`
|
GroupMembershipFilter string `yaml:"group_membership_filter"`
|
||||||
GroupSearchBase string `yaml:"group_search_base"`
|
GroupSearchBase string `yaml:"group_search_base"`
|
||||||
|
@ -37,20 +35,30 @@ type authLDAP struct {
|
||||||
ValidateHostname string `yaml:"validate_hostname"`
|
ValidateHostname string `yaml:"validate_hostname"`
|
||||||
AllowInsecure bool `yaml:"allow_insecure"`
|
AllowInsecure bool `yaml:"allow_insecure"`
|
||||||
} `yaml:"tls_config"`
|
} `yaml:"tls_config"`
|
||||||
|
|
||||||
|
cookie plugins.CookieConfig
|
||||||
|
cookieStore *sessions.CookieStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(cs *sessions.CookieStore) *AuthLDAP {
|
||||||
|
return &AuthLDAP{
|
||||||
|
cookieStore: cs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthenticatorID needs to return an unique string to identify
|
// AuthenticatorID needs to return an unique string to identify
|
||||||
// this special authenticator
|
// this special authenticator
|
||||||
func (a authLDAP) AuthenticatorID() string { return "ldap" }
|
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 plugins.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 {
|
||||||
|
Cookie plugins.CookieConfig `yaml:"cookie"`
|
||||||
Providers struct {
|
Providers struct {
|
||||||
LDAP *authLDAP `yaml:"ldap"`
|
LDAP *AuthLDAP `yaml:"ldap"`
|
||||||
} `yaml:"providers"`
|
} `yaml:"providers"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
|
@ -74,6 +82,8 @@ func (a *authLDAP) Configure(yamlSource []byte) error {
|
||||||
a.UsernameAttribute = envelope.Providers.LDAP.UsernameAttribute
|
a.UsernameAttribute = envelope.Providers.LDAP.UsernameAttribute
|
||||||
a.TLSConfig = envelope.Providers.LDAP.TLSConfig
|
a.TLSConfig = envelope.Providers.LDAP.TLSConfig
|
||||||
|
|
||||||
|
a.cookie = envelope.Cookie
|
||||||
|
|
||||||
// Set defaults
|
// Set defaults
|
||||||
if a.UserSearchFilter == "" {
|
if a.UserSearchFilter == "" {
|
||||||
a.UserSearchFilter = `(uid={0})`
|
a.UserSearchFilter = `(uid={0})`
|
||||||
|
@ -100,7 +110,7 @@ func (a *authLDAP) Configure(yamlSource []byte) error {
|
||||||
// a cookie, header or other methods
|
// a cookie, header or other methods
|
||||||
// If no user was detected the plugins.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
|
||||||
|
|
||||||
if a.EnableBasicAuth {
|
if a.EnableBasicAuth {
|
||||||
|
@ -116,7 +126,7 @@ 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 := a.cookieStore.Get(r, strings.Join([]string{a.cookie.Prefix, a.AuthenticatorID()}, "-"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, plugins.ErrNoValidUserFound
|
return "", nil, plugins.ErrNoValidUserFound
|
||||||
}
|
}
|
||||||
|
@ -132,7 +142,7 @@ func (a authLDAP) DetectUser(res http.ResponseWriter, r *http.Request) (string,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We had a cookie, lets renew it
|
// We had a cookie, lets renew it
|
||||||
sess.Options = mainCfg.Cookie.GetSessionOpts()
|
sess.Options = a.cookie.GetSessionOpts()
|
||||||
if err := sess.Save(r, res); err != nil {
|
if err := sess.Save(r, res); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
@ -149,7 +159,7 @@ func (a authLDAP) DetectUser(res http.ResponseWriter, r *http.Request) (string,
|
||||||
// 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 plugins.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"}, "-"))
|
||||||
password := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "password"}, "-"))
|
password := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "password"}, "-"))
|
||||||
|
|
||||||
|
@ -163,8 +173,8 @@ func (a authLDAP) Login(res http.ResponseWriter, r *http.Request) (string, []plu
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sess, _ := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
sess, _ := a.cookieStore.Get(r, strings.Join([]string{a.cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
||||||
sess.Options = mainCfg.Cookie.GetSessionOpts()
|
sess.Options = a.cookie.GetSessionOpts()
|
||||||
sess.Values["user"] = userDN
|
sess.Values["user"] = userDN
|
||||||
sess.Values["alias"] = alias
|
sess.Values["alias"] = alias
|
||||||
return userDN, nil, sess.Save(r, res)
|
return userDN, nil, sess.Save(r, res)
|
||||||
|
@ -173,7 +183,7 @@ func (a authLDAP) Login(res http.ResponseWriter, r *http.Request) (string, []plu
|
||||||
// LoginFields needs to return the fields required for this login
|
// LoginFields needs to return the fields required for this login
|
||||||
// method. If no login using this method is possible the function
|
// method. If no login using this method is possible the function
|
||||||
// needs to return nil.
|
// needs to return nil.
|
||||||
func (a authLDAP) LoginFields() (fields []plugins.LoginField) {
|
func (a AuthLDAP) LoginFields() (fields []plugins.LoginField) {
|
||||||
return []plugins.LoginField{
|
return []plugins.LoginField{
|
||||||
{
|
{
|
||||||
Label: "Username",
|
Label: "Username",
|
||||||
|
@ -192,16 +202,16 @@ func (a authLDAP) LoginFields() (fields []plugins.LoginField) {
|
||||||
|
|
||||||
// Logout is called when the user visits the logout endpoint and
|
// Logout is called when the user visits the logout endpoint and
|
||||||
// needs to destroy any persistent stored cookies
|
// needs to destroy any persistent stored cookies
|
||||||
func (a authLDAP) Logout(res http.ResponseWriter, r *http.Request) (err error) {
|
func (a AuthLDAP) Logout(res http.ResponseWriter, r *http.Request) (err error) {
|
||||||
sess, _ := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
sess, _ := a.cookieStore.Get(r, strings.Join([]string{a.cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
||||||
sess.Options = mainCfg.Cookie.GetSessionOpts()
|
sess.Options = a.cookie.GetSessionOpts()
|
||||||
sess.Options.MaxAge = -1 // Instant delete
|
sess.Options.MaxAge = -1 // Instant delete
|
||||||
return sess.Save(r, res)
|
return sess.Save(r, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 (plugins.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 {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
|
@ -242,7 +252,7 @@ func (a authLDAP) checkLogin(username, password, aliasAttribute string) (string,
|
||||||
return userDN, alias, nil
|
return userDN, alias, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a authLDAP) portFromScheme(scheme, override string) string {
|
func (a AuthLDAP) portFromScheme(scheme, override string) string {
|
||||||
if override != "" {
|
if override != "" {
|
||||||
return override
|
return override
|
||||||
}
|
}
|
||||||
|
@ -258,7 +268,7 @@ func (a authLDAP) portFromScheme(scheme, override string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// dial connects to the LDAP server and authenticates using manager_dn
|
// dial connects to the LDAP server and authenticates using manager_dn
|
||||||
func (a authLDAP) dial() (*ldap.Conn, error) {
|
func (a AuthLDAP) dial() (*ldap.Conn, error) {
|
||||||
u, err := url.Parse(a.Server)
|
u, err := url.Parse(a.Server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -305,7 +315,7 @@ func (a authLDAP) dial() (*ldap.Conn, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUserGroups searches for groups containing the user
|
// getUserGroups searches for groups containing the user
|
||||||
func (a authLDAP) getUserGroups(userDN, alias string) ([]string, error) {
|
func (a AuthLDAP) getUserGroups(userDN, alias string) ([]string, error) {
|
||||||
l, err := a.dial()
|
l, err := a.dial()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -343,4 +353,4 @@ func (a authLDAP) getUserGroups(userDN, alias string) ([]string, error) {
|
||||||
// configuration return true. If this is true the login interface
|
// configuration return true. If this is true the login interface
|
||||||
// will display an additional field for this provider for the user
|
// will display an additional field for this provider for the user
|
||||||
// to fill in their MFA token.
|
// to fill in their MFA token.
|
||||||
func (a authLDAP) SupportsMFA() bool { return false } // TODO: Implement
|
func (a AuthLDAP) SupportsMFA() bool { return false } // TODO: Implement
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package simple
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -7,33 +7,41 @@ import (
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
|
|
||||||
"github.com/Luzifer/go_helpers/str"
|
"github.com/Luzifer/go_helpers/str"
|
||||||
"github.com/Luzifer/nginx-sso/plugins"
|
"github.com/Luzifer/nginx-sso/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
type AuthSimple struct {
|
||||||
registerAuthenticator(&authSimple{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type authSimple struct {
|
|
||||||
EnableBasicAuth bool `yaml:"enable_basic_auth"`
|
EnableBasicAuth bool `yaml:"enable_basic_auth"`
|
||||||
Users map[string]string `yaml:"users"`
|
Users map[string]string `yaml:"users"`
|
||||||
Groups map[string][]string `yaml:"groups"`
|
Groups map[string][]string `yaml:"groups"`
|
||||||
MFA map[string][]plugins.MFAConfig `yaml:"mfa"`
|
MFA map[string][]plugins.MFAConfig `yaml:"mfa"`
|
||||||
|
|
||||||
|
cookie plugins.CookieConfig
|
||||||
|
cookieStore *sessions.CookieStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(cs *sessions.CookieStore) *AuthSimple {
|
||||||
|
return &AuthSimple{
|
||||||
|
cookieStore: cs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthenticatorID needs to return an unique string to identify
|
// AuthenticatorID needs to return an unique string to identify
|
||||||
// this special authenticator
|
// this special authenticator
|
||||||
func (a authSimple) AuthenticatorID() string { return "simple" }
|
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 plugins.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 {
|
||||||
|
Cookie plugins.CookieConfig `yaml:"cookie"`
|
||||||
Providers struct {
|
Providers struct {
|
||||||
Simple *authSimple `yaml:"simple"`
|
Simple *AuthSimple `yaml:"simple"`
|
||||||
} `yaml:"providers"`
|
} `yaml:"providers"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
|
@ -50,6 +58,8 @@ func (a *authSimple) Configure(yamlSource []byte) error {
|
||||||
a.Groups = envelope.Providers.Simple.Groups
|
a.Groups = envelope.Providers.Simple.Groups
|
||||||
a.MFA = envelope.Providers.Simple.MFA
|
a.MFA = envelope.Providers.Simple.MFA
|
||||||
|
|
||||||
|
a.cookie = envelope.Cookie
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +67,7 @@ func (a *authSimple) Configure(yamlSource []byte) error {
|
||||||
// a cookie, header or other methods
|
// a cookie, header or other methods
|
||||||
// If no user was detected the plugins.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
|
||||||
|
|
||||||
if a.EnableBasicAuth {
|
if a.EnableBasicAuth {
|
||||||
|
@ -76,7 +86,7 @@ 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 := a.cookieStore.Get(r, strings.Join([]string{a.cookie.Prefix, a.AuthenticatorID()}, "-"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, plugins.ErrNoValidUserFound
|
return "", nil, plugins.ErrNoValidUserFound
|
||||||
}
|
}
|
||||||
|
@ -88,7 +98,7 @@ func (a authSimple) DetectUser(res http.ResponseWriter, r *http.Request) (string
|
||||||
}
|
}
|
||||||
|
|
||||||
// We had a cookie, lets renew it
|
// We had a cookie, lets renew it
|
||||||
sess.Options = mainCfg.Cookie.GetSessionOpts()
|
sess.Options = a.cookie.GetSessionOpts()
|
||||||
if err := sess.Save(r, res); err != nil {
|
if err := sess.Save(r, res); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
@ -110,7 +120,7 @@ func (a authSimple) DetectUser(res http.ResponseWriter, r *http.Request) (string
|
||||||
// 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 plugins.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"}, "-"))
|
||||||
password := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "password"}, "-"))
|
password := r.FormValue(strings.Join([]string{a.AuthenticatorID(), "password"}, "-"))
|
||||||
|
|
||||||
|
@ -122,8 +132,8 @@ func (a authSimple) Login(res http.ResponseWriter, r *http.Request) (string, []p
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
sess, _ := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
sess, _ := a.cookieStore.Get(r, strings.Join([]string{a.cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
||||||
sess.Options = mainCfg.Cookie.GetSessionOpts()
|
sess.Options = a.cookie.GetSessionOpts()
|
||||||
sess.Values["user"] = u
|
sess.Values["user"] = u
|
||||||
return u, a.MFA[u], sess.Save(r, res)
|
return u, a.MFA[u], sess.Save(r, res)
|
||||||
}
|
}
|
||||||
|
@ -134,7 +144,7 @@ func (a authSimple) Login(res http.ResponseWriter, r *http.Request) (string, []p
|
||||||
// LoginFields needs to return the fields required for this login
|
// LoginFields needs to return the fields required for this login
|
||||||
// method. If no login using this method is possible the function
|
// method. If no login using this method is possible the function
|
||||||
// needs to return nil.
|
// needs to return nil.
|
||||||
func (a authSimple) LoginFields() (fields []plugins.LoginField) {
|
func (a AuthSimple) LoginFields() (fields []plugins.LoginField) {
|
||||||
return []plugins.LoginField{
|
return []plugins.LoginField{
|
||||||
{
|
{
|
||||||
Label: "Username",
|
Label: "Username",
|
||||||
|
@ -153,9 +163,9 @@ func (a authSimple) LoginFields() (fields []plugins.LoginField) {
|
||||||
|
|
||||||
// Logout is called when the user visits the logout endpoint and
|
// Logout is called when the user visits the logout endpoint and
|
||||||
// needs to destroy any persistent stored cookies
|
// needs to destroy any persistent stored cookies
|
||||||
func (a authSimple) Logout(res http.ResponseWriter, r *http.Request) (err error) {
|
func (a AuthSimple) Logout(res http.ResponseWriter, r *http.Request) (err error) {
|
||||||
sess, _ := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
sess, _ := a.cookieStore.Get(r, strings.Join([]string{a.cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
||||||
sess.Options = mainCfg.Cookie.GetSessionOpts()
|
sess.Options = a.cookie.GetSessionOpts()
|
||||||
sess.Options.MaxAge = -1 // Instant delete
|
sess.Options.MaxAge = -1 // Instant delete
|
||||||
return sess.Save(r, res)
|
return sess.Save(r, res)
|
||||||
}
|
}
|
||||||
|
@ -165,4 +175,4 @@ func (a authSimple) Logout(res http.ResponseWriter, r *http.Request) (err error)
|
||||||
// configuration return true. If this is true the login interface
|
// configuration return true. If this is true the login interface
|
||||||
// will display an additional field for this provider for the user
|
// will display an additional field for this provider for the user
|
||||||
// to fill in their MFA token.
|
// to fill in their MFA token.
|
||||||
func (a authSimple) SupportsMFA() bool { return true }
|
func (a AuthSimple) SupportsMFA() bool { return true }
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package token
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -10,27 +10,27 @@ import (
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
type AuthToken struct {
|
||||||
registerAuthenticator(&authToken{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type authToken struct {
|
|
||||||
Tokens map[string]string `yaml:"tokens"`
|
Tokens map[string]string `yaml:"tokens"`
|
||||||
Groups map[string][]string `yaml:"groups"`
|
Groups map[string][]string `yaml:"groups"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func New() *AuthToken {
|
||||||
|
return &AuthToken{}
|
||||||
|
}
|
||||||
|
|
||||||
// AuthenticatorID needs to return an unique string to identify
|
// AuthenticatorID needs to return an unique string to identify
|
||||||
// this special authenticator
|
// this special authenticator
|
||||||
func (a authToken) AuthenticatorID() string { return "token" }
|
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 plugins.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 {
|
||||||
Token *authToken `yaml:"token"`
|
Token *AuthToken `yaml:"token"`
|
||||||
} `yaml:"providers"`
|
} `yaml:"providers"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ func (a *authToken) Configure(yamlSource []byte) error {
|
||||||
// a cookie, header or other methods
|
// a cookie, header or other methods
|
||||||
// If no user was detected the plugins.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 ") {
|
||||||
|
@ -93,22 +93,22 @@ func (a authToken) DetectUser(res http.ResponseWriter, r *http.Request) (string,
|
||||||
// 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 plugins.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, plugins.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
|
||||||
// method. If no login using this method is possible the function
|
// method. If no login using this method is possible the function
|
||||||
// needs to return nil.
|
// needs to return nil.
|
||||||
func (a authToken) LoginFields() []plugins.LoginField { return nil }
|
func (a AuthToken) LoginFields() []plugins.LoginField { return nil }
|
||||||
|
|
||||||
// Logout is called when the user visits the logout endpoint and
|
// Logout is called when the user visits the logout endpoint and
|
||||||
// needs to destroy any persistent stored cookies
|
// needs to destroy any persistent stored cookies
|
||||||
func (a authToken) Logout(res http.ResponseWriter, r *http.Request) error { return nil }
|
func (a AuthToken) Logout(res http.ResponseWriter, r *http.Request) error { return nil }
|
||||||
|
|
||||||
// SupportsMFA returns the MFA detection capabilities of the login
|
// SupportsMFA returns the MFA detection capabilities of the login
|
||||||
// provider. If the provider can provide mfaConfig objects from its
|
// provider. If the provider can provide mfaConfig objects from its
|
||||||
// configuration return true. If this is true the login interface
|
// configuration return true. If this is true the login interface
|
||||||
// will display an additional field for this provider for the user
|
// will display an additional field for this provider for the user
|
||||||
// to fill in their MFA token.
|
// to fill in their MFA token.
|
||||||
func (a authToken) SupportsMFA() bool { return false }
|
func (a AuthToken) SupportsMFA() bool { return false }
|
|
@ -1,39 +1,46 @@
|
||||||
package main
|
package yubikey
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/GeertJohan/yubigo"
|
"github.com/GeertJohan/yubigo"
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/Luzifer/go_helpers/str"
|
"github.com/Luzifer/go_helpers/str"
|
||||||
"github.com/Luzifer/nginx-sso/plugins"
|
"github.com/Luzifer/nginx-sso/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
type AuthYubikey struct {
|
||||||
registerAuthenticator(&authYubikey{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type authYubikey struct {
|
|
||||||
ClientID string `yaml:"client_id"`
|
ClientID string `yaml:"client_id"`
|
||||||
SecretKey string `yaml:"secret_key"`
|
SecretKey string `yaml:"secret_key"`
|
||||||
Devices map[string]string `yaml:"devices"`
|
Devices map[string]string `yaml:"devices"`
|
||||||
Groups map[string][]string `yaml:"groups"`
|
Groups map[string][]string `yaml:"groups"`
|
||||||
|
|
||||||
|
cookie plugins.CookieConfig
|
||||||
|
cookieStore *sessions.CookieStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(cs *sessions.CookieStore) *AuthYubikey {
|
||||||
|
return &AuthYubikey{
|
||||||
|
cookieStore: cs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthenticatorID needs to return an unique string to identify
|
// AuthenticatorID needs to return an unique string to identify
|
||||||
// this special authenticator
|
// this special authenticator
|
||||||
func (a authYubikey) AuthenticatorID() string { return "yubikey" }
|
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 plugins.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 {
|
||||||
|
Cookie plugins.CookieConfig `yaml:"cookie"`
|
||||||
Providers struct {
|
Providers struct {
|
||||||
Yubikey *authYubikey `yaml:"yubikey"`
|
Yubikey *AuthYubikey `yaml:"yubikey"`
|
||||||
} `yaml:"providers"`
|
} `yaml:"providers"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
|
@ -50,6 +57,8 @@ func (a *authYubikey) Configure(yamlSource []byte) error {
|
||||||
a.Devices = envelope.Providers.Yubikey.Devices
|
a.Devices = envelope.Providers.Yubikey.Devices
|
||||||
a.Groups = envelope.Providers.Yubikey.Groups
|
a.Groups = envelope.Providers.Yubikey.Groups
|
||||||
|
|
||||||
|
a.cookie = envelope.Cookie
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,8 +66,8 @@ func (a *authYubikey) Configure(yamlSource []byte) error {
|
||||||
// a cookie, header or other methods
|
// a cookie, header or other methods
|
||||||
// If no user was detected the plugins.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 := a.cookieStore.Get(r, strings.Join([]string{a.cookie.Prefix, a.AuthenticatorID()}, "-"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, plugins.ErrNoValidUserFound
|
return "", nil, plugins.ErrNoValidUserFound
|
||||||
}
|
}
|
||||||
|
@ -69,7 +78,7 @@ func (a authYubikey) DetectUser(res http.ResponseWriter, r *http.Request) (strin
|
||||||
}
|
}
|
||||||
|
|
||||||
// We had a cookie, lets renew it
|
// We had a cookie, lets renew it
|
||||||
sess.Options = mainCfg.Cookie.GetSessionOpts()
|
sess.Options = a.cookie.GetSessionOpts()
|
||||||
if err := sess.Save(r, res); err != nil {
|
if err := sess.Save(r, res); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
@ -90,7 +99,7 @@ func (a authYubikey) DetectUser(res http.ResponseWriter, r *http.Request) (strin
|
||||||
// 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 plugins.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"}, "-"))
|
||||||
|
|
||||||
yubiAuth, err := yubigo.NewYubiAuth(a.ClientID, a.SecretKey)
|
yubiAuth, err := yubigo.NewYubiAuth(a.ClientID, a.SecretKey)
|
||||||
|
@ -114,8 +123,8 @@ func (a authYubikey) Login(res http.ResponseWriter, r *http.Request) (string, []
|
||||||
return "", nil, plugins.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, _ := a.cookieStore.Get(r, strings.Join([]string{a.cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
||||||
sess.Options = mainCfg.Cookie.GetSessionOpts()
|
sess.Options = a.cookie.GetSessionOpts()
|
||||||
sess.Values["user"] = user
|
sess.Values["user"] = user
|
||||||
return user, nil, sess.Save(r, res)
|
return user, nil, sess.Save(r, res)
|
||||||
}
|
}
|
||||||
|
@ -123,7 +132,7 @@ func (a authYubikey) Login(res http.ResponseWriter, r *http.Request) (string, []
|
||||||
// LoginFields needs to return the fields required for this login
|
// LoginFields needs to return the fields required for this login
|
||||||
// method. If no login using this method is possible the function
|
// method. If no login using this method is possible the function
|
||||||
// needs to return nil.
|
// needs to return nil.
|
||||||
func (a authYubikey) LoginFields() (fields []plugins.LoginField) {
|
func (a AuthYubikey) LoginFields() (fields []plugins.LoginField) {
|
||||||
return []plugins.LoginField{
|
return []plugins.LoginField{
|
||||||
{
|
{
|
||||||
Label: "Yubikey One-Time-Password",
|
Label: "Yubikey One-Time-Password",
|
||||||
|
@ -136,9 +145,9 @@ func (a authYubikey) LoginFields() (fields []plugins.LoginField) {
|
||||||
|
|
||||||
// Logout is called when the user visits the logout endpoint and
|
// Logout is called when the user visits the logout endpoint and
|
||||||
// needs to destroy any persistent stored cookies
|
// needs to destroy any persistent stored cookies
|
||||||
func (a authYubikey) Logout(res http.ResponseWriter, r *http.Request) (err error) {
|
func (a AuthYubikey) Logout(res http.ResponseWriter, r *http.Request) (err error) {
|
||||||
sess, _ := cookieStore.Get(r, strings.Join([]string{mainCfg.Cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
sess, _ := a.cookieStore.Get(r, strings.Join([]string{a.cookie.Prefix, a.AuthenticatorID()}, "-")) // #nosec G104 - On error empty session is returned
|
||||||
sess.Options = mainCfg.Cookie.GetSessionOpts()
|
sess.Options = a.cookie.GetSessionOpts()
|
||||||
sess.Options.MaxAge = -1 // Instant delete
|
sess.Options.MaxAge = -1 // Instant delete
|
||||||
return sess.Save(r, res)
|
return sess.Save(r, res)
|
||||||
}
|
}
|
||||||
|
@ -148,4 +157,4 @@ func (a authYubikey) Logout(res http.ResponseWriter, r *http.Request) (err error
|
||||||
// configuration return true. If this is true the login interface
|
// configuration return true. If this is true the login interface
|
||||||
// will display an additional field for this provider for the user
|
// will display an additional field for this provider for the user
|
||||||
// to fill in their MFA token.
|
// to fill in their MFA token.
|
||||||
func (a authYubikey) SupportsMFA() bool { return false }
|
func (a AuthYubikey) SupportsMFA() bool { return false }
|
Loading…
Reference in a new issue