Skip to content

Dual Authentication & Seller Verification

SCOPE_ITEM: Authentication system that supports both buyer and seller roles, handles seller identity verification (KYC), and builds platform trust through verification levels and trust scores.

Decision Tree

IF: Marketplace allows anyone to become a seller. THEN: Implement self-service seller registration + KYC via PSP.

IF: Marketplace curates sellers (invite-only or application). THEN: Implement seller application flow + manual review + KYC via PSP.

IF: Marketplace is B2B only. THEN: Implement company verification (CoC/KVK lookup) + KYC via PSP.

IF: Users can be both buyer AND seller. THEN: Implement dual-role accounts with role switching.


Buyer Accounts

Registration

SCOPE_ITEM: Low-friction buyer account creation.

INCLUDES: - Email + password registration (minimum 12 characters, bcrypt cost 12). - Social login: Google OAuth 2.0, Apple Sign In. - Email verification (magic link, 24h expiry). - Basic profile: name, email (verified), optional shipping address. - Terms of service and privacy policy acceptance (timestamped).

OPTIONAL: - Phone number with SMS verification. - Profile photo upload. - Saved payment methods (stored at PSP, not in our DB).

CHECK: Social login must request minimal scopes (email, name only). CHECK: Password strength check against breached password list (HaveIBeenPwned API, k-anonymity model).

Buyer Profile Data Model

CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT UNIQUE NOT NULL,
  email_verified BOOLEAN DEFAULT false,
  password_hash TEXT,              -- null for social-only accounts
  name TEXT NOT NULL,
  avatar_url TEXT,
  phone TEXT,
  phone_verified BOOLEAN DEFAULT false,
  roles TEXT[] DEFAULT '{buyer}',  -- buyer, seller, admin
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  last_login_at TIMESTAMPTZ
);

Seller Accounts

Seller Registration Flow

SCOPE_ITEM: Seller onboarding with identity and business verification.

Buyer account exists
  └── "Become a seller" action
        └── Step 1: Business information
        │     - Business name
        │     - Business type (sole trader, BV, VOF, etc.)
        │     - CoC/KVK number (NL) or equivalent
        │     - VAT number (optional, validated format)
        │     - Business address
        └── Step 2: Identity verification (delegated to PSP)
        │     - Stripe Connect onboarding flow, OR
        │     - Mollie Connect OAuth onboarding flow
        │     - PSP collects: ID document, selfie, proof of address
        │     - PSP handles KYC compliance
        └── Step 3: Payout details
        │     - IBAN (validated format, EU banks)
        │     - Account holder name
        │     - Verified via micro-deposit or PSP verification
        └── Step 4: Seller agreement acceptance
        │     - Platform terms for sellers (timestamped)
        │     - Commission structure acknowledgement
        └── Status: Pending verification
              └── PSP webhook: verification approved → seller active
              └── PSP webhook: verification failed → notify, retry

CHECK: NEVER store identity documents (passport, ID card) in our database. KYC documents are collected and stored by the PSP (Stripe/Mollie). CHECK: IBAN validation: use iban npm package for format + checksum. CHECK: KVK number validation: 8 digits, optionally verify via KVK API.

Seller Profile Data Model

CREATE TABLE seller_profiles (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID UNIQUE REFERENCES users(id),
  business_name TEXT NOT NULL,
  business_type TEXT NOT NULL,     -- sole_trader, bv, vof, etc.
  coc_number TEXT,                 -- KVK number (NL)
  vat_number TEXT,
  business_address JSONB NOT NULL, -- {street, city, postal, country}
  psp_account_id TEXT,             -- Stripe Connect account ID or Mollie org ID
  verification_status TEXT DEFAULT 'pending',  -- pending, verified, rejected, suspended
  verification_completed_at TIMESTAMPTZ,
  payout_enabled BOOLEAN DEFAULT false,
  commission_rate NUMERIC(5,4) DEFAULT 0.10,  -- 10% default
  trust_score INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

KYC Verification (Delegated to PSP)

Stripe Connect KYC

SCOPE_ITEM: Seller verification via Stripe Connect onboarding.

INCLUDES: - Stripe Connect Express or Custom account creation. - Stripe-hosted onboarding flow (AccountLink). - Webhook handling: account.updated for verification status. - Capability checks: card_payments and transfers must be active. - Ongoing verification (Stripe may request additional info over time).

Application                      Stripe
    │                               │
    ├── Create Connect account ────▶│
    │◀── Account ID ───────────────│
    ├── Create AccountLink ────────▶│
    │◀── Onboarding URL ──────────│
    ├── Redirect seller to URL ───▶│
    │    (Stripe collects KYC)      │
    │◀── Webhook: account.updated ─│
    ├── Check capabilities          │
    ├── Enable seller if verified   │

CHECK: Use Express accounts for simplest onboarding (Stripe handles UI). CHECK: Use Custom accounts only if full white-label onboarding is required. CHECK: Handle requirements.currently_due — Stripe may require additional documents after initial verification.

Mollie Connect KYC

SCOPE_ITEM: Seller verification via Mollie Connect onboarding.

INCLUDES: - Mollie OAuth flow for seller organisation creation. - Mollie-hosted onboarding (KYC data collection). - Webhook handling for onboarding status changes. - Payment method activation per seller organisation.

CHECK: Mollie Connect supports EUR and GBP split payments. CHECK: Mollie delayed payouts up to 90 days (not full escrow licence).


Trust Scores

OPTIONAL: SCOPE_ITEM: Computed trust score for sellers based on platform activity.

Score Components

Signal Weight Description
Verification level 20% Basic (email) → Enhanced (ID + business)
Account age 10% Months active on platform
Transaction volume 15% Number of completed transactions
Review rating 25% Average rating across all reviews
Response time 10% Average message response time
Dispute rate 15% % of transactions with disputes (lower = better)
Refund rate 5% % of transactions refunded (lower = better)

Score Calculation

INCLUDES: - Computed daily via background job (BullMQ scheduled). - Score range: 0-100. - Score displayed on seller profile (as badge or level, not raw number). - Score used for: search ranking boost, featured placement eligibility, commission tier qualification.

OPTIONAL: - Score history (trend over time). - Score breakdown visible to seller (transparency). - Score-based automated actions (suspend if score drops below threshold).

Trust Levels

Level Score Range Badge Benefits
New Seller 0-20 None Standard commission, standard placement
Verified 21-50 Checkmark Slightly higher search ranking
Trusted 51-80 Star Lower commission, priority support
Top Seller 81-100 Gold star Lowest commission, featured placement

Account Security

Rate Limiting

SCOPE_ITEM: Prevent brute-force and credential stuffing attacks.

INCLUDES: - Login: 5 attempts per email per 15 minutes, then 30-minute lockout. - Registration: 3 accounts per IP per hour. - Password reset: 3 requests per email per hour. - API: 100 requests per minute per authenticated user.

Account Recovery

SCOPE_ITEM: Secure account recovery flows.

INCLUDES: - Password reset via email magic link (1-hour expiry, single use). - Account recovery invalidates all existing sessions. - Notification to user on password change (email to old + new if changed).

OPTIONAL: - Account recovery via support ticket with identity verification. - Recovery codes for MFA-enabled accounts.

Account Suspension

SCOPE_ITEM: Platform ability to suspend accounts.

INCLUDES: - Admin can suspend buyer or seller account with reason. - Suspended sellers: listings hidden, payouts paused, new orders blocked. - Suspended buyers: cannot purchase, can still view. - Suspension notification via email with reason and appeal instructions. - Appeal process: email to support, admin review, reinstate or confirm.


Data Privacy

COMPLIANCE: GDPR Article 6 — Lawful basis for processing. Buyer data: contractual necessity (purchase fulfilment). Seller data: contractual necessity (platform agreement) + legal obligation (KYC/AML via PSP).

COMPLIANCE: GDPR Article 13/14 — Information to data subjects. Privacy policy must explain: what data, why, how long, who receives it.

COMPLIANCE: GDPR Article 17 — Right to erasure. Buyer: anonymise after account deletion (retain order history for legal obligation, 7 years for financial records). Seller: anonymise after account deletion + payout completion + tax retention period (7 years NL).

COMPLIANCE: GDPR Article 20 — Right to data portability. Export: profile data, order history, messages, reviews in JSON/CSV.


Scoping Questions

CHECK: Can anyone become a seller or is it invite-only? CHECK: Can users have both buyer and seller roles simultaneously? CHECK: What business types are accepted (sole traders, companies, both)? CHECK: Is business registration (KVK/CoC) verification required? CHECK: Which PSP for KYC delegation (Stripe Connect or Mollie Connect)? CHECK: Is a trust score system desired? CHECK: What are the account suspension and appeal policies? CHECK: Are there geographic restrictions on sellers?