session handler with cookies.

This commit is contained in:
Miroslav Šedivý 2021-01-29 22:22:14 +01:00
parent 546cd608c3
commit 6d59b3feff
5 changed files with 113 additions and 17 deletions

View File

@ -36,27 +36,30 @@ func New(
}
func (api *ApiManagerCtx) Route(r chi.Router) {
r.Use(api.Authenticate)
r.Post("/login", api.Login)
membersHandler := members.New(api.sessions)
r.Route("/members", membersHandler.Route)
// Authenticated area
r.Group(func(r chi.Router) {
r.Use(api.Authenticate)
roomHandler := room.New(api.sessions, api.desktop, api.capture)
r.Route("/room", roomHandler.Route)
r.Post("/logout", api.Logout)
r.Get("/whoami", api.Whoami)
r.Get("/test", func(w http.ResponseWriter, r *http.Request) {
session := auth.GetSession(r)
utils.HttpBadRequest(w, "Hi `" + session.ID() + "`, you are authenticated.")
membersHandler := members.New(api.sessions)
r.Route("/members", membersHandler.Route)
roomHandler := room.New(api.sessions, api.desktop, api.capture)
r.Route("/room", roomHandler.Route)
for path, router := range api.routers {
r.Route(path, router)
}
})
for path, router := range api.routers {
r.Route(path, router)
}
}
func (api *ApiManagerCtx) Authenticate(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
session, err := api.sessions.Authenticate(r)
session, err := api.sessions.AuthenticateRequest(r)
if err != nil {
utils.HttpUnauthorized(w, err)
} else {

80
internal/api/session.go Normal file
View File

@ -0,0 +1,80 @@
package api
import (
"time"
"net/http"
"demodesk/neko/internal/utils"
"demodesk/neko/internal/types"
"demodesk/neko/internal/http/auth"
)
type SessionLoginPayload struct {
ID string `json:"id"`
Secret string `json:"secret"`
}
type SessionWhoamiPayload struct {
ID string `json:"id"`
Profile types.MemberProfile `json:"profile"`
State types.MemberState `json:"state"`
}
func (api *ApiManagerCtx) Login(w http.ResponseWriter, r *http.Request) {
data := &SessionLoginPayload{}
if !utils.HttpJsonRequest(w, r, data) {
return
}
session, err := api.sessions.Authenticate(data.ID, data.Secret)
if err != nil {
utils.HttpUnauthorized(w, err)
return
}
http.SetCookie(w, &http.Cookie{
Name: "neko-id",
Value: session.ID(),
Expires: time.Now().Add(365 * 24 * time.Hour),
HttpOnly: false,
})
http.SetCookie(w, &http.Cookie{
Name: "neko-secret",
Value: data.Secret,
Expires: time.Now().Add(365 * 24 * time.Hour),
HttpOnly: true,
})
utils.HttpSuccess(w)
}
func (api *ApiManagerCtx) Logout(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, &http.Cookie{
Name: "neko-id",
Value: "",
Path: "/",
Expires: time.Unix(0, 0),
HttpOnly: false,
})
http.SetCookie(w, &http.Cookie{
Name: "neko-secret",
Value: "",
Path: "/",
Expires: time.Unix(0, 0),
HttpOnly: true,
})
utils.HttpSuccess(w)
}
func (api *ApiManagerCtx) Whoami(w http.ResponseWriter, r *http.Request) {
session := auth.GetSession(r)
utils.HttpSuccess(w, SessionWhoamiPayload{
ID: session.ID(),
Profile: session.GetProfile(),
State: session.GetState(),
})
}

View File

@ -7,12 +7,16 @@ import (
"demodesk/neko/internal/types"
)
func (manager *SessionManagerCtx) Authenticate(r *http.Request) (types.Session, error) {
func (manager *SessionManagerCtx) AuthenticateRequest(r *http.Request) (types.Session, error) {
id, secret, ok := getAuthData(r)
if !ok {
return nil, fmt.Errorf("no authentication provided")
}
return manager.Authenticate(id, secret)
}
func (manager *SessionManagerCtx) Authenticate(id string, secret string) (types.Session, error) {
session, ok := manager.Get(id)
if !ok {
return nil, fmt.Errorf("member not found")
@ -30,14 +34,22 @@ func (manager *SessionManagerCtx) Authenticate(r *http.Request) (types.Session,
}
func getAuthData(r *http.Request) (string, string, bool) {
// get from Cookies
cid, err1 := r.Cookie("neko-id")
csecret, err2 := r.Cookie("neko-secret")
if err1 == nil && err2 == nil {
return cid.Value, csecret.Value, true
}
// get from BasicAuth
id, secret, ok := r.BasicAuth()
if ok {
return id, secret, true
}
// get from QueryParams
id = r.URL.Query().Get("id")
secret = r.URL.Query().Get("secret")
if id != "" && secret != "" {
return id, secret, true
}

View File

@ -89,5 +89,6 @@ type SessionManager interface {
ImplicitHosting() bool
Authenticate(r *http.Request) (Session, error)
AuthenticateRequest(r *http.Request) (Session, error)
Authenticate(id string, secret string) (Session, error)
}

View File

@ -155,7 +155,7 @@ func (ws *WebSocketManagerCtx) Upgrade(w http.ResponseWriter, r *http.Request, c
return err
}
session, err := ws.sessions.Authenticate(r)
session, err := ws.sessions.AuthenticateRequest(r)
if err != nil {
ws.logger.Warn().Err(err).Msg("authentication failed")