NIP-42
Authentication of Clients to Relays - defines kind 22242 authentication events that prove a client controls a specific pubkey. The relay sends a challenge string, and the client signs an auth event containing that challenge and the relay URL.
Import
import { nip42 } from 'nostr-core'
// or import individual functions
import {
createAuthEventTemplate,
createAuthEvent,
verifyAuthEvent,
} from 'nostr-core'nip42.createAuthEventTemplate
function createAuthEventTemplate(opts: { relay: string; challenge: string }): EventTemplateCreates an unsigned kind 22242 client authentication event template. Use with finalizeEvent() or pass to a Signer.
| Parameter | Type | Description |
|---|---|---|
opts.relay | string | Relay URL that issued the challenge |
opts.challenge | string | Challenge string received from the relay |
Returns: EventTemplate - Unsigned kind 22242 event with relay and challenge tags.
const template = nip42.createAuthEventTemplate({
relay: 'wss://relay.example.com',
challenge: 'random-challenge-string',
})
const signed = await signer.signEvent(template)nip42.createAuthEvent
function createAuthEvent(opts: { relay: string; challenge: string }, secretKey: Uint8Array): NostrEventCreates and signs a kind 22242 client authentication event.
| Parameter | Type | Description |
|---|---|---|
opts.relay | string | Relay URL that issued the challenge |
opts.challenge | string | Challenge string from the relay |
secretKey | Uint8Array | Signer's secret key (32 bytes) |
Returns: NostrEvent - Signed kind 22242 event to send back to the relay.
const authEvent = nip42.createAuthEvent(
{ relay: 'wss://relay.example.com', challenge: 'random-challenge-string' },
secretKey,
)nip42.verifyAuthEvent
function verifyAuthEvent(event: NostrEvent, challenge: string, relayUrl: string): booleanVerifies a kind 22242 authentication event. Checks that the event is valid, has the correct kind, and that the relay and challenge tags match the expected values.
| Parameter | Type | Description |
|---|---|---|
event | NostrEvent | The authentication event to verify |
challenge | string | The challenge string that was issued |
relayUrl | string | The relay URL that issued the challenge |
Returns: boolean - true if the auth event is valid and matches the challenge/relay.
const isValid = nip42.verifyAuthEvent(authEvent, 'random-challenge-string', 'wss://relay.example.com')
if (isValid) {
console.log(`Authenticated as ${authEvent.pubkey}`)
}Full Example
import { generateSecretKey, getPublicKey, nip42, Relay } from 'nostr-core'
const sk = generateSecretKey()
const pk = getPublicKey(sk)
// Connect to a relay that requires authentication
const relay = new Relay('wss://relay.example.com')
// Handle the AUTH challenge from the relay
relay.onauth = async (challenge: string) => {
// Create and sign an auth event
const authEvent = nip42.createAuthEvent(
{ relay: 'wss://relay.example.com', challenge },
sk,
)
// Send the auth event back to the relay
await relay.auth(authEvent)
console.log('Authenticated successfully!')
}
await relay.connect()
// Or use the template approach with a Signer
relay.onauth = async (challenge: string) => {
const template = nip42.createAuthEventTemplate({
relay: 'wss://relay.example.com',
challenge,
})
const signed = await signer.signEvent(template)
await relay.auth(signed)
}
// Server-side: verify an auth event
function handleAuth(event: NostrEvent, expectedChallenge: string) {
const valid = nip42.verifyAuthEvent(event, expectedChallenge, 'wss://relay.example.com')
if (valid) {
console.log(`User ${event.pubkey} authenticated`)
// Grant access to restricted resources
} else {
console.log('Authentication failed')
}
}
relay.close()How It Works
- The relay sends an
AUTHmessage containing a challenge string to the client - The client creates a kind 22242 event with
relayandchallengetags - The signed event proves the client controls the private key for a specific pubkey
- The client sends the signed event back via the
AUTHcommand - Verification checks: valid signature, kind 22242, matching relay URL, matching challenge string
- Relays use authentication to restrict access (e.g., private relays, rate limiting)
- The
relay.onauthcallback is triggered when the relay issues an AUTH challenge - The
relay.auth()method sends the signed auth event back to the relay - Authentication is per-connection and must be repeated on reconnection