diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2023-10-24 08:38:40 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2023-10-24 08:38:40 +0200 |
| commit | a9927763f43d59c418b264790ccee59defe8ca29 (patch) | |
| tree | 5dfc4f1f1f29d1ef1cbca3406bf57d1667b93f76 /auth | |
| parent | ed23d402fec268e163ec895748f43e3254ba3dfd (diff) | |
refactor: Rename packages for clarityv0.3.0
Diffstat (limited to 'auth')
| -rw-r--r-- | auth/config.go | 34 | ||||
| -rw-r--r-- | auth/cookie.go | 21 | ||||
| -rw-r--r-- | auth/crypto.go | 54 | ||||
| -rw-r--r-- | auth/middlewares.go | 92 |
4 files changed, 0 insertions, 201 deletions
diff --git a/auth/config.go b/auth/config.go deleted file mode 100644 index 6a55839..0000000 --- a/auth/config.go +++ /dev/null @@ -1,34 +0,0 @@ -package auth - -import ( - "encoding/hex" - "errors" - "os" - - "github.com/martinlehoux/kagamigo/core" - "golang.org/x/exp/slog" -) - -var ( - ErrCookieBadLength = errors.New("cookie secret must be 32 bytes") -) - -type AuthConfig struct { - Domain string - CookieSecret []byte -} - -func LoadCookieSecret(cookieSecretString string) []byte { - cookiesSecret, err := hex.DecodeString(cookieSecretString) - if err != nil { - err = core.Wrap(err, "error decoding cookie secret") - slog.Error(err.Error()) - os.Exit(1) - } - if len(cookiesSecret) != 32 { - slog.Error(ErrCookieBadLength.Error()) - os.Exit(1) - } - slog.Info("cookie secret loaded") - return cookiesSecret -} diff --git a/auth/cookie.go b/auth/cookie.go deleted file mode 100644 index 61349fa..0000000 --- a/auth/cookie.go +++ /dev/null @@ -1,21 +0,0 @@ -package auth - -import ( - "fmt" - "net/http" - "time" - - "github.com/martinlehoux/kagamigo/core" -) - -func CraftCookie(id core.ID, config AuthConfig) http.Cookie { - expiresAt := time.Now().Add(24 * time.Hour) - cookieValue := encrypt(config.CookieSecret, fmt.Sprintf("%s:%d", id.String(), expiresAt.Unix())) - return http.Cookie{ - Domain: config.Domain, - Name: "authentication", - Value: cookieValue, - Expires: expiresAt, - Path: "/", - } -} diff --git a/auth/crypto.go b/auth/crypto.go deleted file mode 100644 index 254539f..0000000 --- a/auth/crypto.go +++ /dev/null @@ -1,54 +0,0 @@ -package auth - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/base64" - "errors" - - "github.com/martinlehoux/kagamigo/core" -) - -var ( - ErrEncryptedTooShort = errors.New("encrypted text is too short") -) - -func encrypt(secret []byte, plainText string) string { - block, err := aes.NewCipher(secret) - core.Expect(err, "error creating AES cipher") - - aead, err := cipher.NewGCM(block) - core.Expect(err, "error creating AEAD") - - nonce := make([]byte, aead.NonceSize()) - _, err = rand.Read(nonce) - core.Expect(err, "error generating nonce") - - return base64.URLEncoding.EncodeToString(aead.Seal(nonce, nonce, []byte(plainText), nil)) -} - -func decrypt(secret []byte, encryptedText string) (string, error) { - encryptedBytes, err := base64.URLEncoding.DecodeString(encryptedText) - if err != nil { - err = core.Wrap(err, "error decoding base64") - return "", err - } - block, err := aes.NewCipher(secret) - core.Expect(err, "error creating AES cipher") - - aead, err := cipher.NewGCM(block) - core.Expect(err, "error creating AEAD") - - nonceSize := aead.NonceSize() - if len(encryptedBytes) < nonceSize { - return "", ErrEncryptedTooShort - } - nonce, cipherText := encryptedBytes[:nonceSize], encryptedBytes[nonceSize:] - plainBytes, err := aead.Open(nil, nonce, cipherText, nil) - if err != nil { - err = core.Wrap(err, "error decrypting") - return "", err - } - return string(plainBytes), nil -} diff --git a/auth/middlewares.go b/auth/middlewares.go deleted file mode 100644 index 1534b16..0000000 --- a/auth/middlewares.go +++ /dev/null @@ -1,92 +0,0 @@ -package auth - -import ( - "context" - "errors" - "net/http" - "strconv" - "strings" - "time" - - "github.com/martinlehoux/kagamigo/core" - "golang.org/x/exp/slog" -) - -var ( - ErrUserNotLoggedIn = errors.New("user not logged in") - ErrCookieExpired = errors.New("cookie expired") - ErrBadCookie = errors.New("invalid cookie") -) - -type userContext struct{} - -func UserFromContext[U any](ctx context.Context) (U, bool) { - user, ok := ctx.Value(userContext{}).(U) - return user, ok -} - -func LoginFromContext[U core.WithLanguage](ctx context.Context) core.Login[U] { - user, ok := UserFromContext[U](ctx) - return core.LoginFromUser(user, ok) -} - -func Unauthorized(w http.ResponseWriter, err error) { - w.WriteHeader(http.StatusUnauthorized) - if err != nil { - _, err = w.Write([]byte(err.Error())) - core.Expect(err, "error writing response") - } -} - -func CookieAuthMiddleware(loadUser func(context.Context, core.ID) (any, error), config AuthConfig) func(http.Handler) http.Handler { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - cookie, err := r.Cookie("authentication") - if errors.Is(err, http.ErrNoCookie) { - next.ServeHTTP(w, r) - return - } - core.Expect(err, "error reading cookie") - - authentication, err := decrypt(config.CookieSecret, cookie.Value) - if err != nil { - err = core.Wrap(err, "error decrypting cookie") - slog.Warn(err.Error()) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - parts := strings.Split(authentication, ":") - if len(parts) != 2 { - slog.Warn(ErrBadCookie.Error()) - http.Error(w, ErrBadCookie.Error(), http.StatusBadRequest) - return - } - userId, err := core.ParseID(parts[0]) - if err != nil { - err = core.Wrap(err, "error parsing user id") - slog.Warn(err.Error()) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - expiresAtSeconds, err := strconv.Atoi(parts[1]) - if err != nil { - err = core.Wrap(err, "error parsing expires at") - slog.Warn(err.Error()) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - expiresAt := time.Unix(int64(expiresAtSeconds), 0) - if time.Now().After(expiresAt) { - slog.Warn(ErrCookieExpired.Error()) - http.Error(w, ErrCookieExpired.Error(), http.StatusUnauthorized) - return - } - user, err := loadUser(ctx, userId) - core.Expect(err, "error loading user") - - ctx = context.WithValue(ctx, userContext{}, user) - next.ServeHTTP(w, r.WithContext(ctx)) - }) - } -} |
