58 lines
1.5 KiB
Go
58 lines
1.5 KiB
Go
package storage
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"git.ewellenr.ca/receipt_indexer/backend/internal/lcrypto"
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
// game plan. store the session token/id and a salt. then, hash them to create the csrf token. give this csrf token out to the user. when the user ends a session, it ends the session but also deletes it from the csrf store
|
|
|
|
// const csrfSaltLength = 32
|
|
// const csrfTokenLength = 128
|
|
|
|
// should be set by the hasher
|
|
|
|
type RedisCSRFStore struct {
|
|
rdb *redis.Client
|
|
hasher lcrypto.Hasher
|
|
expirationTime uint
|
|
}
|
|
|
|
func (r *RedisCSRFStore) AddCSRF(ctx context.Context, sessionToken string) (csrftoken string, err error) {
|
|
csrf, err := r.hasher.Hash(sessionToken)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
csrftoken = string(csrf)
|
|
|
|
if err = r.rdb.Set(ctx, sessionToken, csrftoken, time.Duration(r.expirationTime)).Err(); err != nil {
|
|
return "", err
|
|
}
|
|
return csrftoken, nil
|
|
}
|
|
|
|
func (r *RedisCSRFStore) RemoveCSRF(ctx context.Context, sessionToken string) error {
|
|
r.rdb.Del(ctx, sessionToken)
|
|
return nil
|
|
}
|
|
|
|
func (r *RedisCSRFStore) ValidCSRF(ctx context.Context, sessionToken string, csrfToken string) (bool, error) {
|
|
storedcsrfToken, err := r.rdb.Get(ctx, sessionToken).Result()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if err = r.rdb.ExpireXX(ctx, sessionToken, time.Duration(r.expirationTime)).Err(); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
valid, err := lcrypto.CompareHash([]byte(csrfToken), []byte(storedcsrfToken))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return valid, nil
|
|
}
|