session validation/invalidation
This commit is contained in:
parent
1c0e541c89
commit
562ed2e015
4 changed files with 19 additions and 6 deletions
|
@ -483,7 +483,7 @@ func staticHandler() http.Handler {
|
||||||
|
|
||||||
func enforceSession(app *model.AppState, next http.Handler) http.Handler {
|
func enforceSession(app *model.AppState, next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
session, err := controller.GetSessionFromRequest(app.DB, r)
|
session, err := controller.GetSessionFromRequest(app, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "WARN: Failed to retrieve session: %v\n", err)
|
fmt.Fprintf(os.Stderr, "WARN: Failed to retrieve session: %v\n", err)
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
|
|
@ -20,7 +20,7 @@ func ServeRelease(app *model.AppState, release *model.Release) http.Handler {
|
||||||
// only allow authorised users to view hidden releases
|
// only allow authorised users to view hidden releases
|
||||||
privileged := false
|
privileged := false
|
||||||
if !release.Visible {
|
if !release.Visible {
|
||||||
session, err := controller.GetSessionFromRequest(app.DB, r)
|
session, err := controller.GetSessionFromRequest(app, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "WARN: Failed to retrieve session: %v\n", err)
|
fmt.Fprintf(os.Stderr, "WARN: Failed to retrieve session: %v\n", err)
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"arimelody-web/log"
|
||||||
"arimelody-web/model"
|
"arimelody-web/model"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
@ -15,7 +16,7 @@ import (
|
||||||
|
|
||||||
const TOKEN_LEN = 64
|
const TOKEN_LEN = 64
|
||||||
|
|
||||||
func GetSessionFromRequest(db *sqlx.DB, r *http.Request) (*model.Session, error) {
|
func GetSessionFromRequest(app *model.AppState, r *http.Request) (*model.Session, error) {
|
||||||
sessionCookie, err := r.Cookie(model.COOKIE_TOKEN)
|
sessionCookie, err := r.Cookie(model.COOKIE_TOKEN)
|
||||||
if err != nil && err != http.ErrNoCookie {
|
if err != nil && err != http.ErrNoCookie {
|
||||||
return nil, errors.New(fmt.Sprintf("Failed to retrieve session cookie: %v", err))
|
return nil, errors.New(fmt.Sprintf("Failed to retrieve session cookie: %v", err))
|
||||||
|
@ -25,14 +26,26 @@ func GetSessionFromRequest(db *sqlx.DB, r *http.Request) (*model.Session, error)
|
||||||
|
|
||||||
if sessionCookie != nil {
|
if sessionCookie != nil {
|
||||||
// fetch existing session
|
// fetch existing session
|
||||||
session, err = GetSession(db, sessionCookie.Value)
|
session, err = GetSession(app.DB, sessionCookie.Value)
|
||||||
|
|
||||||
if err != nil && !strings.Contains(err.Error(), "no rows") {
|
if err != nil && !strings.Contains(err.Error(), "no rows") {
|
||||||
return nil, errors.New(fmt.Sprintf("Failed to retrieve session: %v", err))
|
return nil, errors.New(fmt.Sprintf("Failed to retrieve session: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if session != nil {
|
if session != nil {
|
||||||
// TODO: consider running security checks here (i.e. user agent mismatches)
|
if session.UserAgent != r.UserAgent() {
|
||||||
|
msg := "Session user agent mismatch. A cookie may have been hijacked!"
|
||||||
|
if session.Account != nil {
|
||||||
|
account, _ := GetAccountByID(app.DB, session.Account.ID)
|
||||||
|
msg += " (Account \"" + account.Username + "\")"
|
||||||
|
}
|
||||||
|
app.Log.Warn(log.TYPE_ACCOUNT, msg)
|
||||||
|
err = DeleteSession(app.DB, session.Token)
|
||||||
|
if err != nil {
|
||||||
|
app.Log.Warn(log.TYPE_ACCOUNT, "Failed to delete affected session")
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ func ServeGateway(app *model.AppState, release *model.Release) http.Handler {
|
||||||
// only allow authorised users to view hidden releases
|
// only allow authorised users to view hidden releases
|
||||||
privileged := false
|
privileged := false
|
||||||
if !release.Visible {
|
if !release.Visible {
|
||||||
session, err := controller.GetSessionFromRequest(app.DB, r)
|
session, err := controller.GetSessionFromRequest(app, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "WARN: Failed to retrieve session: %v\n", err)
|
fmt.Fprintf(os.Stderr, "WARN: Failed to retrieve session: %v\n", err)
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue