import { EventTemplate } from 'nostr-tools' import { MetadataController, NostrController } from '.' import { setAuthState, setMetadataEvent } from '../store/actions' import store from '../store/store' import { base64DecodeAuthToken, base64EncodeSignedEvent, getAuthToken, getVisitedLink, saveAuthToken } from '../utils' import { appPrivateRoutes } from '../routes' import { SignedEvent } from '../types' export class AuthController { private nostrController: NostrController private metadataController: MetadataController constructor() { this.nostrController = NostrController.getInstance() this.metadataController = new MetadataController() } /** * Function will authenticate user by signing an auth event * which is done by calling the sign() function, where appropriate * method will be chosen (extension, nsecbunker or keys) * * @param pubkey of the user trying to login * @returns url to redirect if authentication successfull * or error if otherwise */ async authenticateAndFindMetadata(pubkey: string) { this.metadataController .findMetadata(pubkey) .then((event) => { store.dispatch(setMetadataEvent(event)) }) .catch((err) => { console.error('Error occurred while finding metadata', err) }) // Nostr uses unix timestamps const timestamp = Math.floor(Date.now() / 1000) const { hostname } = window.location const authEvent: EventTemplate = { kind: 1, tags: [], content: `${hostname}-${timestamp}`, created_at: timestamp } const signedAuthEvent = await this.nostrController.signEvent(authEvent) this.createAndSaveAuthToken(signedAuthEvent) store.dispatch( setAuthState({ loggedIn: true, usersPubkey: pubkey }) ) const visitedLink = getVisitedLink() if (visitedLink) { const { pathname, search } = visitedLink return Promise.resolve(`${pathname}${search}`) } else { // Navigate user in return Promise.resolve(appPrivateRoutes.homePage) } } checkSession() { const savedAuthToken = getAuthToken() if (savedAuthToken) { const signedEvent = base64DecodeAuthToken(savedAuthToken) store.dispatch( setAuthState({ loggedIn: true, usersPubkey: signedEvent.pubkey }) ) return } store.dispatch( setAuthState({ loggedIn: false, usersPubkey: undefined }) ) } private createAndSaveAuthToken(signedAuthEvent: SignedEvent) { const base64Encoded = base64EncodeSignedEvent(signedAuthEvent) // save newly created auth token (base64 nostr singed event) in local storage along with expiry time saveAuthToken(base64Encoded) return base64Encoded } }