github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/web/auth/share_by_link.go (about) 1 package auth 2 3 import ( 4 "encoding/base64" 5 "errors" 6 "net/http" 7 8 "github.com/cozy/cozy-stack/model/permission" 9 "github.com/cozy/cozy-stack/model/session" 10 build "github.com/cozy/cozy-stack/pkg/config" 11 "github.com/cozy/cozy-stack/pkg/couchdb" 12 "github.com/cozy/cozy-stack/pkg/crypto" 13 "github.com/cozy/cozy-stack/web/middlewares" 14 "github.com/labstack/echo/v4" 15 ) 16 17 // checkPasswordForShareByLink checks the password for a share by link 18 // protected by password, and creates a cookie if the password is correct. 19 func checkPasswordForShareByLink(c echo.Context) error { 20 res := c.Response() 21 origin := c.Request().Header.Get(echo.HeaderOrigin) 22 res.Header().Set(echo.HeaderAccessControlAllowOrigin, origin) 23 res.Header().Set(echo.HeaderAccessControlAllowCredentials, "true") 24 res.Header().Add(echo.HeaderVary, echo.HeaderOrigin) 25 26 inst := middlewares.GetInstance(c) 27 permID := c.FormValue("perm_id") 28 perm, err := permission.GetByID(inst, permID) 29 if err != nil { 30 if couchdb.IsNotFoundError(err) || errors.Is(err, permission.ErrExpiredToken) { 31 return c.JSON(http.StatusNotFound, echo.Map{"error": err.Error()}) 32 } 33 return c.JSON(http.StatusInternalServerError, echo.Map{"error": err.Error()}) 34 } 35 36 hash64, _ := perm.Password.(string) 37 if len(hash64) == 0 { 38 return c.JSON(http.StatusOK, echo.Map{"password": "none"}) 39 } 40 hash, err := base64.StdEncoding.DecodeString(hash64) 41 if err != nil { 42 return c.JSON(http.StatusInternalServerError, echo.Map{"error": err.Error()}) 43 } 44 45 password := []byte(c.FormValue("password")) 46 _, err = crypto.CompareHashAndPassphrase(hash, password) 47 if err != nil { 48 msg := inst.Translate("Share by link Password Invalid") 49 return c.JSON(http.StatusForbidden, echo.Map{"error": msg}) 50 } 51 52 // Put a cookie so that later requests can use the sharecode 53 cookieName := "pass" + permID 54 cfg := crypto.MACConfig{Name: cookieName, MaxLen: 256} 55 encoded, err := crypto.EncodeAuthMessage(cfg, inst.SessionSecret(), []byte(permID), nil) 56 if err != nil { 57 return c.JSON(http.StatusInternalServerError, echo.Map{"error": err.Error()}) 58 } 59 cookie := &http.Cookie{ 60 Name: cookieName, 61 Value: string(encoded), 62 MaxAge: 0, 63 Path: "/", 64 Domain: session.CookieDomain(inst), 65 Secure: !build.IsDevRelease(), 66 HttpOnly: true, 67 SameSite: http.SameSiteLaxMode, 68 } 69 c.SetCookie(cookie) 70 71 return c.JSON(http.StatusOK, echo.Map{"password": "ok"}) 72 }