Adding a Legacy Identity Provider
As a permissionless protocol, Zapf lets anyone integrate a new Legacy Identity Provider (LIDP).
Whether you are adding GitHub, Slack, Telegram, or a custom enterprise authentication system, the process follows a standardized, open pattern.
Understanding the Role
When you add a LIDP, you are teaching an Zap Settlement Provider (ZSP) how to verify ownership of that platform and how to construct the standardized Nostr events (Identity Connection and ZSP Attestation) that prove it.
The Integration Pattern
If you are developing a new LIDP integration for the official open-source Zapf reference ZSP (or your own custom implementation), you must implement these four steps:
1. The Verification Flow (OAuth or OTP)
You need to write the logic that securely proves the user owns the identifier.
For OAuth Providers (e.g., GitHub, Google, LinkedIn):
- Register an OAuth application with the provider to get a Client ID and Secret.
- Implement the standard OAuth 2.0 authorization code flow.
- Ensure you request the minimum necessary scopes (usually just
read:useroremail). - Fetch the user's canonical identifier (e.g., their numeric GitHub ID or primary email).
For OTP Providers (e.g., SMS, Custom App Push):
- Integrate a reliable delivery mechanism (like Twilio, SendGrid, or Firebase).
- Implement rate limiting (CRITICAL) to prevent abuse.
- Generate and verify short-lived numeric codes.
2. Identifier Normalization
Before signing any attestations, the ZSP must rigidly normalize the identifier to prevent spoofing.
- Emails must be lowercased and stripped of aliases (e.g.,
user+spam@gmail.com->user@gmail.com). - Phone numbers must be in E.164 format (e.g.,
+1234567890). - Social handles should ignore casing if the platform is case-insensitive.
3. ConnectionKey Generation
Generate the ConnectionKey for the Nostr events:
// Example logic
rawString := fmt.Sprintf("%s:%s", lidpName, normalizedIdentifier)
connectionKey := sha256(rawString)
Note: Even if you intend to publish the raw identifier in the profile content for searchability (the Public Privacy Model), the ConnectionKey must strictly be this SHA-256 hash.
4. Constructing the Evidence Payload (OAuth Only)
If your LIDP uses OAuth, you must construct an evidence object containing the Access Token and provider metadata. This is necessary for Evidence Sharing.
Use secure encryption ↗ for this payload directed at the user's public key.
5. Signing and Publishing
Finally, your ZSP code must construct the Attestation:
- Set the connection key.
- Set the user's Nostr public key.
- Set your provider string (e.g.,
"github"). - Specify the
expirationbased on the OAuth token expiry or a sensible default for OTP.
Sign the event with the ZSP's private key and publish it to the designated Nostr relays. Return the raw JSON to the user's client so they can construct their Identity Connection.