1
0
Fork 0
mirror of https://github.com/Luzifer/nginx-sso-auth-supercookie.git synced 2024-12-22 12:11:18 +00:00

Initial version

This commit is contained in:
Knut Ahlers 2019-02-23 19:26:11 +01:00
commit 8cebe8cf6d
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
5 changed files with 179 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
auth-supercookie.so

9
Makefile Normal file
View file

@ -0,0 +1,9 @@
default: build
build:
docker run --rm -i \
-e CGO_ENABLED=1 \
-v "$(CURDIR):/go/src/github.com/Luzifer/auth-supercookie" \
-w /go/src/github.com/Luzifer/auth-supercookie \
golang:alpine \
sh -c 'apk add --update build-base git && go get -d && go build -buildmode=plugin -o auth-supercookie.so'

6
go.mod Normal file
View file

@ -0,0 +1,6 @@
module nginx-sso-auth-supercookie
require (
github.com/Luzifer/nginx-sso v0.15.2-0.20190221232702-e9bff08810b8
gopkg.in/yaml.v2 v2.2.2
)

46
go.sum Normal file
View file

@ -0,0 +1,46 @@
github.com/GeertJohan/yubigo v0.0.0-20140521141543-b1764f04aa9b/go.mod h1:njRCDrl+1RQ/A/+KVU8Ho2EWAxUSkohOWczdW3dzDG0=
github.com/Luzifer/go_helpers v2.8.1+incompatible h1:9YvrAn7pU2viK5vRpAnI+0gyz+Tw8rxWHVIYHi642zk=
github.com/Luzifer/go_helpers v2.8.1+incompatible/go.mod h1:5yUSe0FS7lIx1Uzmt0R3tdPFrSSaPfiCqaIA6u0Zn4Y=
github.com/Luzifer/nginx-sso v0.15.1 h1:thGZrJGUoDKeYIVANt5klgEFRFsoWvLl1bzzREVhtKg=
github.com/Luzifer/nginx-sso v0.15.1/go.mod h1:QN9la0mXv/jgh0JplABNvPM23M9tjMqAB6ndLpuEmr8=
github.com/Luzifer/nginx-sso v0.15.2-0.20190221231245-83fcc4d0fefd h1:fr6KofAAoLZv4fZnOTqngq+d5TjtuBSSSFs2w861x/4=
github.com/Luzifer/nginx-sso v0.15.2-0.20190221231245-83fcc4d0fefd/go.mod h1:QN9la0mXv/jgh0JplABNvPM23M9tjMqAB6ndLpuEmr8=
github.com/Luzifer/nginx-sso v0.15.2-0.20190221232702-e9bff08810b8 h1:5M+iFKEuRpx+CDpIPkxJYvLlUn4i4O/8H4lR0ez7waE=
github.com/Luzifer/nginx-sso v0.15.2-0.20190221232702-e9bff08810b8/go.mod h1:QN9la0mXv/jgh0JplABNvPM23M9tjMqAB6ndLpuEmr8=
github.com/Luzifer/rconfig v2.2.0+incompatible/go.mod h1:9pet6z2+mm/UAB0jF/rf0s62USfHNolzgR6Q4KpsJI0=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/duosecurity/duo_api_golang v0.0.0-20190107154727-539434bf0d45/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo=
github.com/flosch/pongo2 v0.0.0-20181225140029-79872a7b2769/go.mod h1:tbAXHifHQWNSpWbiJHpJTZH5fi3XHhDMdP//vuz9WS4=
github.com/go-check/check v1.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
github.com/jda/go-crowd v0.0.0-20180225080536-9c6f17811dc6/go.mod h1:YapIHiLsT+0vQL2UBXLBjX+3SXYSXi2OyGgr7zXLnbc=
github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/otp v1.1.0/go.mod h1:Zad1CMQfSQZI5KLpahDiSUX4tMMREnXw98IvL1nhgMk=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/validator.v2 v2.0.0-20180514200540-135c24b11c19/go.mod h1:o4V0GXN9/CAmCsvJ0oXYZvrZOe7syiDZSN1GWGZTGzc=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

117
main.go Normal file
View file

@ -0,0 +1,117 @@
package main
import (
"net/http"
"github.com/Luzifer/go_helpers/str"
"github.com/Luzifer/nginx-sso/plugins"
yaml "gopkg.in/yaml.v2"
)
func Register(ra plugins.RegisterAuthenticatorFunc, rm plugins.RegisterMFAProviderFunc) {
ra(&authSupercookie{})
}
type authSupercookie struct {
CookieName string `yaml:"cookie_name"`
Tokens map[string]string `yaml:"tokens"`
Groups map[string][]string `yaml:"groups"`
}
// AuthenticatorID needs to return an unique string to identify
// this special authenticator
func (a authSupercookie) AuthenticatorID() string { return "supercookie" }
// 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 (a *authSupercookie) Configure(yamlSource []byte) error {
envelope := struct {
Providers struct {
SuperCookie *authSupercookie `yaml:"supercookie"`
} `yaml:"providers"`
}{}
if err := yaml.Unmarshal(yamlSource, &envelope); err != nil {
return err
}
if envelope.Providers.SuperCookie == nil {
return plugins.ErrProviderUnconfigured
}
a.CookieName = envelope.Providers.SuperCookie.CookieName
a.Tokens = envelope.Providers.SuperCookie.Tokens
a.Groups = envelope.Providers.SuperCookie.Groups
return nil
}
// DetectUser is used to detect a user without a login form from
// a cookie, header or other methods
// If no user was detected the plugins.ErrNoValidUserFound needs to be
// returned
func (a authSupercookie) DetectUser(res http.ResponseWriter, r *http.Request) (string, []string, error) {
var (
user, token string
userFound bool
)
for _, c := range r.Cookies() {
if c.Name != a.CookieName {
continue
}
for user, token = range a.Tokens {
if token == c.Value {
userFound = true
break
}
}
if userFound {
break
}
}
if !userFound {
return "", nil, plugins.ErrNoValidUserFound
}
groups := []string{}
for group, users := range a.Groups {
if str.StringInSlice(user, users) {
groups = append(groups, group)
}
}
return user, groups, nil
}
// Login is called when the user submits the login form and needs
// to authenticate the user or throw an error. If the user has
// successfully logged in the persistent cookie should be written
// in order to use DetectUser for the next login.
// If the user did not login correctly the plugins.ErrNoValidUserFound
// needs to be returned
func (a authSupercookie) Login(res http.ResponseWriter, r *http.Request) (string, []plugins.MFAConfig, error) {
return "", nil, plugins.ErrNoValidUserFound
}
// LoginFields needs to return the fields required for this login
// method. If no login using this method is possible the function
// needs to return nil.
func (a authSupercookie) LoginFields() []plugins.LoginField { return nil }
// Logout is called when the user visits the logout endpoint and
// needs to destroy any persistent stored cookies
func (a authSupercookie) Logout(res http.ResponseWriter, r *http.Request) error { return nil }
// SupportsMFA returns the MFA detection capabilities of the login
// provider. If the provider can provide mfaConfig objects from its
// configuration return true. If this is true the login interface
// will display an additional field for this provider for the user
// to fill in their MFA token.
func (a authSupercookie) SupportsMFA() bool { return false }