Refactor Nostr auth service
This commit is contained in:
@@ -15,7 +15,7 @@ export default class NostrConnectComponent extends Component {
|
|||||||
@action
|
@action
|
||||||
async connectExtension() {
|
async connectExtension() {
|
||||||
try {
|
try {
|
||||||
await this.nostrAuth.login('extension');
|
await this.nostrAuth.connectWithExtension();
|
||||||
if (this.args.onConnect) {
|
if (this.args.onConnect) {
|
||||||
this.args.onConnect();
|
this.args.onConnect();
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ export default class NostrConnectComponent extends Component {
|
|||||||
@action
|
@action
|
||||||
async connectApp() {
|
async connectApp() {
|
||||||
try {
|
try {
|
||||||
await this.nostrAuth.login('connect');
|
await this.nostrAuth.connectWithApp();
|
||||||
if (this.args.onConnect) {
|
if (this.args.onConnect) {
|
||||||
this.args.onConnect();
|
this.args.onConnect();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export default class UserMenuComponent extends Component {
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
disconnectNostr() {
|
disconnectNostr() {
|
||||||
this.nostrAuth.logout();
|
this.nostrAuth.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ const STORAGE_KEY_CONNECT_LOCAL_KEY = 'marco:nostr_connect_local_key';
|
|||||||
const STORAGE_KEY_CONNECT_REMOTE_PUBKEY = 'marco:nostr_connect_remote_pubkey';
|
const STORAGE_KEY_CONNECT_REMOTE_PUBKEY = 'marco:nostr_connect_remote_pubkey';
|
||||||
const STORAGE_KEY_CONNECT_RELAY = 'marco:nostr_connect_relay';
|
const STORAGE_KEY_CONNECT_RELAY = 'marco:nostr_connect_relay';
|
||||||
|
|
||||||
|
const DEFAULT_CONNECT_RELAY = 'wss://relay.nsec.app';
|
||||||
|
|
||||||
export default class NostrAuthService extends Service {
|
export default class NostrAuthService extends Service {
|
||||||
@service nostrRelay;
|
@service nostrRelay;
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ export default class NostrAuthService extends Service {
|
|||||||
async _verifyPubkey() {
|
async _verifyPubkey() {
|
||||||
if (this.signerType === 'extension') {
|
if (this.signerType === 'extension') {
|
||||||
if (typeof window.nostr === 'undefined') {
|
if (typeof window.nostr === 'undefined') {
|
||||||
this.logout();
|
this.disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -56,14 +58,14 @@ export default class NostrAuthService extends Service {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('Failed to verify extension nostr pubkey, logging out', e);
|
console.warn('Failed to verify extension nostr pubkey, logging out', e);
|
||||||
this.logout();
|
this.disconnect();
|
||||||
}
|
}
|
||||||
} else if (this.signerType === 'connect') {
|
} else if (this.signerType === 'connect') {
|
||||||
try {
|
try {
|
||||||
await this._initConnectSigner();
|
await this._initConnectSigner();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('Failed to verify connect nostr pubkey, logging out', e);
|
console.warn('Failed to verify connect nostr pubkey, logging out', e);
|
||||||
this.logout();
|
this.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,8 +101,7 @@ export default class NostrAuthService extends Service {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async login(type = 'extension') {
|
async connectWithExtension() {
|
||||||
if (type === 'extension') {
|
|
||||||
if (typeof window.nostr === 'undefined') {
|
if (typeof window.nostr === 'undefined') {
|
||||||
throw new Error('No NIP-07 Nostr extension found (e.g., Alby, nos2x).');
|
throw new Error('No NIP-07 Nostr extension found (e.g., Alby, nos2x).');
|
||||||
}
|
}
|
||||||
@@ -116,11 +117,9 @@ export default class NostrAuthService extends Service {
|
|||||||
console.error('Failed to get public key from extension:', error);
|
console.error('Failed to get public key from extension:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
} else if (type === 'connect') {
|
}
|
||||||
this.connectStatus = 'waiting';
|
|
||||||
|
|
||||||
try {
|
_getLocalSigner() {
|
||||||
// Generate or retrieve a local ephemeral keypair
|
|
||||||
let localKeyHex = localStorage.getItem(STORAGE_KEY_CONNECT_LOCAL_KEY);
|
let localKeyHex = localStorage.getItem(STORAGE_KEY_CONNECT_LOCAL_KEY);
|
||||||
let localSigner;
|
let localSigner;
|
||||||
if (localKeyHex) {
|
if (localKeyHex) {
|
||||||
@@ -133,9 +132,17 @@ export default class NostrAuthService extends Service {
|
|||||||
.join('');
|
.join('');
|
||||||
localStorage.setItem(STORAGE_KEY_CONNECT_LOCAL_KEY, localKeyHex);
|
localStorage.setItem(STORAGE_KEY_CONNECT_LOCAL_KEY, localKeyHex);
|
||||||
}
|
}
|
||||||
|
return localSigner;
|
||||||
|
}
|
||||||
|
|
||||||
|
async connectWithApp() {
|
||||||
|
this.connectStatus = 'waiting';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const localSigner = this._getLocalSigner();
|
||||||
|
|
||||||
// We use a specific relay for the connection handshake.
|
// We use a specific relay for the connection handshake.
|
||||||
const relay = 'wss://relay.nsec.app';
|
const relay = DEFAULT_CONNECT_RELAY;
|
||||||
localStorage.setItem(STORAGE_KEY_CONNECT_RELAY, relay);
|
localStorage.setItem(STORAGE_KEY_CONNECT_RELAY, relay);
|
||||||
|
|
||||||
// Override aggressive 10s EOSE timeout to allow time for QR scanning
|
// Override aggressive 10s EOSE timeout to allow time for QR scanning
|
||||||
@@ -207,21 +214,19 @@ export default class NostrAuthService extends Service {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async _initConnectSigner() {
|
async _initConnectSigner() {
|
||||||
const localKeyHex = localStorage.getItem(STORAGE_KEY_CONNECT_LOCAL_KEY);
|
|
||||||
const remotePubkey = localStorage.getItem(
|
const remotePubkey = localStorage.getItem(
|
||||||
STORAGE_KEY_CONNECT_REMOTE_PUBKEY
|
STORAGE_KEY_CONNECT_REMOTE_PUBKEY
|
||||||
);
|
);
|
||||||
const relay =
|
const relay =
|
||||||
localStorage.getItem(STORAGE_KEY_CONNECT_RELAY) || 'wss://relay.nsec.app';
|
localStorage.getItem(STORAGE_KEY_CONNECT_RELAY) || DEFAULT_CONNECT_RELAY;
|
||||||
|
|
||||||
if (!localKeyHex || !remotePubkey) {
|
if (!remotePubkey) {
|
||||||
throw new Error('Missing Nostr Connect local state.');
|
throw new Error('Missing Nostr Connect remote pubkey.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const localSigner = PrivateKeySigner.fromKey(localKeyHex);
|
const localSigner = this._getLocalSigner();
|
||||||
|
|
||||||
// Override aggressive 10s EOSE timeout to allow time for QR scanning
|
// Override aggressive 10s EOSE timeout to allow time for QR scanning
|
||||||
this.nostrRelay.pool.relay(relay).eoseTimeout = 180000; // 3 minutes
|
this.nostrRelay.pool.relay(relay).eoseTimeout = 180000; // 3 minutes
|
||||||
@@ -259,7 +264,7 @@ export default class NostrAuthService extends Service {
|
|||||||
return await this.signer.signEvent(event);
|
return await this.signer.signEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
async logout() {
|
async disconnect() {
|
||||||
this.pubkey = null;
|
this.pubkey = null;
|
||||||
this.signerType = null;
|
this.signerType = null;
|
||||||
this.connectStatus = null;
|
this.connectStatus = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user