Skip to content

Instantly share code, notes, and snippets.

@egbertp
Created July 23, 2018 20:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save egbertp/682350fa9f1ea42705fbc30f32152e99 to your computer and use it in GitHub Desktop.
Save egbertp/682350fa9f1ea42705fbc30f32152e99 to your computer and use it in GitHub Desktop.
Authentication done in Buffalo v0.12.3; using Azure AD as the authentication provider
package actions
import (
"math"
"os"
"github.com/gobuffalo/buffalo"
"github.com/gobuffalo/pop"
"github.com/gobuffalo/pop/nulls"
"github.com/gorilla/sessions"
"github.com/markbates/going/defaults"
"github.com/markbates/goth"
"github.com/markbates/goth/gothic"
"github.com/markbates/goth/providers/azuread"
"github.com/pkg/errors"
"gitlab.com/egbertp/openvpn_management/models"
)
func init() {
// FIX 3
// The standard Goth SessionStore is not big enough to hold all the data from the OpenID connect provider
// gothic.Store = App().SessionStore
store := sessions.NewFilesystemStore(os.TempDir(), []byte("openvpn-management"))
// set the maxLength of the cookies stored on the disk to a larger number to prevent issues with:
// securecookie: the value is too long
// when using OpenID Connect , since this can contain a large amount of extra information in the id_token
// Note, when using the FilesystemStore only the session.ID is written to a browser cookie, so this is explicit for the storage on disk
// See: https://github.com/markbates/goth/issues/133
store.MaxLength(math.MaxInt64)
gothic.Store = store
goth.UseProviders(
// FIX 1
// The next line is generated by buffalo generate goth-auth azuread; this line misses the last parameter.
// azuread.New(os.Getenv("AZUREAD_KEY"), os.Getenv("AZUREAD_SECRET"), fmt.Sprintf("%s%s", App().Host, "/auth/azuread/callback")),
// I've added the fourth parameter 'nil' as shown in https://github.com/markbates/goth/blob/master/examples/main.go#L84
// FIX 2
// I've also hardcoded the hostname to be http://localhost:3000. Otherwise I keep getting an error saying: "could not find a matching session for this request"
// more details: https://github.com/markbates/goth/issues/94
azuread.New(os.Getenv("AZUREAD_KEY"), os.Getenv("AZUREAD_SECRET"), "http://localhost:3000/auth/azuread/callback", nil),
)
}
func AuthCallback(c buffalo.Context) error {
gu, err := gothic.CompleteUserAuth(c.Response(), c.Request())
if err != nil {
return c.Error(401, err)
}
// c.Logger()
tx := c.Value("tx").(*pop.Connection)
c.LogField("tx", tx)
q := tx.Where("provider = ? and provider_id = ?", gu.Provider, gu.UserID)
exists, err := q.Exists("users")
if err != nil {
return errors.WithStack(err)
}
u := &models.User{}
if exists {
if err = q.First(u); err != nil {
return errors.WithStack(err)
}
}
u.Name = defaults.String(gu.Name, gu.NickName)
u.Provider = gu.Provider
u.ProviderID = gu.UserID
u.Email = nulls.NewString(gu.Email)
if err = tx.Save(u); err != nil {
return errors.WithStack(err)
}
c.Session().Set("current_user_id", u.ID)
if err = c.Session().Save(); err != nil {
return errors.WithStack(err)
}
c.Flash().Add("success", "You have been logged in")
return c.Redirect(302, "/")
}
func AuthDestroy(c buffalo.Context) error {
c.Session().Clear()
c.Flash().Add("success", "You have been logged out")
return c.Redirect(302, "/")
}
func SetCurrentUser(next buffalo.Handler) buffalo.Handler {
return func(c buffalo.Context) error {
if uid := c.Session().Get("current_user_id"); uid != nil {
u := &models.User{}
tx := c.Value("tx").(*pop.Connection)
if err := tx.Find(u, uid); err != nil {
return errors.WithStack(err)
}
c.Set("current_user", u)
}
return next(c)
}
}
func Authorize(next buffalo.Handler) buffalo.Handler {
return func(c buffalo.Context) error {
if uid := c.Session().Get("current_user_id"); uid == nil {
c.Flash().Add("danger", "You must be authorized to see that page")
return c.Redirect(302, "/")
}
return next(c)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment