A browser extension that enables zero-redirect authentication to Solid servers using Nostr cryptographic keys (NIP-98).
✨ Zero OAuth Redirects - Authenticate instantly without leaving the page 🔑 Uses Existing Nostr Keys - Works with nos2x, Alby, and other NIP-07 providers 🎯 did:nostr Identity - Proper 64-char hex format for DID resolution 🛡️ Secure by Design - Never touches your private keys, NIP-07 only 🌈 Beautiful UI - Soft gradients and light theme ⚡ Auto-Sign - Optional automatic signing for trusted sites
Request → 401 → IdP Redirect → Login → Auth Code → Token Exchange → Access
Request → 401 → Sign Event → Access ✨
You must have a NIP-07 Nostr provider installed:
git clone https://github.com/JavaScriptSolidServer/nostr-solid-auth.git
cd nostr-solid-auth
Open Chrome and navigate to chrome://extensions/
Enable Developer mode (toggle in top right)
Click Load unpacked
Select the nostr-solid-auth directory
Clone the repository (same as above)
Navigate to about:debugging#/runtime/this-firefox
Click Load Temporary Add-on
Select the manifest.json file
Click the extension icon to:
The extension implements NIP-98 HTTP Auth:
{
"kind": 27235, // HTTP Auth event
"created_at": 1704451200,
"tags": [
["u", "https://example.com/resource"], // Full URL
["method", "GET"] // HTTP method
],
"content": ""
}
Authorization header format:
Authorization: Nostr <base64-encoded-signed-event>
Public keys are validated as 64-character hexadecimal strings:
// Valid
const pubkey = "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d";
const did = `did:nostr:${pubkey}`;
// did:nostr:3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d
Your Solid server must support NIP-98 authentication. See the server implementation in JavaScriptSolidServer.
Example server-side validation:
// Extract and decode Authorization header
const authHeader = request.headers.authorization;
if (authHeader?.startsWith('Nostr ')) {
const eventBase64 = authHeader.substring(6);
const event = JSON.parse(atob(eventBase64));
// Validate event
// 1. Verify signature
// 2. Check kind === 27235
// 3. Match URL and method
// 4. Check timestamp (< 60 seconds old)
// 5. Verify pubkey is 64-char hex
// Resolve identity
const did = `did:nostr:${event.pubkey}`;
// Map to WebID via did:nostr resolver
}
┌─────────────────────────────────────────────────┐
│ Browser Tab │
│ ┌───────────────────────────────────────────┐ │
│ │ Content Script (content.js) │ │
│ │ - Detects 401 responses │ │
│ │ - Shows trust prompts │ │
│ │ - Calls window.nostr.signEvent() │ │
│ │ - Generates Authorization headers │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
↕
┌─────────────────────────────────────────────────┐
│ Background Service Worker (background.js) │
│ - Intercepts webRequest events │
│ - Manages trusted origins storage │
│ - Validates 64-char hex pubkeys │
│ - Coordinates auth flow │
└─────────────────────────────────────────────────┘
↕
┌─────────────────────────────────────────────────┐
│ NIP-07 Provider (nos2x, Alby, etc.) │
│ - Stores private keys securely │
│ - Signs events via window.nostr.signEvent() │
│ - Returns 64-char hex pubkey │
└─────────────────────────────────────────────────┘
nostr-solid-auth/
├── manifest.json # Extension manifest (MV3)
├── background.js # Service worker (401 detection)
├── content.js # Content script (NIP-07 bridge)
├── popup.html # Popup UI
├── popup.js # Popup logic
├── icons/ # Extension icons
│ ├── icon16.png
│ ├── icon48.png
│ └── icon128.png
└── README.md
[Nostr-Solid Auth] Extension installed
[Nostr-Solid Auth] Detected 401 response: https://...
[Nostr-Solid Auth] Auth required for: https://...
The extension validates all public keys to ensure proper did:nostr format:
function isValidNostrPubkey(pubkey) {
if (typeof pubkey !== 'string') return false;
if (pubkey.length !== 64) return false;
return /^[0-9a-fA-F]{64}$/.test(pubkey);
}
Contributions welcome! Please:
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)MIT
Built with 💜 for the Solid and Nostr ecosystems.
Part of the JavaScriptSolidServer project.