JavaScript Integration
Add DID-based authentication to any website. Choose your approach based on your stack.
Backend verification is required. Client-side wallet discovery and presentation requests are convenient for UX, but the Verifiable Presentation must be verified on the server where trusted issuer lists and resolver endpoints cannot be tampered with.
Vanilla JavaScript
HTML
<script type="module"> import { pickWallet, verifyPresentation } from 'https://cdn.attestto.com/id-wallet-adapter/0.4.1/index.mjs' document.getElementById('did-login').addEventListener('click', async () => { const wallet = await pickWallet({ render: 'modal' }) const vp = await wallet.requestPresentation({ challenge: crypto.randomUUID(), }) // Send VP to backend for verification const res = await fetch('/api/auth/did-login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ vp }), }) const session = await res.json() if (session.authenticated) { window.location.href = '/dashboard' } }) </script> <button id="did-login">Sign in with DID</button>
React
DIDLogin.tsx
import { pickWallet } from '@attestto/id-wallet-adapter' export function DIDLogin() { const handleLogin = async () => { const wallet = await pickWallet({ render: 'modal' }) const vp = await wallet.requestPresentation({ challenge: crypto.randomUUID(), }) const res = await fetch('/api/auth/did-login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ vp }), }) const session = await res.json() if (session.authenticated) window.location.href = '/dashboard' } return ( <button onClick={handleLogin}>Sign in with DID</button> ) }
Vue
DIDLogin.vue
<script setup lang="ts"> import { pickWallet } from '@attestto/id-wallet-adapter' async function handleLogin() { const wallet = await pickWallet({ render: 'modal' }) const vp = await wallet.requestPresentation({ challenge: crypto.randomUUID(), }) const res = await fetch('/api/auth/did-login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ vp }), }) const session = await res.json() if (session.authenticated) window.location.href = '/dashboard' } </script> <template> <button @click="handleLogin">Sign in with DID</button> </template>
Web Component
HTML
<!-- Drop-in: no framework needed --> <script type="module" src="https://cdn.attestto.com/id-wallet-adapter/0.4.1/did-login.mjs" ></script> <attestto-did-login verify-endpoint="/api/auth/did-login" redirect="/dashboard" ></attestto-did-login>
Backend: Express.js Middleware
middleware/did-auth.ts
import { verifyPresentation } from '@attestto/id-wallet-adapter' const TRUSTED_ISSUERS = [ 'did:web:gov.example.com', 'did:sns:attestto.sol', ] export async function didAuth(req, res) { const { vp } = req.body if (!vp) return res.status(400).json({ error: 'Missing VP' }) const result = await verifyPresentation(vp, { trustedIssuers: TRUSTED_ISSUERS, checkRevocation: true, }) if (!result.valid) { return res.status(401).json({ errors: result.errors }) } // Create session with the verified holder DID req.session.did = result.holderDid res.json({ authenticated: true, did: result.holderDid }) }
CDN Approach
For sites that cannot use npm, the adapter is available via CDN as a single
ESM module. Add a <script type="module"> tag pointing to
the CDN URL. No build step required.
HTML
<script type="module" src="https://cdn.attestto.com/id-wallet-adapter/0.4.1/index.mjs"></script>