@micro-cms/crypto-auth-node 1.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # @micro-cms/crypto-auth-node
2
+
3
+ A Micro-CMS backend module for verifying crypto signatures and managing nonces for wallet-based authentication.
4
+
5
+ ## Features
6
+ - **Capabilities**: Provides `authentication` and `route-provider` abilities.
7
+ - **Multichain**: Verifies Solana and EVM (Ethereum/Base) signatures.
8
+ - **Provisioning**: Supports `onVerified` hooks for user database provisioning.
9
+
10
+ ## Integration
11
+
12
+ ### Initialization
13
+ ```typescript
14
+ import { createApp } from '@micro-cms/core';
15
+ import CryptoAuthModule from '@micro-cms/crypto-auth-node';
16
+
17
+ const cms = createApp();
18
+
19
+ cms.use(CryptoAuthModule, {
20
+ jwtSecret: 'your-secret',
21
+ onVerified: async ({ address, network, req }) => {
22
+ // Look up or create user in DB
23
+ return { id: 1, email: `${address}@${network}.com` };
24
+ }
25
+ });
26
+
27
+ await cms.start();
28
+ ```
29
+
30
+ ### Endpoints (Automatic)
31
+ The module provides the following endpoints via the `route-provider` capability:
32
+ - `POST /api/auth/crypto/nonce`: Generates a unique nonce for signing.
33
+ - `POST /api/auth/crypto/verify`: Verifies the signature and returns a JWT.
@@ -0,0 +1,5 @@
1
+ import { CmsModule } from '@micro-cms/types';
2
+
3
+ declare const _default: CmsModule;
4
+
5
+ export { _default as default };
@@ -0,0 +1,5 @@
1
+ import { CmsModule } from '@micro-cms/types';
2
+
3
+ declare const _default: CmsModule;
4
+
5
+ export { _default as default };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var j=Object.create;var g=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,E=Object.prototype.hasOwnProperty;var k=(n,e)=>{for(var r in e)g(n,r,{get:e[r],enumerable:!0})},h=(n,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of M(e))!E.call(n,t)&&t!==r&&g(n,t,{get:()=>e[t],enumerable:!(o=C(e,t))||o.enumerable});return n};var p=(n,e,r)=>(r=n!=null?j(x(n)):{},h(e||!n||!n.__esModule?g(r,"default",{value:n,enumerable:!0}):r,n)),P=n=>h(g({},"__esModule",{value:!0}),n);var b={};k(b,{default:()=>V});module.exports=P(b);var d=p(require("bs58")),v=require("viem"),w=p(require("jsonwebtoken")),f=class{constructor(e){this.options=e;this.nonces=new Map}generateNonce(e){let r=Math.floor(Math.random()*1e6).toString();return this.nonces.set(e.toLowerCase(),r),r}async verifySolana(e,r){let o=this.nonces.get(e.toLowerCase());if(!o)return null;try{let t=new TextEncoder().encode(`Sign this message to authenticate: ${o}`),l=d.default.decode(r),i=d.default.decode(e);if(await this.verifySolanaSignature(t,l,i))return this.nonces.delete(e.toLowerCase()),this.issueToken(e,"solana")}catch(t){console.error("Solana verification error:",t)}return null}async verifySolanaSignature(e,r,o){let{sign:t}=await import("tweetnacl");return t.detached.verify(e,r,o)}async verifyEVM(e,r){let o=this.nonces.get(e.toLowerCase());if(!o)return null;try{let t=`Sign this message to authenticate: ${o}`;if(await(0,v.verifyMessage)({address:e,message:t,signature:r}))return this.nonces.delete(e.toLowerCase()),this.issueToken(e,"evm")}catch(t){console.error("EVM verification error:",t)}return null}issueToken(e,r){let o={expiresIn:this.options.jwtExpiresIn||"24h"};return w.default.sign({address:e,network:r},this.options.jwtSecret,o)}};var V={manifest:{name:"@micro-cms/crypto-auth-node",version:"1.0.0",provides:["authentication","route-provider"],requires:[]},async load(n){let{jwtSecret:e,jwtExpiresIn:r,onVerified:o}=n.config;e||console.warn("[@micro-cms/crypto-auth-node] jwtSecret not provided in config.");let t=new f({jwtSecret:e||"fallback-secret",jwtExpiresIn:r});n.runtime.register("authentication",{verifySolana:(i,s)=>t.verifySolana(i,s),verifyEVM:(i,s)=>t.verifyEVM(i,s),generateNonce:i=>t.generateNonce(i)});let l=[{method:"POST",path:"/api/auth/crypto/nonce",handler:async(i,s)=>{let{address:a}=i.body;if(!a)return s.status(400).json({error:"Address required"});let c=t.generateNonce(a);s.json({nonce:c})}},{method:"POST",path:"/api/auth/crypto/verify",handler:async(i,s)=>{let{address:a,signature:c,network:y}=i.body;if(!a||!c||!y)return s.status(400).json({error:"Address, signature and network required"});let u=null;if(y==="solana"?u=await t.verifySolana(a,c):u=await t.verifyEVM(a,c),u){let m=null;if(o)try{m=await o({address:a,network:y,token:u,req:i})}catch(S){console.error("[@micro-cms/crypto-auth-node] onVerified hook failed:",S.message)}s.json({token:u,user:m})}else s.status(401).json({error:"Verification failed"})}}];n.runtime.register("route-provider",{getRoutes:()=>l})}};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/auth.service.ts"],"sourcesContent":["import { CmsContext, CmsModule, RouteProvider, RouteDefinition } from '@micro-cms/types';\nimport { CryptoAuthService } from './auth.service';\n\nexport default {\n manifest: {\n name: '@micro-cms/crypto-auth-node',\n version: '1.0.0',\n provides: ['authentication', 'route-provider'],\n requires: []\n },\n\n async load(context: CmsContext) {\n const { jwtSecret, jwtExpiresIn, onVerified } = context.config;\n \n if (!jwtSecret) {\n console.warn('[@micro-cms/crypto-auth-node] jwtSecret not provided in config.');\n }\n\n const authService = new CryptoAuthService({ \n jwtSecret: jwtSecret || 'fallback-secret',\n jwtExpiresIn \n });\n\n context.runtime.register('authentication', {\n verifySolana: (address: string, signature: string) => authService.verifySolana(address, signature),\n verifyEVM: (address: string, signature: string) => authService.verifyEVM(address, signature),\n generateNonce: (address: string) => authService.generateNonce(address)\n });\n\n const routes: RouteDefinition[] = [\n {\n method: 'POST',\n path: '/api/auth/crypto/nonce',\n handler: async (req: any, res: any) => {\n const { address } = req.body;\n if (!address) return res.status(400).json({ error: 'Address required' });\n const nonce = authService.generateNonce(address);\n res.json({ nonce });\n }\n },\n {\n method: 'POST',\n path: '/api/auth/crypto/verify',\n handler: async (req: any, res: any) => {\n const { address, signature, network } = req.body;\n if (!address || !signature || !network) {\n return res.status(400).json({ error: 'Address, signature and network required' });\n }\n\n let token: string | null = null;\n if (network === 'solana') {\n token = await authService.verifySolana(address, signature);\n } else {\n token = await authService.verifyEVM(address, signature);\n }\n\n if (token) {\n // Optional hook to provision user in DB\n let user = null;\n if (onVerified) {\n try {\n user = await onVerified({ address, network, token, req });\n } catch (e: any) {\n console.error('[@micro-cms/crypto-auth-node] onVerified hook failed:', e.message);\n }\n }\n res.json({ token, user });\n } else {\n res.status(401).json({ error: 'Verification failed' });\n }\n }\n }\n ];\n\n context.runtime.register('route-provider', {\n getRoutes: () => routes\n } as RouteProvider);\n }\n} as CmsModule;\n","import { PublicKey } from '@solana/web3.js';\nimport bs58 from 'bs58';\nimport { verifyMessage } from 'viem';\nimport jwt from 'jsonwebtoken';\n\nexport interface CryptoAuthOptions {\n jwtSecret: string;\n jwtExpiresIn?: string;\n}\n\nexport class CryptoAuthService {\n private nonces = new Map<string, string>();\n\n constructor(private options: CryptoAuthOptions) {}\n\n generateNonce(address: string): string {\n const nonce = Math.floor(Math.random() * 1000000).toString();\n this.nonces.set(address.toLowerCase(), nonce);\n return nonce;\n }\n\n async verifySolana(address: string, signature: string): Promise<string | null> {\n const nonce = this.nonces.get(address.toLowerCase());\n if (!nonce) return null;\n\n try {\n const message = new TextEncoder().encode(`Sign this message to authenticate: ${nonce}`);\n const signatureUint8 = bs58.decode(signature);\n const publicKeyUint8 = bs58.decode(address);\n \n const verified = await this.verifySolanaSignature(message, signatureUint8, publicKeyUint8);\n \n if (verified) {\n this.nonces.delete(address.toLowerCase());\n return this.issueToken(address, 'solana');\n }\n } catch (e) {\n console.error('Solana verification error:', e);\n }\n return null;\n }\n\n private async verifySolanaSignature(message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): Promise<boolean> {\n // In a real implementation, use nacl or @solana/web3.js if it provides it directly\n // For now, let's assume we use tweetnacl via @solana/web3.js dependency or similar\n const { sign } = await import('tweetnacl');\n return sign.detached.verify(message, signature, publicKey);\n }\n\n async verifyEVM(address: string, signature: string): Promise<string | null> {\n const nonce = this.nonces.get(address.toLowerCase());\n if (!nonce) return null;\n\n try {\n const message = `Sign this message to authenticate: ${nonce}`;\n const verified = await verifyMessage({\n address: address as `0x${string}`,\n message,\n signature: signature as `0x${string}`,\n });\n\n if (verified) {\n this.nonces.delete(address.toLowerCase());\n return this.issueToken(address, 'evm');\n }\n } catch (e) {\n console.error('EVM verification error:', e);\n }\n return null;\n }\n\n private issueToken(address: string, network: string): string {\n const options: any = { \n expiresIn: this.options.jwtExpiresIn || '24h' \n };\n return jwt.sign(\n { address, network },\n this.options.jwtSecret,\n options\n );\n }\n}\n"],"mappings":"0jBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAAA,eAAAC,EAAAH,GCCA,IAAAI,EAAiB,mBACjBC,EAA8B,gBAC9BC,EAAgB,2BAOHC,EAAN,KAAwB,CAG7B,YAAoBC,EAA4B,CAA5B,aAAAA,EAFpB,KAAQ,OAAS,IAAI,GAE4B,CAEjD,cAAcC,EAAyB,CACrC,IAAMC,EAAQ,KAAK,MAAM,KAAK,OAAO,EAAI,GAAO,EAAE,SAAS,EAC3D,YAAK,OAAO,IAAID,EAAQ,YAAY,EAAGC,CAAK,EACrCA,CACT,CAEA,MAAM,aAAaD,EAAiBE,EAA2C,CAC7E,IAAMD,EAAQ,KAAK,OAAO,IAAID,EAAQ,YAAY,CAAC,EACnD,GAAI,CAACC,EAAO,OAAO,KAEnB,GAAI,CACF,IAAME,EAAU,IAAI,YAAY,EAAE,OAAO,sCAAsCF,CAAK,EAAE,EAChFG,EAAiB,EAAAC,QAAK,OAAOH,CAAS,EACtCI,EAAiB,EAAAD,QAAK,OAAOL,CAAO,EAI1C,GAFiB,MAAM,KAAK,sBAAsBG,EAASC,EAAgBE,CAAc,EAGvF,YAAK,OAAO,OAAON,EAAQ,YAAY,CAAC,EACjC,KAAK,WAAWA,EAAS,QAAQ,CAE5C,OAASO,EAAG,CACV,QAAQ,MAAM,6BAA8BA,CAAC,CAC/C,CACA,OAAO,IACT,CAEA,MAAc,sBAAsBJ,EAAqBD,EAAuBM,EAAyC,CAGvH,GAAM,CAAE,KAAAC,CAAK,EAAI,KAAM,QAAO,WAAW,EACzC,OAAOA,EAAK,SAAS,OAAON,EAASD,EAAWM,CAAS,CAC3D,CAEA,MAAM,UAAUR,EAAiBE,EAA2C,CAC1E,IAAMD,EAAQ,KAAK,OAAO,IAAID,EAAQ,YAAY,CAAC,EACnD,GAAI,CAACC,EAAO,OAAO,KAEnB,GAAI,CACF,IAAME,EAAU,sCAAsCF,CAAK,GAO3D,GANiB,QAAM,iBAAc,CACnC,QAASD,EACT,QAAAG,EACA,UAAWD,CACb,CAAC,EAGC,YAAK,OAAO,OAAOF,EAAQ,YAAY,CAAC,EACjC,KAAK,WAAWA,EAAS,KAAK,CAEzC,OAASO,EAAG,CACV,QAAQ,MAAM,0BAA2BA,CAAC,CAC5C,CACA,OAAO,IACT,CAEQ,WAAWP,EAAiBU,EAAyB,CAC3D,IAAMX,EAAe,CACnB,UAAW,KAAK,QAAQ,cAAgB,KAC1C,EACA,OAAO,EAAAY,QAAI,KACT,CAAE,QAAAX,EAAS,QAAAU,CAAQ,EACnB,KAAK,QAAQ,UACbX,CACF,CACF,CACF,ED9EA,IAAOa,EAAQ,CACb,SAAU,CACR,KAAM,8BACN,QAAS,QACT,SAAU,CAAC,iBAAkB,gBAAgB,EAC7C,SAAU,CAAC,CACb,EAEA,MAAM,KAAKC,EAAqB,CAC9B,GAAM,CAAE,UAAAC,EAAW,aAAAC,EAAc,WAAAC,CAAW,EAAIH,EAAQ,OAEnDC,GACH,QAAQ,KAAK,iEAAiE,EAGhF,IAAMG,EAAc,IAAIC,EAAkB,CACxC,UAAWJ,GAAa,kBACxB,aAAAC,CACF,CAAC,EAEDF,EAAQ,QAAQ,SAAS,iBAAkB,CACzC,aAAc,CAACM,EAAiBC,IAAsBH,EAAY,aAAaE,EAASC,CAAS,EACjG,UAAW,CAACD,EAAiBC,IAAsBH,EAAY,UAAUE,EAASC,CAAS,EAC3F,cAAgBD,GAAoBF,EAAY,cAAcE,CAAO,CACvE,CAAC,EAED,IAAME,EAA4B,CAChC,CACE,OAAQ,OACR,KAAM,yBACN,QAAS,MAAOC,EAAUC,IAAa,CACrC,GAAM,CAAE,QAAAJ,CAAQ,EAAIG,EAAI,KACxB,GAAI,CAACH,EAAS,OAAOI,EAAI,OAAO,GAAG,EAAE,KAAK,CAAE,MAAO,kBAAmB,CAAC,EACvE,IAAMC,EAAQP,EAAY,cAAcE,CAAO,EAC/CI,EAAI,KAAK,CAAE,MAAAC,CAAM,CAAC,CACpB,CACF,EACA,CACE,OAAQ,OACR,KAAM,0BACN,QAAS,MAAOF,EAAUC,IAAa,CACrC,GAAM,CAAE,QAAAJ,EAAS,UAAAC,EAAW,QAAAK,CAAQ,EAAIH,EAAI,KAC5C,GAAI,CAACH,GAAW,CAACC,GAAa,CAACK,EAC7B,OAAOF,EAAI,OAAO,GAAG,EAAE,KAAK,CAAE,MAAO,yCAA0C,CAAC,EAGlF,IAAIG,EAAuB,KAO3B,GANID,IAAY,SACdC,EAAQ,MAAMT,EAAY,aAAaE,EAASC,CAAS,EAEzDM,EAAQ,MAAMT,EAAY,UAAUE,EAASC,CAAS,EAGpDM,EAAO,CAET,IAAIC,EAAO,KACX,GAAIX,EACF,GAAI,CACFW,EAAO,MAAMX,EAAW,CAAE,QAAAG,EAAS,QAAAM,EAAS,MAAAC,EAAO,IAAAJ,CAAI,CAAC,CAC1D,OAASM,EAAQ,CACf,QAAQ,MAAM,wDAAyDA,EAAE,OAAO,CAClF,CAEFL,EAAI,KAAK,CAAE,MAAAG,EAAO,KAAAC,CAAK,CAAC,CAC1B,MACEJ,EAAI,OAAO,GAAG,EAAE,KAAK,CAAE,MAAO,qBAAsB,CAAC,CAEzD,CACF,CACF,EAEAV,EAAQ,QAAQ,SAAS,iBAAkB,CACzC,UAAW,IAAMQ,CACnB,CAAkB,CACpB,CACF","names":["index_exports","__export","index_default","__toCommonJS","import_bs58","import_viem","import_jsonwebtoken","CryptoAuthService","options","address","nonce","signature","message","signatureUint8","bs58","publicKeyUint8","e","publicKey","sign","network","jwt","index_default","context","jwtSecret","jwtExpiresIn","onVerified","authService","CryptoAuthService","address","signature","routes","req","res","nonce","network","token","user","e"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import p from"bs58";import{verifyMessage as m}from"viem";import h from"jsonwebtoken";var g=class{constructor(e){this.options=e;this.nonces=new Map}generateNonce(e){let r=Math.floor(Math.random()*1e6).toString();return this.nonces.set(e.toLowerCase(),r),r}async verifySolana(e,r){let n=this.nonces.get(e.toLowerCase());if(!n)return null;try{let t=new TextEncoder().encode(`Sign this message to authenticate: ${n}`),l=p.decode(r),o=p.decode(e);if(await this.verifySolanaSignature(t,l,o))return this.nonces.delete(e.toLowerCase()),this.issueToken(e,"solana")}catch(t){console.error("Solana verification error:",t)}return null}async verifySolanaSignature(e,r,n){let{sign:t}=await import("tweetnacl");return t.detached.verify(e,r,n)}async verifyEVM(e,r){let n=this.nonces.get(e.toLowerCase());if(!n)return null;try{let t=`Sign this message to authenticate: ${n}`;if(await m({address:e,message:t,signature:r}))return this.nonces.delete(e.toLowerCase()),this.issueToken(e,"evm")}catch(t){console.error("EVM verification error:",t)}return null}issueToken(e,r){let n={expiresIn:this.options.jwtExpiresIn||"24h"};return h.sign({address:e,network:r},this.options.jwtSecret,n)}};var M={manifest:{name:"@micro-cms/crypto-auth-node",version:"1.0.0",provides:["authentication","route-provider"],requires:[]},async load(u){let{jwtSecret:e,jwtExpiresIn:r,onVerified:n}=u.config;e||console.warn("[@micro-cms/crypto-auth-node] jwtSecret not provided in config.");let t=new g({jwtSecret:e||"fallback-secret",jwtExpiresIn:r});u.runtime.register("authentication",{verifySolana:(o,i)=>t.verifySolana(o,i),verifyEVM:(o,i)=>t.verifyEVM(o,i),generateNonce:o=>t.generateNonce(o)});let l=[{method:"POST",path:"/api/auth/crypto/nonce",handler:async(o,i)=>{let{address:s}=o.body;if(!s)return i.status(400).json({error:"Address required"});let a=t.generateNonce(s);i.json({nonce:a})}},{method:"POST",path:"/api/auth/crypto/verify",handler:async(o,i)=>{let{address:s,signature:a,network:f}=o.body;if(!s||!a||!f)return i.status(400).json({error:"Address, signature and network required"});let c=null;if(f==="solana"?c=await t.verifySolana(s,a):c=await t.verifyEVM(s,a),c){let y=null;if(n)try{y=await n({address:s,network:f,token:c,req:o})}catch(d){console.error("[@micro-cms/crypto-auth-node] onVerified hook failed:",d.message)}i.json({token:c,user:y})}else i.status(401).json({error:"Verification failed"})}}];u.runtime.register("route-provider",{getRoutes:()=>l})}};export{M as default};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/auth.service.ts","../src/index.ts"],"sourcesContent":["import { PublicKey } from '@solana/web3.js';\nimport bs58 from 'bs58';\nimport { verifyMessage } from 'viem';\nimport jwt from 'jsonwebtoken';\n\nexport interface CryptoAuthOptions {\n jwtSecret: string;\n jwtExpiresIn?: string;\n}\n\nexport class CryptoAuthService {\n private nonces = new Map<string, string>();\n\n constructor(private options: CryptoAuthOptions) {}\n\n generateNonce(address: string): string {\n const nonce = Math.floor(Math.random() * 1000000).toString();\n this.nonces.set(address.toLowerCase(), nonce);\n return nonce;\n }\n\n async verifySolana(address: string, signature: string): Promise<string | null> {\n const nonce = this.nonces.get(address.toLowerCase());\n if (!nonce) return null;\n\n try {\n const message = new TextEncoder().encode(`Sign this message to authenticate: ${nonce}`);\n const signatureUint8 = bs58.decode(signature);\n const publicKeyUint8 = bs58.decode(address);\n \n const verified = await this.verifySolanaSignature(message, signatureUint8, publicKeyUint8);\n \n if (verified) {\n this.nonces.delete(address.toLowerCase());\n return this.issueToken(address, 'solana');\n }\n } catch (e) {\n console.error('Solana verification error:', e);\n }\n return null;\n }\n\n private async verifySolanaSignature(message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): Promise<boolean> {\n // In a real implementation, use nacl or @solana/web3.js if it provides it directly\n // For now, let's assume we use tweetnacl via @solana/web3.js dependency or similar\n const { sign } = await import('tweetnacl');\n return sign.detached.verify(message, signature, publicKey);\n }\n\n async verifyEVM(address: string, signature: string): Promise<string | null> {\n const nonce = this.nonces.get(address.toLowerCase());\n if (!nonce) return null;\n\n try {\n const message = `Sign this message to authenticate: ${nonce}`;\n const verified = await verifyMessage({\n address: address as `0x${string}`,\n message,\n signature: signature as `0x${string}`,\n });\n\n if (verified) {\n this.nonces.delete(address.toLowerCase());\n return this.issueToken(address, 'evm');\n }\n } catch (e) {\n console.error('EVM verification error:', e);\n }\n return null;\n }\n\n private issueToken(address: string, network: string): string {\n const options: any = { \n expiresIn: this.options.jwtExpiresIn || '24h' \n };\n return jwt.sign(\n { address, network },\n this.options.jwtSecret,\n options\n );\n }\n}\n","import { CmsContext, CmsModule, RouteProvider, RouteDefinition } from '@micro-cms/types';\nimport { CryptoAuthService } from './auth.service';\n\nexport default {\n manifest: {\n name: '@micro-cms/crypto-auth-node',\n version: '1.0.0',\n provides: ['authentication', 'route-provider'],\n requires: []\n },\n\n async load(context: CmsContext) {\n const { jwtSecret, jwtExpiresIn, onVerified } = context.config;\n \n if (!jwtSecret) {\n console.warn('[@micro-cms/crypto-auth-node] jwtSecret not provided in config.');\n }\n\n const authService = new CryptoAuthService({ \n jwtSecret: jwtSecret || 'fallback-secret',\n jwtExpiresIn \n });\n\n context.runtime.register('authentication', {\n verifySolana: (address: string, signature: string) => authService.verifySolana(address, signature),\n verifyEVM: (address: string, signature: string) => authService.verifyEVM(address, signature),\n generateNonce: (address: string) => authService.generateNonce(address)\n });\n\n const routes: RouteDefinition[] = [\n {\n method: 'POST',\n path: '/api/auth/crypto/nonce',\n handler: async (req: any, res: any) => {\n const { address } = req.body;\n if (!address) return res.status(400).json({ error: 'Address required' });\n const nonce = authService.generateNonce(address);\n res.json({ nonce });\n }\n },\n {\n method: 'POST',\n path: '/api/auth/crypto/verify',\n handler: async (req: any, res: any) => {\n const { address, signature, network } = req.body;\n if (!address || !signature || !network) {\n return res.status(400).json({ error: 'Address, signature and network required' });\n }\n\n let token: string | null = null;\n if (network === 'solana') {\n token = await authService.verifySolana(address, signature);\n } else {\n token = await authService.verifyEVM(address, signature);\n }\n\n if (token) {\n // Optional hook to provision user in DB\n let user = null;\n if (onVerified) {\n try {\n user = await onVerified({ address, network, token, req });\n } catch (e: any) {\n console.error('[@micro-cms/crypto-auth-node] onVerified hook failed:', e.message);\n }\n }\n res.json({ token, user });\n } else {\n res.status(401).json({ error: 'Verification failed' });\n }\n }\n }\n ];\n\n context.runtime.register('route-provider', {\n getRoutes: () => routes\n } as RouteProvider);\n }\n} as CmsModule;\n"],"mappings":"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","names":["bs58","verifyMessage","jwt","CryptoAuthService","options","address","nonce","signature","message","signatureUint8","publicKeyUint8","e","publicKey","sign","network","index_default","context","jwtSecret","jwtExpiresIn","onVerified","authService","CryptoAuthService","address","signature","routes","req","res","nonce","network","token","user","e"]}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@micro-cms/crypto-auth-node",
3
+ "version": "1.0.32",
4
+ "description": "Node.js Crypto Authentication Module for Micro-CMS",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsup",
13
+ "dev": "tsup src/index.ts --format cjs,esm --watch --dts"
14
+ },
15
+ "dependencies": {
16
+ "@solana/web3.js": "^1.91.1",
17
+ "bs58": "^5.0.0",
18
+ "jsonwebtoken": "^9.0.2",
19
+ "tweetnacl": "^1.0.3",
20
+ "viem": "^2.7.0"
21
+ },
22
+ "peerDependencies": {
23
+ "@micro-cms/core": "workspace:*",
24
+ "@micro-cms/types": "workspace:*"
25
+ },
26
+ "devDependencies": {
27
+ "@types/jsonwebtoken": "^9.0.5",
28
+ "tsup": "^8.0.2",
29
+ "typescript": "^5.3.3"
30
+ }
31
+ }