fluidtrends/carmel

View on GitHub
web/sdk/hooks/auth.tsx

Summary

Maintainability
A
2 hrs
Test Coverage
import { useState } from 'react';
import * as cr from '~/utils/crypto'

export const useCarmelAuth = (carmelNet: any) => {
  const [isLoading, setIsLoading] = useState(false);

  const status = () => {
    return {
      loggedIn: cr.isLoggedIn(),
      registered: cr.isRegistered(),
      session: cr.loadSession(),
      account: cr.loadAccount()
    }
  }

  const login = async (props: any) => {
    const account = localStorage.getItem('carmel.account')

    if (!account) {
      console.log("not logged in.")
      return;
    }

    const { username, id, jwk } = JSON.parse(atob(account))

    const action = "did:carmel:0123456789:0123456789x"
    const challenge = cr.utf8StringToBuffer(`${username}:${action}`)  
    const publicKey: any = cr.loginOptions({ username, id, challenge })  
    const assertion: any = await navigator.credentials.get({ publicKey });
    
    const sig = await cr.getSig(assertion)
    const digest = await cr.getDigest(assertion)

    const token = cr.stringToBase64(JSON.stringify({
      account,
      action,
      sig: cr.bufferToBase64URLString(sig),
      digest,
    }))
    
    localStorage.setItem('carmel.token', token)
  }

  const register = async ({ username, code }: any) => {
    const publicKey: any = cr.registerOptions({ username })
    const attestation: any = await navigator.credentials.create({ publicKey })
    const jwk = await cr.getJWK(attestation)

    const account = {
      username, 
      id: attestation.id, 
      jwk: JSON.stringify(jwk)
    }

    localStorage.setItem('carmel.account', cr.stringToBase64(JSON.stringify(account)))

    try {
      const channel = carmelNet.session.station.channel("system")
      const result = await channel.sendEvent("register", {
        data: { username, code, publicKey }
      })

    } catch (e) {
      console.log(e)
    }
  }

  return {
    register,
    login,
    isLoading,
    ...status
  }
}