From 8865aaefaf83c0e016ac55163843aee4641ce2c4 Mon Sep 17 00:00:00 2001 From: Namekuji Date: Sun, 4 Dec 2022 14:50:55 -0500 Subject: [PATCH] refactor getting session --- audon-fe/src/views/LoginView.vue | 2 +- error.go | 2 +- oauth.go | 50 +++++++++++++-------------- room.go | 13 +++---- server.go | 59 ++++++++++++++++---------------- 5 files changed, 59 insertions(+), 67 deletions(-) diff --git a/audon-fe/src/views/LoginView.vue b/audon-fe/src/views/LoginView.vue index 0d47611..24fb686 100644 --- a/audon-fe/src/views/LoginView.vue +++ b/audon-fe/src/views/LoginView.vue @@ -46,7 +46,7 @@ export default { return; } try { - const response = await axios.postForm("/api/login", { + const response = await axios.postForm("/app/login", { server: this.server, }); if (response.status === 201) { diff --git a/error.go b/error.go index 1da0b5a..131d789 100644 --- a/error.go +++ b/error.go @@ -9,7 +9,7 @@ import ( var ( ErrInvalidRequestFormat = echo.NewHTTPError(http.StatusBadRequest, "invalid_request_format") - ErrInvalidCookie = echo.NewHTTPError(http.StatusBadRequest, err_invalid_cookie.Error()) + ErrInvalidSession = echo.NewHTTPError(http.StatusBadRequest) ErrSessionNotAvailable = echo.NewHTTPError(http.StatusInternalServerError, "session_not_available") ) diff --git a/oauth.go b/oauth.go index abd3dff..b4c4b17 100644 --- a/oauth.go +++ b/oauth.go @@ -6,15 +6,14 @@ import ( "net/url" "time" - "github.com/gorilla/sessions" "github.com/labstack/echo/v4" mastodon "github.com/mattn/go-mastodon" "github.com/oklog/ulid/v2" "go.mongodb.org/mongo-driver/mongo" ) -func verifyTokenInSession(c echo.Context, sess *sessions.Session) (valid bool, err error) { - data, err := getSessionData(sess) +func verifyTokenInSession(c echo.Context) (valid bool, err error) { + data, err := getSessionData(c) if err != nil { return false, err } @@ -34,7 +33,7 @@ func verifyTokenInSession(c echo.Context, sess *sessions.Session) (valid bool, e return true, nil } -// handler for POST to /login +// handler for POST to /app/login func loginHandler(c echo.Context) (err error) { serverHost := c.FormValue("server") @@ -42,13 +41,7 @@ func loginHandler(c echo.Context) (err error) { return wrapValidationError(err) } - sess, err := getSession(c) - if err != nil { - c.Logger().Error(err) - return ErrSessionNotAvailable - } - - valid, _ := verifyTokenInSession(c, sess) + valid, _ := verifyTokenInSession(c) if !valid { serverURL := &url.URL{ Host: serverHost, @@ -83,7 +76,7 @@ func loginHandler(c echo.Context) (err error) { return c.NoContent(http.StatusNoContent) } -// handler for GET to /oauth?code=**** +// handler for GET to /app/oauth?code=**** func oauthHandler(c echo.Context) (err error) { authCode := c.QueryParam("code") if authCode == "" { @@ -93,15 +86,9 @@ func oauthHandler(c echo.Context) (err error) { return echo.NewHTTPError(http.StatusBadRequest, "authentication code needed") } - sess, err := getSession(c) + data, err := getSessionData(c) if err != nil { - c.Logger().Error(err) - return ErrSessionNotAvailable - } - - data, err := getSessionData(sess) - if err != nil { - return ErrInvalidCookie + return err } appConf, err := getAppConfig(data.MastodonConfig.Server) if err != nil { @@ -123,12 +110,6 @@ func oauthHandler(c echo.Context) (err error) { coll := mainDB.Collection(COLLECTION_USER) if result, dbErr := findUserByRemote(c.Request().Context(), string(acc.ID), acc.URL); dbErr == mongo.ErrNoDocuments { - // Create user if not yet registered - // canonic, err := nanoid.Standard(21) // Should AudonID be sortable? - // if err != nil { - // c.Logger().Error(err) - // return echo.NewHTTPError(http.StatusInternalServerError) - // } entropy := ulid.Monotonic(rand.Reader, 0) id, err := ulid.New(ulid.Timestamp(time.Now().UTC()), entropy) if err != nil { @@ -163,3 +144,20 @@ func oauthHandler(c echo.Context) (err error) { return c.Redirect(http.StatusFound, "/") // return c.Redirect(http.StatusFound, "http://localhost:5173") } + +func authMiddleware(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + data, err := getSessionData(c) + if err != nil { + return err + } + + if data.AudonID != "" { + if _, err := findUserByID(c.Request().Context(), data.AudonID); err == nil { + return next(c) + } + } + + return echo.NewHTTPError(http.StatusUnauthorized, "login_required") + } +} diff --git a/room.go b/room.go index 49fcfb3..0ea7485 100644 --- a/room.go +++ b/room.go @@ -10,6 +10,7 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) +// handler for POST to /api/room func createRoomHandler(c echo.Context) (err error) { room := new(Room) if err = c.Bind(room); err != nil { @@ -25,14 +26,9 @@ func createRoomHandler(c echo.Context) (err error) { } room.RoomID = canonic() - sess, err := getSession(c) + sessData, err := getSessionData(c) if err != nil { - c.Logger().Error(err) - return ErrSessionNotAvailable - } - sessData, err := getSessionData(sess) - if err != nil { - return ErrInvalidCookie + return err } var host *AudonUser @@ -50,7 +46,7 @@ func createRoomHandler(c echo.Context) (err error) { room.ScheduledAt = now } - // If CoHosts are already registered, retrieve their AudonID + // If CoHosts are already registered, retrieve their data from DB for i, cohost := range room.CoHost { cohostUser, err := findUserByRemote(c.Request().Context(), cohost.RemoteID, cohost.RemoteURL) if err == nil { @@ -59,7 +55,6 @@ func createRoomHandler(c echo.Context) (err error) { } room.CreatedAt = now - coll := mainDB.Collection(COLLECTION_ROOM) if _, insertErr := coll.InsertOne(c.Request().Context(), room); insertErr != nil { c.Logger().Error(insertErr) diff --git a/server.go b/server.go index 3c6988a..59f3fa3 100644 --- a/server.go +++ b/server.go @@ -97,36 +97,19 @@ func main() { cookieStore.Options.HttpOnly = false } e.Use(session.Middleware(cookieStore)) - // e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{ - // CookiePath: "/", - // TokenLookup: "header:X-XSRF-TOKEN", - // })) - e.GET("/api/verify", verifyHandler) - e.POST("/api/room", createRoomHandler) - e.POST("/api/login", loginHandler) - e.GET("/api/oauth", oauthHandler) e.Static("/", "audon-fe/dist/assets") + e.POST("/app/login", loginHandler) + e.GET("/app/oauth", oauthHandler) + e.GET("/app/verify", verifyHandler) + + api := e.Group("/api", authMiddleware) + api.POST("/room", createRoomHandler) + e.Logger.Debug(e.Start(":1323")) } -// handler for GET to /api/v1/verify -func verifyHandler(c echo.Context) (err error) { - sess, err := getSession(c) - if err != nil { - c.Logger().Error(err) - return echo.NewHTTPError(http.StatusInternalServerError) - } - - valid, _ := verifyTokenInSession(c, sess) - if !valid { - return c.NoContent(http.StatusUnauthorized) - } - - return c.NoContent(http.StatusOK) -} - func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error { return t.templates.ExecuteTemplate(w, name, data) } @@ -155,7 +138,7 @@ func getAppConfig(server string) (*mastodon.AppConfig, error) { Scheme: "https", Path: "/", } - u = u.JoinPath("api", "oauth") + u = u.JoinPath("app", "oauth") redirectURI = u.String() conf := &mastodon.AppConfig{ @@ -176,8 +159,8 @@ func getAppConfig(server string) (*mastodon.AppConfig, error) { }, nil } -func getSession(c echo.Context) (sess *sessions.Session, err error) { - sess, err = session.Get(SESSION_NAME, c) +func getSession(c echo.Context, sessionID string) (sess *sessions.Session, err error) { + sess, err = session.Get(sessionID, c) if err != nil { return nil, err } @@ -186,12 +169,18 @@ func getSession(c echo.Context) (sess *sessions.Session, err error) { } // retrieve user's session, returns invalid cookie error if failed -func getSessionData(sess *sessions.Session) (data *SessionData, err error) { +func getSessionData(c echo.Context) (data *SessionData, err error) { + sess, err := getSession(c, SESSION_NAME) + if err != nil { + c.Logger().Error(err) + return nil, ErrSessionNotAvailable + } + val := sess.Values[SESSION_DATASTORE_NAME] data, ok := val.(*SessionData) if !ok { - return nil, err_invalid_cookie + return nil, ErrInvalidSession } return data, nil @@ -199,7 +188,7 @@ func getSessionData(sess *sessions.Session) (data *SessionData, err error) { // write user's session, returns error if failed func writeSessionData(c echo.Context, data *SessionData) error { - sess, err := getSession(c) + sess, err := getSession(c, SESSION_NAME) if err != nil { return err } @@ -208,3 +197,13 @@ func writeSessionData(c echo.Context, data *SessionData) error { return sess.Save(c.Request(), c.Response()) } + +// handler for GET to /app/verify +func verifyHandler(c echo.Context) (err error) { + valid, _ := verifyTokenInSession(c) + if !valid { + return c.NoContent(http.StatusUnauthorized) + } + + return c.NoContent(http.StatusOK) +}