Created
August 29, 2022 21:29
-
-
Save jdnichollsc/705a83229868ee1d112f42f05a3971e0 to your computer and use it in GitHub Desktop.
Verify that a request is signed by the owner of the public key (NestJS, ExpressJS and Solana)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ApiProperty } from '@nestjs/swagger'; | |
export class UserSignatureDto { | |
@ApiProperty({ description: 'Wallet base58-encoded public key' }) | |
walletPK: string; | |
@ApiProperty({ description: 'base58-encoded signature of a unique message' }) | |
signature: string; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Controller, | |
UseGuards, | |
Req, | |
Post, | |
Body, | |
UnauthorizedException, | |
} from '@nestjs/common'; | |
import { AuthGuard } from '@nestjs/passport'; | |
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; | |
import { Request } from 'express'; | |
import nacl from 'tweetnacl'; | |
import { PublicKey } from '@solana/web3.js'; | |
import b58 from 'bs58'; | |
import { UserService } from './user.service'; | |
import { UserSignatureDto } from './user-signature.dto'; | |
@ApiBearerAuth() | |
@UseGuards(AuthGuard('jwt')) | |
@ApiTags('User') | |
@Controller('user') | |
export class UserController { | |
constructor(private readonly userService: UserService) {} | |
@ApiOperation({ summary: `Verify that the request is signed by the owner of the public key` }) | |
@Post('wallet') | |
async verifySignature( | |
@Req() req: Request, | |
@Body() signatureDto: UserSignatureDto, | |
) { | |
const { walletPK, signature } = signatureDto; | |
const message = `UserId: ${req.user.userId}`; | |
const encodedMessage = new TextEncoder().encode(message); | |
const hasValidSig = nacl.sign.detached.verify( | |
encodedMessage, | |
b58.decode(signature), | |
new PublicKey(walletPK).toBytes(), | |
); | |
if (!hasValidSig) { | |
throw new UnauthorizedException('Invalid signature'); | |
} | |
const user = await this.userService.findOneByEmail(req.user.email); | |
user.walletPK = walletPK; | |
return await this.userService.update(user.userId, user); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment