mirror of
https://github.com/Luzifer/nginx-sso.git
synced 2024-12-20 12:51:17 +00:00
Duo MFA, clean up & documentation
This commit is contained in:
parent
0e511023f0
commit
416af9eed8
3 changed files with 47 additions and 17 deletions
20
README.md
20
README.md
|
@ -188,6 +188,26 @@ attributes:
|
|||
<mapping of attributes>
|
||||
```
|
||||
|
||||
#### Duo
|
||||
|
||||
This provider needs a configuration to function correctly:
|
||||
|
||||
```yaml
|
||||
mfa:
|
||||
duo:
|
||||
# Get your ikey / skey / host from https://duo.com/docs/duoweb#first-steps
|
||||
ikey: "<IKEY>"
|
||||
skey: "<SKEY>"
|
||||
host: "<API HOST>"
|
||||
user_agent: "nginx-sso"
|
||||
```
|
||||
|
||||
The corresponding expected MFA configuration is as following:
|
||||
|
||||
```yaml
|
||||
provider: duo
|
||||
```
|
||||
|
||||
#### Google Authenticator
|
||||
|
||||
The provider name here is `google` while the only supported argument at the moment is `secret`. The secret is what you need to provide to your users for them to add the config to their authenticator. (It MUST be base32 encoded!)
|
||||
|
|
|
@ -47,7 +47,7 @@ mfa:
|
|||
ikey: "IKEY"
|
||||
skey: "SKEY"
|
||||
host: "HOST"
|
||||
userAgent: "nginx-sso"
|
||||
user_agent: "nginx-sso"
|
||||
|
||||
providers:
|
||||
# Authentication against an Atlassian Crowd directory server
|
||||
|
|
36
mfa_duo.go
36
mfa_duo.go
|
@ -2,22 +2,27 @@ package main
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/duosecurity/duo_api_golang"
|
||||
"github.com/duosecurity/duo_api_golang/authapi"
|
||||
"github.com/pkg/errors"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
const mfaDuoResponseAllow = "allow"
|
||||
const mfaDuoRequestTimeout = 10 * time.Second
|
||||
|
||||
func init() {
|
||||
registerMFAProvider(&mfaDuo{})
|
||||
}
|
||||
|
||||
type mfaDuo struct {
|
||||
Ikey string `yaml:"ikey"`
|
||||
Skey string `yaml:"skey"`
|
||||
IKey string `yaml:"ikey"`
|
||||
SKey string `yaml:"skey"`
|
||||
Host string `yaml:"host"`
|
||||
UserAgent string `yaml:"userAgent"`
|
||||
UserAgent string `yaml:"user_agent"`
|
||||
}
|
||||
|
||||
// ProviderID needs to return an unique string to identify
|
||||
|
@ -43,8 +48,8 @@ func (m *mfaDuo) Configure(yamlSource []byte) (err error) {
|
|||
return errProviderUnconfigured
|
||||
}
|
||||
|
||||
m.Ikey = envelope.MFA.Duo.Ikey
|
||||
m.Skey = envelope.MFA.Duo.Skey
|
||||
m.IKey = envelope.MFA.Duo.IKey
|
||||
m.SKey = envelope.MFA.Duo.SKey
|
||||
m.Host = envelope.MFA.Duo.Host
|
||||
m.UserAgent = envelope.MFA.Duo.UserAgent
|
||||
return nil
|
||||
|
@ -59,8 +64,8 @@ func (m mfaDuo) ValidateMFA(res http.ResponseWriter, r *http.Request, user strin
|
|||
if c.Provider != m.ProviderID() {
|
||||
continue
|
||||
}
|
||||
ip := r.Header.Get("X-Real-IP")
|
||||
duo := authapi.NewAuthApi(*duoapi.NewDuoApi(m.Ikey,m.Skey,m.Host,m.UserAgent,duoapi.SetTimeout(10*time.Second)))
|
||||
remoteIP := r.Header.Get("X-Real-IP")
|
||||
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 {
|
||||
keyInput = values[0]
|
||||
|
@ -68,13 +73,19 @@ func (m mfaDuo) ValidateMFA(res http.ResponseWriter, r *http.Request, user strin
|
|||
}
|
||||
//Check if MFA token provided and fallover to push if not supplied
|
||||
if keyInput != "" {
|
||||
auth, _ := duo.Auth("passcode",authapi.AuthUsername(user),authapi.AuthPasscode(keyInput),authapi.AuthIpAddr(ip))
|
||||
if auth.Response.Result == "allow" {
|
||||
auth, err := duo.Auth("passcode", authapi.AuthUsername(user), authapi.AuthPasscode(keyInput), authapi.AuthIpAddr(remoteIP))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Unable to authenticate with Duo.")
|
||||
}
|
||||
if auth.Response.Result == mfaDuoResponseAllow {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
auth, _ := duo.Auth("auto",authapi.AuthUsername(user),authapi.AuthDevice("auto"),authapi.AuthIpAddr(ip))
|
||||
if auth.Response.Result == "allow" {
|
||||
auth, err := duo.Auth("auto", authapi.AuthUsername(user), authapi.AuthDevice("auto"), authapi.AuthIpAddr(remoteIP))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Unable to authenticate with Duo.")
|
||||
}
|
||||
if auth.Response.Result == mfaDuoResponseAllow {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -83,4 +94,3 @@ func (m mfaDuo) ValidateMFA(res http.ResponseWriter, r *http.Request, user strin
|
|||
// Report this provider was not able to verify the MFA request
|
||||
return errNoValidUserFound
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue