Skip to main content

Security and Authentication

This page explains how OpenLynk protects your data, authenticates SDK requests, and enforces tenant isolation.

API Key Security

Each app in OpenLynk has its own API key, prefixed with ol_. API keys authenticate mobile SDK traffic and supported server-side REST calls (for example creating invite links from an admin backend).

Server-Side Hashing

OpenLynk never stores API keys in plaintext. When a key is generated, it is hashed using SHA-256 before storage. When the SDK sends a request with the key in the x-openlynk-sdk-key header (or Authorization: Bearer), the server hashes the incoming key and compares it against the stored hash.

warning

Because keys are hashed server-side, OpenLynk cannot retrieve your key if you lose it. Store your API key securely when it is first generated. If you lose it, you must rotate the key from the dashboard.

Per-App Key Isolation

Each API key is tied to a single app. A key for App A cannot be used to create links, restore pending links, or access any data belonging to App B. For authenticated routes, the server derives the app from the API key (request-body appId is not used for authorization).

Key Rotation

You can rotate an API key from the OpenLynk dashboard at any time:

  1. The old key is revoked immediately — any SDK instances using the old key will receive 401 Unauthorized responses
  2. A new key is generated and displayed once
  3. Update your app with the new key and redeploy

There is no grace period. Rotation is instantaneous.

caution

After rotating a key, all deployed app instances using the old key will stop working until they are updated with the new key. Plan key rotations during maintenance windows or use a remote configuration system to update keys without redeploying.

Multi-Tenant Data Isolation

OpenLynk is a multi-tenant system. Data isolation is enforced at multiple levels.

Organization as Tenant Boundary

The organization is the top-level tenant boundary in OpenLynk:

Organization
└── App 1
│ └── Links
│ └── Analytics
│ └── API Key
└── App 2
└── Links
└── Analytics
└── API Key
  • Each user belongs to exactly one organization
  • Each app belongs to exactly one organization
  • Each link belongs to exactly one app

Row Level Security (RLS)

OpenLynk uses Supabase with Row Level Security (RLS) policies to enforce data boundaries at the database level. RLS ensures that:

  • Dashboard queries only return data belonging to the authenticated user's organization
  • API key-authenticated requests only access data belonging to the key's app
  • No application-level bug can leak data across tenant boundaries, because the database itself enforces isolation

Privacy

OpenLynk is designed with user privacy in mind:

IP Address Handling

IP addresses are hashed using SHA-256 before storage. The hash is used for:

  • Deferred deep link matching (IP + user-agent triangulation)
  • Geographic analytics (country-level, derived before hashing)

The plaintext IP address is never written to the database.

Device Fingerprints

Device fingerprints used for deferred deep linking are generated client-side by the SDK. The fingerprint is based on device characteristics and does not include personally identifiable information. Fingerprints are stored with pending link records and automatically deleted when the pending link is restored or expires.

Pending link records are automatically expired and removed after 30 days. This limits the window during which device matching data is retained.

Service Role Access

Link resolution (the process of redirecting a user when they click a deep link) requires read access to app and link data without user authentication, since the person clicking the link is not an OpenLynk user.

Link resolution uses a service role with minimal permissions:

  • Read-only access to apps, links, and custom domains
  • Write access limited to click analytics and pending link records
  • No access to organization data, user data, or API keys

Membership Model

The OpenLynk membership model is straightforward:

EntityBelongs ToConstraint
UserOrganizationOne organization per user
AppOrganizationOne organization per app
LinkAppOne app per link
API KeyAppOne key per app at a time
Custom DomainAppOne app per domain

This model ensures clear ownership boundaries and simplifies access control.

What's Next?