LEX — AI Legal Platform for Law Firms

AI-powered legal analysis platform for law firms and corporate counsel.

Features

Resources

Blog Articles

Technology

Built on AWS (EC2, Bedrock Claude AI, ALB, WAF, S3, ACM, KMS). PostgreSQL, Redis, Qdrant vector database. TypeScript, React, Node.js.

Start free — 50 credits on registration. Sign up

TECH 7 min

Authentication via Diia: How We Integrated National Digital Identity into a Legal Platform

A passport on your smartphone — now the key to legal AI. We integrated Diia.Signature for authentication: deep link on mobile, QR code on desktop, ECDSA + SHA256 for hashing, and lawyers verify their identity with the same app they use to show documents at checkpoints. No passwords. No registration. One tap — and you are in.

Authentication via Diia: How We Integrated National Digital Identity

A passport on your smartphone — now the key to legal AI.


Why Diia, Not Yet Another OAuth

A legal platform works with confidential data. Google OAuth confirms you have a Gmail account. Diia confirms that you are you. The difference is fundamental: Diia is tied to a real document — a passport, ID card, or qualified electronic signature.

For a legal platform where attorney-client privilege and party identification are not optional but required by law, this is the only appropriate level of verification.

Architecture: Two Flows

Mobile (Deep Link)

  1. User taps "Sign in with Diia"
  2. Backend generates requestId (ECDSA + SHA256, base64)
  3. Deep link diia:// opens with session parameters
  4. Diia app shows an authorization request
  5. User confirms → Diia sends a callback with data
  6. Backend verifies the signature, creates a JWT session

Desktop (QR Code)

  1. Backend requests a session from Diia API (api2s.diia.gov.ua)
  2. Receives a deep link → converts to QR code
  3. User scans QR with the Diia app on their phone
  4. From there — the same flow: confirmation → callback → JWT

Cryptography: Why ECDSA

The Diia API requires hashing requestId via ECDSA with SHA256. Not HMAC, not RSA — specifically ECDSA. This is the electronic signature standard in Ukraine (DSTU 4145), and Diia follows it.

requestId = base64(ECDSA_SHA256(branchId + offerId + requestId))

Every request is unique. Every signature is verified. Replay attacks are impossible.

What We Get from Diia

After successful authentication:

| Field | Description | |——-|————-| | Full name | Last name, first name, patronymic | | Date of birth | From the document | | Tax ID (IPN) | Individual tax number | | Document series/number | Passport or ID card | | Photo | From the document (optional) |

This is sufficient for full identification on a legal platform — and for future ERAU integration (attorney verification by tax ID).

Security

UX: One Tap Instead of a Form

On mobile:

On desktop:

No passwords. No registration forms. No "confirm your email." The same app you use to show your ID at a checkpoint — is now your key to legal AI.

Three Authentication Methods

LEX AI now supports three independent sign-in methods:

| Method | Trust Level | Best For | |——–|————|———-| | Google OAuth | Basic | Quick start, exploration | | Authentik SSO | Corporate | Law firms, organizations | | Diia | Government | Full identification, attorneys |

The lawyer chooses their level. The platform adapts.


Production Post-Mortem: Redis + Nginx

After deploying to production behind the AWS Application Load Balancer, authentication via Diia stopped working. Completely. Users tapped "Sign in with Diia" — and got an error.

The root causes turned out to be two, and both were infrastructure-related.

First: Redis key mismatch. During Diia session initiation we stored the state with one prefix, but during the callback we read with a different one. Redis silently returned null, the backend considered the session invalid and rejected the callback. The fix was unifying key prefixes in one place.

Second: Nginx was overwriting X-Forwarded-Proto. The ALB correctly passed https, but Nginx in its configuration forcefully set http. The callback URL was formed with the HTTP scheme, Diia rejected it as non-matching the registered redirect URI. The solution — Nginx now passes through the original header from the load balancer instead of substituting its own.

Both issues were not reproducible locally, because the dev environment has no ALB and Redis prefixes matched by accident. A reminder: staging should match production as closely as possible.