package auth import ( "context" "errors" "local/dndex/config" "local/dndex/storage" "net/http" "time" "github.com/google/uuid" ) func Verify(g storage.RateLimitedGraph, w http.ResponseWriter, r *http.Request) error { token, ok := getToken(r) if !ok { return errors.New("auth not found") } if !config.New().Auth { return nil } if isPublic(token, g, r) { return nil } return verifyToken(token, g, r) } func getToken(r *http.Request) (Token, bool) { if !config.New().Auth { namespaces, ok := r.URL.Query()["ns"] if ok && len(namespaces) > 0 { return Token{Namespace: namespaces[0], ID: uuid.New().String()}, true } } cookie, err := r.Cookie(AuthKey) if err != nil { return Token{}, false } obfuscated := cookie.Value var token Token err = token.Deobfuscate(obfuscated) return token, err == nil } func isPublic(token Token, g storage.RateLimitedGraph, r *http.Request) bool { return isPublicNamespace(r.Context(), g, token.Namespace) } func isPublicNamespace(ctx context.Context, g storage.RateLimitedGraph, namespace string) bool { maybePublicContainer, err := g.Get(ctx, toAuthNamespace(namespace), UserKey) if err != nil { return false } return maybePublicContainer.Title == "" } func verifyToken(token Token, g storage.RateLimitedGraph, r *http.Request) error { serverTokenContainer, err := g.Get(r.Context(), toAuthNamespace(token.Namespace), token.ID) if err != nil { return err } var serverToken Token if err := serverToken.Deobfuscate(serverTokenContainer.Title); err != nil { return err } if token.Namespace != serverToken.Namespace { return errors.New("token namespace does not match request's namespace") } modified := time.Unix(0, serverTokenContainer.Modified) if time.Since(modified) > config.New().AuthLifetime { return errors.New("token is expired") } return nil }