Skip to content

vanruch/fastify-siwe

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

fastify-siwe

Sign In with Ethereum middleware for Fastify.

Example

See packages/example to see an example of the usage.

How it works

diagram

  1. The frontend requests a nonce from the backend server. The nonce must be generated and verified on the backend to protect against replay attacks.
  2. The dapp signs the message with user's wallet and saves the signed message locally.
  3. An Authentication header is included in every request with the signed message.

Header format

Authorization: Bearer <json encoded message>

Example of the signed message:

{
  "signature":"0xafa5d63362c63b0da57f152afb0fbd296abd1aec046355927f2c34e26ab67b1a58ce34bcd609d312293391005c25780a87c110cfb6374a747184a35b047b08d91c",
  "message":{
    "domain":"localhost:3002",
    "address":"0x2C6e1d8a2E457c5D79fAD2c9F2f0f463e0Df5376",
    "statement":"Sign in with Ethereum to the app.",
    "uri":"http://localhost:3002",
    "version":"1",
    "chainId":1,
    "nonce":"JGiZrkbZ2uwUXl5yl",
    "issuedAt":"2022-04-23T17:25:20.427Z"
  }
}

Installation

npm add fastify-siwe

yarn add fastify-siwe

pnpm add fastify-siwe

Usage

Register the middleware:

import { signInWithEthereum } from 'fastify-siwe'

fastify.register(signInWithEthereum())

All requests come decorated with req.siwe object. req.siwe.session will contain be present if the request is authenticated.

fastify.get(
  '/siwe/me',
  {},
  async function handler(
    this: FastifyInstance,
    req: FastifyRequest,
    reply,
  ) {
    if (!req.siwe.session) {
      reply.status(401).send()
      return
    }

    console.log('address =', req.siwe.session.address)
  },
)

Generating a new nonce:

const nonce = await req.siwe.generateNonce()

Checkout the full example at packages/example

Implementing a custom store

By default, sessions are stored in memory. Session data will be lost on server restart.

To preserve sessions you can implement a custom store backed by a database.

import { SessionStore, signInWithEthereum } from 'fastify-siwe'

class MyStore implements SessionStore {
  async get(nonce: string): Promise<StoredSession | undefined> {
    // Fetch from database
  }

  public async save(session: StoredSession){
    // Save to database
  }


  async remove(nonce: string): Promise<void> {
    // Delete from database
  }
}

fastify.register(signInWithEthereum({ store: new MyStore() }))

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published