pronounsfu/backend/routes/auth/oauth.go

46 lines
1.1 KiB
Go

package auth
import (
"context"
"crypto/rand"
"encoding/base64"
"github.com/mediocregopher/radix/v4"
)
// numStates is the number of CSRF states stored in Redis at any one time.
// This must be an integer.
const numStates = "1000"
// setCSRFState generates a random string to use as state, then stores that in Redis.
func (s *Server) setCSRFState(ctx context.Context) (string, error) {
state := RandBase64(32)
err := s.DB.MultiCmd(ctx,
radix.Cmd(nil, "LPUSH", "csrf", state),
radix.Cmd(nil, "LTRIM", "csrf", "0", numStates),
)
return state, err
}
// validateCSRFState checks if the given state exists in Redis.
func (s *Server) validateCSRFState(ctx context.Context, state string) (matched bool, err error) {
var num int
err = s.DB.Redis.Do(ctx, radix.Cmd(&num, "LREM", "csrf", "1", state))
if err != nil {
return
}
return num > 0, nil
}
// RandBase64 returns a string of random bytes encoded in raw base 64.
func RandBase64(size int) string {
b := make([]byte, size)
_, err := rand.Read(b)
if err != nil {
panic(err)
}
return base64.RawURLEncoding.EncodeToString(b)
}