-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Full flow working with ethereum signatures
- Loading branch information
Showing
13 changed files
with
27,959 additions
and
14,205 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,31 @@ | ||
import { Controller, Post, UseGuards, Request, Get } from '@nestjs/common'; | ||
import { Controller, Post, UseGuards, Request, Get, Param, Body } from '@nestjs/common'; | ||
import { ApiTags } from '@nestjs/swagger'; | ||
import { Public } from './auth.decorator'; | ||
import { AuthService } from './auth.service'; | ||
import { LoginDto } from './dto/login.dto'; | ||
import { JwtAuthGuard } from './jwt-auth.guard'; | ||
import { LocalAuthGuard } from './local-auth.guard'; | ||
|
||
@ApiTags('Auth') | ||
@Controller() | ||
export class AuthController { | ||
constructor(private authService: AuthService) { } | ||
// eslint-disable-next-line @typescript-eslint/require-await | ||
@Public() | ||
@UseGuards(LocalAuthGuard) | ||
@Post('login') | ||
async login(@Request() req) { | ||
async login( | ||
@Body('client_assertion_type') clientAssertionType: string, | ||
@Body('client_assertion') clientAssertion: string, | ||
): Promise<LoginDto> { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access | ||
return this.authService.login(req.user); | ||
return this.authService.validateClaim(clientAssertionType, clientAssertion); | ||
} | ||
|
||
// Test endpoint | ||
@UseGuards(JwtAuthGuard) | ||
@Get('profile') | ||
getProfile(@Request() req) { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access | ||
console.log(req.user); | ||
return req.user; | ||
} | ||
} |
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,34 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { Injectable, UnauthorizedException } from '@nestjs/common'; | ||
import { JwtService } from '@nestjs/jwt'; | ||
import { UsersService } from '../users/users.service'; | ||
import { JWTPayload } from 'jose'; | ||
import { CLIENT_ASSERTION_TYPE } from './constants'; | ||
import { LoginDto } from './dto/login.dto'; | ||
import { jwtEthVerify } from './jwt.utils'; | ||
|
||
@Injectable() | ||
export class AuthService { | ||
constructor(private usersService: UsersService, private jwtService: JwtService) { } | ||
constructor(private jwtService: JwtService) { } | ||
|
||
async validateUser(username: string, pass: string): Promise<any> { | ||
const user = await this.usersService.findOne(username); | ||
if (user && user.password === pass) { | ||
const { password, ...result } = user; | ||
return result; | ||
// RFC-7523 Client Authentication https://datatracker.ietf.org/doc/html/rfc7523#section-2.2 | ||
// RFC-8812 ECDSA Signature with secp256k1 Curve (ES256K) | ||
// https://www.rfc-editor.org/rfc/rfc8812#name-ecdsa-signature-with-secp25 | ||
// This implementation is different from the standard in: | ||
// - the size of the signature. ethereum adds an extra byte to the signature to help | ||
// with recovering the public key that create the signature | ||
// - the hash function used. ES256K uses sha-256 while ethereum uses keccak | ||
async validateClaim(clientAssertionType: string, clientAssertion: string): Promise<LoginDto> { | ||
if (clientAssertionType !== CLIENT_ASSERTION_TYPE) { | ||
throw new UnauthorizedException('Invalid "client_assertion_type"'); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
async login(user: any) { | ||
const payload = { username: user.username, sub: user.userId }; | ||
let payload: JWTPayload; | ||
try { | ||
payload = await jwtEthVerify(clientAssertion); | ||
} catch (error) { | ||
throw new UnauthorizedException(`The 'client_assertion' is invalid: ${error.message}`); | ||
} | ||
return { | ||
access_token: this.jwtService.sign(payload) | ||
access_token: this.jwtService.sign({ iss: payload.iss }) | ||
}; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
export const jwtConstants = { | ||
secret: 'secretKey' | ||
}; | ||
}; | ||
|
||
export const CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { ApiProperty } from "@nestjs/swagger"; | ||
import { IsString } from "class-validator"; | ||
|
||
export class LoginDto { | ||
@ApiProperty({ | ||
description: `The Authorization Bearer token`, | ||
example: '{"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0.eyJpc3Mi[...omitted for brevity...]"}' | ||
}) | ||
@IsString() | ||
access_token: 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
Oops, something went wrong.