# NIP-05 Badge Component ## Overview The NIP-05 Badge component is a live Twig component that verifies NIP-05 identifiers (DNS-based internet identifiers for Nostr keys) and displays them as a verified badge when the verification succeeds. ## Features - ✅ **Automatic verification**: Fetches and validates `.well-known/nostr.json` from the specified domain - ✅ **Security compliant**: Follows NIP-05 security constraints (no redirect following) - ✅ **Cached results**: Verification results are cached for 1 hour to reduce network requests - ✅ **Relay discovery**: Extracts and stores relay information when available - ✅ **Display formatting**: Automatically formats root identifiers (`_@domain.com` → `domain.com`) - ✅ **Graceful failures**: Shows nothing when verification fails (no badge displayed) - ✅ **Character validation**: Only accepts valid NIP-05 local-part characters (a-z0-9-_.) ## Usage ### Basic Usage ```twig {# In any Twig template #} ``` ### With Author Metadata ```twig
{{ author.name ?? 'Anonymous' }} {% if author.nip05 is defined and author.pubkey is defined %} {% endif %}
``` ### In a Card Component ```twig
{{ author.name }}

{{ author.name }}

``` ## Props | Prop | Type | Required | Description | |------|------|----------|-------------| | `nip05` | `string` | Yes | The NIP-05 identifier (e.g., "bob@example.com") | | `pubkeyHex` | `string` | Yes | The public key in hex format (64 characters) | ## Verification Process The component performs the following verification steps: 1. **Validates identifier format**: Checks that the local part contains only `a-z0-9-_.` 2. **Splits identifier**: Extracts local part and domain from the identifier 3. **Fetches well-known document**: Makes a GET request to `https:///.well-known/nostr.json?name=` 4. **Rejects redirects**: Any HTTP redirect causes verification to fail (NIP-05 security requirement) 5. **Validates response**: Checks for valid JSON with required `names` field 6. **Matches public key**: Compares the returned pubkey with the expected pubkey 7. **Validates hex format**: Ensures pubkey is in hex format (not npub) 8. **Extracts relays**: Optionally retrieves relay information if present ## Display Behavior ### When Verified ✅ Shows a green badge with a checkmark icon and the identifier: - Regular identifier: `bob@example.com` - Root identifier: `_@example.com` displays as `example.com` - Tooltip shows relay count when available ### When Not Verified ❌ Shows nothing (no badge rendered) ## Cache Behavior - Verification results are cached for **1 hour** in Redis - Cache key format: `nip05_{md5(identifier)}` - Failed verifications are also cached to prevent repeated failed requests ## Security Features - ✅ **No redirect following**: HTTP redirects are blocked per NIP-05 spec - ✅ **Timeout protection**: 5-second timeout on HTTP requests - ✅ **Format validation**: Strict validation of identifier format - ✅ **Hex-only pubkeys**: Rejects npub format keys - ✅ **Case-insensitive matching**: Handles case variations properly ## Styling The component includes built-in styles that can be customized: ```css .nip05-badge { /* Green badge with checkmark */ background-color: rgba(34, 197, 94, 0.1); border: 1px solid rgba(34, 197, 94, 0.3); color: rgb(22, 163, 74); } .nip05-identifier { /* Truncates long identifiers */ max-width: 200px; text-overflow: ellipsis; } ``` ## Service Layer The `Nip05VerificationService` can also be used independently: ```php use App\Service\Nip05VerificationService; class MyController { public function __construct( private Nip05VerificationService $nip05Service ) {} public function verifyIdentifier(string $nip05, string $pubkey): void { $result = $this->nip05Service->verify($nip05, $pubkey); if ($result['verified']) { // Identifier is verified! $relays = $result['relays']; // Available relay URLs } } } ``` ## Testing Comprehensive test scenarios are defined in `tests/NIPs/NIP-05.feature` covering: - Successful verification flows - User discovery - Validation rules - Security constraints - Edge cases and error handling ## Examples ### Valid Identifiers - `bob@example.com` - `alice_123@example.com` - `user-name@example.com` - `test.user@example.com` - `_@example.com` (root identifier) ### Invalid Identifiers - `bob+tag@example.com` (+ not allowed) - `bob space@example.com` (spaces not allowed) - `bob#hash@example.com` (# not allowed) - `npub1...` (not an identifier format) ## Troubleshooting ### Badge not showing - Check that both `nip05` and `pubkeyHex` props are provided - Verify the pubkey is in **hex format** (64 characters), not npub format - Check logs for verification failures - Ensure the domain serves `.well-known/nostr.json` with CORS headers ### CORS Issues The server must return: ``` Access-Control-Allow-Origin: * ``` ### Verification failures Check application logs for specific error messages: - Invalid identifier format - Missing names field - Pubkey mismatch - Invalid hex format - Network timeout ## Related Documentation - [NIP-05 Specification](https://github.com/nostr-protocol/nips/blob/master/05.md) - [Test Definitions](../../../tests/NIPs/NIP-05.feature)