Add authentication middleware
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
package authentication
|
||||
|
||||
import (
|
||||
. "ersteller-lib"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
const sessionName = "session"
|
||||
const EmailKey = "email"
|
||||
const UserIdKey = "userId"
|
||||
const AuthContextKey = "authContext"
|
||||
|
||||
type AuthContext struct {
|
||||
Email string
|
||||
UserId int
|
||||
}
|
||||
|
||||
func SaveEmailAndUserIdToSessionStore(request *http.Request, writer http.ResponseWriter, store *sessions.CookieStore, email string, userId int) error {
|
||||
session, err := store.New(request, sessionName)
|
||||
if err != nil {
|
||||
LogError("Failed to create session: %v", err)
|
||||
return err
|
||||
}
|
||||
session.Values = map[interface{}]interface{}{
|
||||
EmailKey: email,
|
||||
UserIdKey: userId,
|
||||
}
|
||||
err = session.Save(request, writer)
|
||||
if err != nil {
|
||||
LogError("Failed to save session: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetUserIdAndEmailFromSessionStore(request *http.Request, store *sessions.CookieStore) (bool, *http.Request, error) {
|
||||
session, err := store.Get(request, sessionName)
|
||||
if err != nil {
|
||||
LogError("Failed to get session: %v", err)
|
||||
return false, nil, err
|
||||
}
|
||||
email, ok := session.Values[EmailKey].(string)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
userId, ok := session.Values[UserIdKey].(int)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
ctx := context.WithValue(request.Context(), AuthContextKey, AuthContext{
|
||||
Email: email,
|
||||
UserId: userId,
|
||||
})
|
||||
return true, request.WithContext(ctx), nil
|
||||
}
|
||||
|
||||
func LogoutSession(writer http.ResponseWriter, request *http.Request, sessionStore *sessions.CookieStore, redirectUrl string) {
|
||||
// Clear the session
|
||||
session, err := sessionStore.Get(request, sessionName) // Using default session name
|
||||
if err != nil {
|
||||
LogError("Failed to get session: %v", err)
|
||||
http.Redirect(writer, request, redirectUrl, http.StatusTemporaryRedirect)
|
||||
return
|
||||
}
|
||||
|
||||
session.Options.MaxAge = -1
|
||||
err = session.Save(request, writer)
|
||||
if err != nil {
|
||||
LogError("Failed to save session: %v", err)
|
||||
http.Error(writer, "Failed to clear session", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(writer, request, redirectUrl, http.StatusTemporaryRedirect)
|
||||
}
|
||||
|
||||
func Middleware(store *sessions.CookieStore, excludedPrefixes []string, redirectUrl string) MiddlewareFunc {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
Debug("Authenticating")
|
||||
if r.Method == http.MethodOptions {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
for _, prefix := range excludedPrefixes {
|
||||
if strings.HasPrefix(r.URL.Path, prefix) {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
ok, r, err := SetUserIdAndEmailFromSessionStore(r, store)
|
||||
if err != nil {
|
||||
LogError("Failed to set user id and email from session: %v", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if ok {
|
||||
next.ServeHTTP(w, r)
|
||||
} else {
|
||||
Debug("Redirecting to login because there is no session")
|
||||
http.Redirect(w, r, redirectUrl, http.StatusTemporaryRedirect)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user