Skip to content

Commit

Permalink
refactor(unlock-app): dry-ing up SIWE messages (#11916)
Browse files Browse the repository at this point in the history
* dry-ing up SIWE messages

* cleanup

* adding siweSign
  • Loading branch information
julien51 committed May 17, 2023
1 parent cadd8d2 commit baf63aa
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 75 deletions.
57 changes: 29 additions & 28 deletions unlock-app/src/components/interface/checkout/Connect/Confirm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { FaEthereum as EthereumIcon } from 'react-icons/fa'
import { OAuthConfig } from '~/unlockTypes'
import { PaywallConfigType as PaywallConfig } from '@unlock-protocol/core'
import { useAuth } from '~/contexts/AuthenticationContext'
import { createMessageToSignIn } from '~/utils/oauth'
import { Connected } from '../Connected'
import { ConnectService } from './connectMachine'
import { PoweredByUnlock } from '../PoweredByUnlock'
import { useCheckoutCommunication } from '~/hooks/useCheckoutCommunication'
import { useSIWE } from '~/hooks/useSIWE'
import { generateNonce } from 'siwe'

interface Props {
paywallConfig?: PaywallConfig
Expand All @@ -29,39 +30,39 @@ export function ConfirmConnect({
communication,
}: Props) {
const [loading, setLoading] = useState(false)
const { account, network, getWalletService, isUnlockAccount } = useAuth()
const { siweSign } = useSIWE()
const { account, isUnlockAccount } = useAuth()

const onSignIn = async () => {
try {
setLoading(true)
const walletService = await getWalletService()

const message = createMessageToSignIn({
clientId: oauthConfig.clientId,
statement: paywallConfig?.messageToSign || '',
address: account!,
chainId: network,
})

const signature = await walletService.signMessage(
message,
'personal_sign'
const result = await siweSign(
generateNonce(),
paywallConfig?.messageToSign || ''
)
const code = Buffer.from(
JSON.stringify({
d: message,
s: signature,

if (result) {
const { message, signature } = result
const code = Buffer.from(
JSON.stringify({
d: message,
s: signature,
})
).toString('base64')
communication?.emitUserInfo({
address: account,
message: message,
signedMessage: signature,
})
).toString('base64')
setLoading(false)
communication?.emitUserInfo({
address: account,
message: message,
signedMessage: signature,
})
onClose({
code,
state: oauthConfig.state,
})
onClose({
code,
state: oauthConfig.state,
})
setLoading(false)
} else {
setLoading(false)
}
} catch (error: any) {
setLoading(false)
console.error(error)
Expand Down
64 changes: 49 additions & 15 deletions unlock-app/src/hooks/useSIWE.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ type Status = 'loading' | 'error' | 'success' | 'rejected' | 'idle'
export interface SIWEContextType {
session?: string | null
signIn: () => Promise<unknown> | unknown
siweSign: (
nonce: string,
statement: string
) => Promise<{ message: string; signature: string } | null> | null
signOut: () => Promise<unknown> | unknown
status?: Status
isSignedIn: boolean
}

const SIWEContext = createContext<SIWEContextType>({
siweSign: (_nonce: string, _statement: string) => {
throw new Error('No SIWE provider found')
},
signIn: () => {
throw new Error('No SIWE provider found')
},
Expand Down Expand Up @@ -69,7 +76,10 @@ export const SIWEProvider = ({ children }: Props) => {
}
}

const signIn = async () => {
const siweSign = async (
nonce: string,
statement: string
): Promise<{ message: string; signature: string } | null> => {
try {
setStatus('loading')
if (!connected) {
Expand All @@ -78,7 +88,7 @@ export const SIWEProvider = ({ children }: Props) => {
const walletService = await getWalletService()

const address = await walletService.signer.getAddress()
const { data: nonce } = await storage.nonce()

const parent = new URL(
window.location != window.parent.location
? document.referrer
Expand All @@ -88,13 +98,14 @@ export const SIWEProvider = ({ children }: Props) => {
if (parent.host !== window.location.host) {
resources = [window.location.origin]
}

const siwe = new SiweMessage({
domain: parent.host,
uri: parent.origin,
address,
chainId: network,
version: '1',
statement: '',
statement,
nonce,
resources,
})
Expand All @@ -104,28 +115,51 @@ export const SIWEProvider = ({ children }: Props) => {
message,
'personal_sign'
)
const response = await storage.login({
message,
signature,
})
const { accessToken, walletAddress } = response.data
if (accessToken && walletAddress) {
saveAccessToken({
accessToken,
walletAddress,

return { message, signature }
} catch (error) {
onError(error)
return null
}
}

const signIn = async () => {
try {
setStatus('loading')
if (!connected) {
throw new Error('No wallet connected.')
}

const { data: nonce } = await storage.nonce()
const siweResult = await siweSign(nonce, '')
if (siweResult) {
const { message, signature } = siweResult

const response = await storage.login({
message,
signature,
})
const { accessToken, walletAddress } = response.data
if (accessToken && walletAddress) {
saveAccessToken({
accessToken,
walletAddress,
})
}
await queryClient.refetchQueries()
await refetchSession()
}
await queryClient.refetchQueries()
await refetchSession()
setStatus('idle')
} catch (error) {
onError(error)
return null
}
}

const isSignedIn = !!session
return (
<SIWEContext.Provider
value={{ session, signIn, status, signOut, isSignedIn }}
value={{ session, signIn, siweSign, status, signOut, isSignedIn }}
>
{children}
</SIWEContext.Provider>
Expand Down
32 changes: 0 additions & 32 deletions unlock-app/src/utils/oauth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { generateNonce, SiweMessage } from 'siwe'
import { OAuthConfig } from '../unlockTypes'

export default function getConfigFromSearch(
Expand All @@ -25,34 +24,3 @@ export default function getConfigFromSearch(
state,
}
}

export function createMessageToSignIn({
clientId,
statement,
address,
chainId,
}: {
clientId: string
statement: string
address: string
chainId?: number
}) {
const nonce = generateNonce()
const expirationDate = new Date()
// Add 7 day expiration from today. This will account for months.
expirationDate.setDate(expirationDate.getDate() + 7)

const message = new SiweMessage({
nonce,
domain: window.location.hostname,
statement: statement.trim(),
uri: window.location.origin,
version: '1',
address,
chainId,
resources: [new URL('https://' + clientId).toString()],
expirationTime: expirationDate.toISOString(),
})

return message.prepareMessage()
}

0 comments on commit baf63aa

Please sign in to comment.