Skip to content

Commit 02fc3fa

Browse files
authored
Merge pull request #33 from GeneralMagicio/auth-module
added generate nonce and verify payload
2 parents 5a69072 + fe70873 commit 02fc3fa

File tree

7 files changed

+522
-9
lines changed

7 files changed

+522
-9
lines changed

package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,16 @@
2828
"@nestjs/mapped-types": "*",
2929
"@nestjs/platform-express": "^11.0.1",
3030
"@prisma/client": "^6.5.0",
31+
"@worldcoin/minikit-js": "^1.8.0",
3132
"class-validator": "^0.14.1",
33+
"cookie-parser": "^1.4.7",
34+
"crypto": "^1.0.1",
35+
"react": "^19.1.0",
3236
"reflect-metadata": "^0.2.2",
33-
"rxjs": "^7.8.1"
37+
"rxjs": "^7.8.1",
38+
"viem": "^2.24.2",
39+
"view": "^1.1.1",
40+
"zustand": "^5.0.3"
3441
},
3542
"devDependencies": {
3643
"@eslint/eslintrc": "^3.2.0",

src/app.module.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import { AppService } from './app.service';
44
import { DatabaseService } from './database/database.service';
55
import { DatabaseModule } from './database/database.module';
66
import { PollModule } from './poll/poll.module';
7+
import { AuthModule } from './auth/auth.module';
8+
import { AuthService } from './auth/auth.service';
79

810
@Module({
9-
imports: [DatabaseModule, PollModule],
11+
imports: [DatabaseModule, PollModule, AuthModule],
1012
controllers: [AppController],
11-
providers: [AppService, DatabaseService],
13+
providers: [AppService, DatabaseService, AuthService],
1214
})
1315
export class AppModule {}

src/auth/auth.controller.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Body, Controller, Get, Post, Req, Res } from '@nestjs/common';
2+
import { Response, Request } from 'express';
3+
import { AuthService } from './auth.service';
4+
import { MiniAppWalletAuthSuccessPayload } from '@worldcoin/minikit-js';
5+
6+
interface IRequestPayload {
7+
payload: MiniAppWalletAuthSuccessPayload;
8+
}
9+
@Controller('auth')
10+
export class AuthController {
11+
constructor(private readonly authService: AuthService) {}
12+
13+
@Get('nonce')
14+
async generateNonce(@Res() res: Response): Promise<any> {
15+
const nonce = this.authService.generateNonce();
16+
res.cookie('siwe', nonce, {
17+
httpOnly: true,
18+
secure: process.env.NODE_ENV === 'production',
19+
sameSite: 'strict',
20+
maxAge: 2 * 60 * 1000, //2 minutes
21+
});
22+
23+
return res.json({ nonce });
24+
}
25+
26+
@Post('verifyPayload')
27+
async verifyPayload(
28+
@Req() req: Request,
29+
@Body() body: IRequestPayload,
30+
@Res() res: Response,
31+
) {
32+
const { payload } = body;
33+
const storedNonce = req.cookies?.siwe;
34+
if (!storedNonce) {
35+
return res.status(400).json({
36+
status: 'error',
37+
isValid: false,
38+
message: 'No nonce found in cookies',
39+
});
40+
}
41+
try {
42+
const validMessage = await this.authService.verifyPayload(
43+
payload,
44+
storedNonce,
45+
);
46+
return res.status(200).json({ isValid: validMessage });
47+
} catch (error: any) {
48+
return res
49+
.status(400)
50+
.json({ status: 'error', isValid: false, message: error.message });
51+
}
52+
}
53+
}

src/auth/auth.module.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Module } from '@nestjs/common';
2+
import { AuthController } from './auth.controller';
3+
import { AuthService } from './auth.service';
4+
5+
@Module({
6+
controllers: [AuthController],
7+
providers: [AuthService],
8+
})
9+
export class AuthModule {}

src/auth/auth.service.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Injectable } from '@nestjs/common';
2+
import * as crypto from 'crypto';
3+
import {
4+
MiniAppWalletAuthSuccessPayload,
5+
verifySiweMessage,
6+
} from '@worldcoin/minikit-js';
7+
import { DatabaseService } from 'src/database/database.service';
8+
9+
@Injectable()
10+
export class AuthService {
11+
constructor(private readonly databaseService: DatabaseService) {}
12+
13+
generateNonce(length: number = 8): string {
14+
return crypto
15+
.randomBytes(Math.ceil(length / 2))
16+
.toString('hex')
17+
.slice(0, length);
18+
}
19+
20+
async verifyPayload(payload: MiniAppWalletAuthSuccessPayload, nonce: string) {
21+
const validMessage = await verifySiweMessage(payload, nonce);
22+
return validMessage.isValid;
23+
}
24+
}

src/main.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { NestFactory } from '@nestjs/core';
22
import { AppModule } from './app.module';
3+
import * as cookieParser from 'cookie-parser';
34

45
async function bootstrap() {
56
const app = await NestFactory.create(AppModule);
7+
app.use(cookieParser());
8+
69
await app.listen(process.env.PORT ?? 3000);
710
}
811
bootstrap();

0 commit comments

Comments
 (0)