summaryrefslogtreecommitdiff
path: root/pkg/web/cookie.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/web/cookie.go')
-rw-r--r--pkg/web/cookie.go44
1 files changed, 43 insertions, 1 deletions
diff --git a/pkg/web/cookie.go b/pkg/web/cookie.go
index 1377274..4795f96 100644
--- a/pkg/web/cookie.go
+++ b/pkg/web/cookie.go
@@ -1,18 +1,28 @@
package web
import (
+ "crypto/sha256"
+ "encoding/base64"
+ "fmt"
"net/http"
+ "strings"
"github.com/xlgmokha/x/pkg/cookie"
+ "github.com/xlgmokha/x/pkg/crypt"
"github.com/xlgmokha/x/pkg/env"
+ "github.com/xlgmokha/x/pkg/pls"
"github.com/xlgmokha/x/pkg/x"
)
+var key []byte = x.Must(pls.GenerateRandomBytes(32)) // TODO:: Read fix key from environment variable
+var Signer *crypt.HMACSigner = x.New[*crypt.HMACSigner](crypt.WithKey(key), crypt.WithAlgorithm(sha256.New))
+var delimiter string = "--"
+
func NewCookie(name, value string, options ...x.Option[*http.Cookie]) *http.Cookie {
return x.New[*http.Cookie](x.Prepend[x.Option[*http.Cookie]](
options,
cookie.WithName(name),
- cookie.WithValue(value), // TODO:: digitally sign the value
+ withSignedValue(value),
cookie.WithPath("/"),
cookie.WithHttpOnly(true),
cookie.WithSecure(true),
@@ -21,6 +31,19 @@ func NewCookie(name, value string, options ...x.Option[*http.Cookie]) *http.Cook
)...)
}
+func withSignedValue(value string) x.Option[*http.Cookie] {
+ signature, err := Signer.Sign([]byte(value))
+ if err != nil {
+ return nil
+ }
+ return cookie.WithValue(fmt.Sprintf(
+ "%v%v%v",
+ value,
+ delimiter,
+ base64.URLEncoding.EncodeToString(signature),
+ ))
+}
+
func ExpireCookie(w http.ResponseWriter, name string) {
cookie.Expire(w, name,
cookie.WithPath("/"),
@@ -29,3 +52,22 @@ func ExpireCookie(w http.ResponseWriter, name string) {
cookie.WithSecure(true),
)
}
+
+func CookieValueFrom(c *http.Cookie) string {
+ segments := strings.SplitN(c.Value, delimiter, 2)
+ if len(segments) != 2 {
+ return ""
+ }
+
+ data := segments[0]
+ signature, err := base64.URLEncoding.DecodeString(segments[1])
+ if err != nil {
+ return ""
+ }
+
+ if !Signer.Verify([]byte(data), []byte(signature)) {
+ return ""
+ }
+
+ return data
+}