package middleware import ( "crypto/rand" "fmt" "math/big" "net/http" "github.com/google/uuid" "github.com/pkg/errors" ) const AnonIssuer = "anon" func WithAnonymousUser(funcs ...DefaultUserOptionFunc) DefaultUserOptionFunc { return func(opts *DefaultUserOptions) { opts.GetSubject = getAnonymousSubject opts.GetPreferredUsername = getAnonymousPreferredUsername opts.Issuer = AnonIssuer for _, fn := range funcs { fn(opts) } } } func getAnonymousSubject(r *http.Request) (string, error) { uuid, err := uuid.NewUUID() if err != nil { return "", errors.Wrap(err, "could not generate uuid for anonymous user") } subject := fmt.Sprintf("%s-%s", AnonIssuer, uuid.String()) return subject, nil } func getAnonymousPreferredUsername(r *http.Request) (string, error) { preferredUsername, err := generateRandomPreferredUsername(8) if err != nil { return "", errors.Wrap(err, "could not generate preferred username for anonymous user") } return preferredUsername, nil } func generateRandomPreferredUsername(size int) (string, error) { var letters = []rune("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") max := big.NewInt(int64(len(letters))) b := make([]rune, size) for i := range b { idx, err := rand.Int(rand.Reader, max) if err != nil { return "", errors.WithStack(err) } b[i] = letters[idx.Int64()] } return fmt.Sprintf("Anon %s", string(b)), nil }