Created
July 23, 2018 20:05
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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