add forgetten lnurl-auth files
This commit is contained in:
		
							parent
							
								
									2e26e421e7
								
							
						
					
					
						commit
						9a15c228dc
					
				
							
								
								
									
										26
									
								
								api/resolvers/lnurl.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								api/resolvers/lnurl.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					import { randomBytes } from 'crypto'
 | 
				
			||||||
 | 
					import { bech32 } from 'bech32'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  Query: {
 | 
				
			||||||
 | 
					    lnAuth: async (parent, { k1 }, { models }) => {
 | 
				
			||||||
 | 
					      return await models.lnAuth.findUnique({ where: { k1 } })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  Mutation: {
 | 
				
			||||||
 | 
					    createAuth: async (parent, args, { models }) => {
 | 
				
			||||||
 | 
					      const k1 = randomBytes(32).toString('hex')
 | 
				
			||||||
 | 
					      return await models.lnAuth.create({ data: { k1 } })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  LnAuth: {
 | 
				
			||||||
 | 
					    encodedUrl: async (lnAuth, args, { models }) => {
 | 
				
			||||||
 | 
					      const url = new URL(process.env.LNAUTH_URL)
 | 
				
			||||||
 | 
					      url.searchParams.set('tag', 'login')
 | 
				
			||||||
 | 
					      url.searchParams.set('k1', lnAuth.k1)
 | 
				
			||||||
 | 
					      // bech32 encode url
 | 
				
			||||||
 | 
					      const words = bech32.toWords(Buffer.from(url.toString(), 'utf8'))
 | 
				
			||||||
 | 
					      return bech32.encode('lnurl', words, 1023)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								api/typeDefs/lnurl.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								api/typeDefs/lnurl.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					import { gql } from 'apollo-server-micro'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default gql`
 | 
				
			||||||
 | 
					  extend type Query {
 | 
				
			||||||
 | 
					    lnAuth(k1: String!): LnAuth!
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  extend type Mutation {
 | 
				
			||||||
 | 
					    createAuth: LnAuth!
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  type LnAuth {
 | 
				
			||||||
 | 
					    id: ID!
 | 
				
			||||||
 | 
					    createdAt: String!
 | 
				
			||||||
 | 
					    k1: String!
 | 
				
			||||||
 | 
					    pubkey: String
 | 
				
			||||||
 | 
					    encodedUrl: String!
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
							
								
								
									
										31
									
								
								components/lnqr.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								components/lnqr.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					import QRCode from 'qrcode.react'
 | 
				
			||||||
 | 
					import { CopyInput, InputSkeleton } from './form'
 | 
				
			||||||
 | 
					import InvoiceStatus from './invoice-status'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function LnQR ({ value, statusVariant, status }) {
 | 
				
			||||||
 | 
					  const qrValue = 'lightning:' + value.toUpperCase()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <>
 | 
				
			||||||
 | 
					      <div>
 | 
				
			||||||
 | 
					        <QRCode className='h-auto mw-100' value={qrValue} renderAs='svg' size={300} />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div className='mt-3 w-100'>
 | 
				
			||||||
 | 
					        <CopyInput type='text' placeholder={value} readOnly />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <InvoiceStatus variant={statusVariant} status={status} />
 | 
				
			||||||
 | 
					    </>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function LnQRSkeleton ({ status }) {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <>
 | 
				
			||||||
 | 
					      <div className='h-auto w-100 clouds' style={{ paddingTop: 'min(300px, 100%)', maxWidth: '300px' }} />
 | 
				
			||||||
 | 
					      <div className='mt-3 w-100'>
 | 
				
			||||||
 | 
					        <InputSkeleton />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <InvoiceStatus variant='default' status={status} />
 | 
				
			||||||
 | 
					    </>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								lib/lnurl.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								lib/lnurl.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					import { randomBytes } from 'crypto'
 | 
				
			||||||
 | 
					import { bech32 } from 'bech32'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function lnurlAuth (params) {
 | 
				
			||||||
 | 
					  // generate secret (32 random bytes)
 | 
				
			||||||
 | 
					  const secret = Buffer.from(randomBytes(32), 'hex')
 | 
				
			||||||
 | 
					  // create url
 | 
				
			||||||
 | 
					  const url = new URL(process.env.LNAUTH_URL)
 | 
				
			||||||
 | 
					  url.searchParams = new URLSearchParams({
 | 
				
			||||||
 | 
					    ...params,
 | 
				
			||||||
 | 
					    k1: secret
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  // bech32 encode url
 | 
				
			||||||
 | 
					  const words = bech32.toWords(Buffer.from(url.toString(), 'utf8'))
 | 
				
			||||||
 | 
					  const encodedUrl = bech32.encode('lnurl', words, 1023)
 | 
				
			||||||
 | 
					  return { secret, encodedUrl }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -94,7 +94,7 @@ const options = {
 | 
				
			|||||||
    })
 | 
					    })
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  adapter: Adapters.Prisma.Adapter({ prisma }),
 | 
					  adapter: Adapters.Prisma.Adapter({ prisma }),
 | 
				
			||||||
  secret: process.env.SECRET,
 | 
					  secret: process.env.NEXTAUTH_SECRET,
 | 
				
			||||||
  session: { jwt: true },
 | 
					  session: { jwt: true },
 | 
				
			||||||
  jwt: {
 | 
					  jwt: {
 | 
				
			||||||
    signingKey: process.env.JWT_SIGNING_PRIVATE_KEY
 | 
					    signingKey: process.env.JWT_SIGNING_PRIVATE_KEY
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										21
									
								
								pages/api/lnauth.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								pages/api/lnauth.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					// verify it's signed
 | 
				
			||||||
 | 
					// store pubkey in db
 | 
				
			||||||
 | 
					// create user with pubkey and name truncated pubkey
 | 
				
			||||||
 | 
					import secp256k1 from 'secp256k1'
 | 
				
			||||||
 | 
					import models from '../../api/models'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default async ({ query }, res) => {
 | 
				
			||||||
 | 
					  const sig = Buffer.from(query.sig, 'hex')
 | 
				
			||||||
 | 
					  const k1 = Buffer.from(query.k1, 'hex')
 | 
				
			||||||
 | 
					  const key = Buffer.from(query.key, 'hex')
 | 
				
			||||||
 | 
					  const signature = secp256k1.signatureImport(sig)
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    if (secp256k1.ecdsaVerify(signature, k1, key)) {
 | 
				
			||||||
 | 
					      await models.lnAuth.update({ where: { k1: query.k1 }, data: { pubkey: query.key } })
 | 
				
			||||||
 | 
					      return res.status(200).json({ status: 'OK' })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } catch (error) {
 | 
				
			||||||
 | 
					    console.log(error)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return res.status(400).json({ status: 'ERROR', reason: 'signature verification failed' })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								prisma/migrations/20210626191129_lnurl_auth/migration.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								prisma/migrations/20210626191129_lnurl_auth/migration.sql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					  Warnings:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - A unique constraint covering the columns `[pubkey]` on the table `users` will be added. If there are existing duplicate values, this will fail.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					-- AlterTable
 | 
				
			||||||
 | 
					ALTER TABLE "users" ADD COLUMN     "pubkey" TEXT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- CreateTable
 | 
				
			||||||
 | 
					CREATE TABLE "LnAuth" (
 | 
				
			||||||
 | 
					    "id" SERIAL NOT NULL,
 | 
				
			||||||
 | 
					    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
 | 
				
			||||||
 | 
					    "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
 | 
				
			||||||
 | 
					    "k1" TEXT NOT NULL,
 | 
				
			||||||
 | 
					    "pubkey" TEXT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PRIMARY KEY ("id")
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- CreateIndex
 | 
				
			||||||
 | 
					CREATE UNIQUE INDEX "LnAuth.k1_unique" ON "LnAuth"("k1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- CreateIndex
 | 
				
			||||||
 | 
					CREATE UNIQUE INDEX "users.pubkey_unique" ON "users"("pubkey");
 | 
				
			||||||
							
								
								
									
										3
									
								
								svgs/lightning.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								svgs/lightning.svg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
				
			||||||
 | 
					<path d="M19 10.1907L8.48754 21L12.6726 12.7423H5L14.6157 3L11.5267 10.2835L19 10.1907Z" fill="black"/>
 | 
				
			||||||
 | 
					</svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 207 B  | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user