-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(auth): implement Secure Remote Password (SRP) authentication #386
Changes from 6 commits
b669db1
d6baa03
d3013ae
4dd36f8
4640051
e2a88c1
ac2c989
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
-- AlterTable | ||
ALTER TABLE "user" ADD COLUMN "srp_salt" VARCHAR(500), | ||
ADD COLUMN "srp_upgraded" BOOLEAN NOT NULL DEFAULT false, | ||
ADD COLUMN "srp_verifier" VARCHAR(1000); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
-- AlterTable | ||
ALTER TABLE "user" ALTER COLUMN "hashed_password" DROP NOT NULL; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
-- AlterTable | ||
ALTER TABLE "user" ADD COLUMN "last_password_changed_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP; |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -1,3 +1,5 @@ | ||||||||||
APP_NAME=Cheese | ||||||||||
|
||||||||||
# The port that the app will listen to | ||||||||||
PORT=3000 | ||||||||||
|
||||||||||
|
@@ -70,3 +72,13 @@ EMAILTEST_RECEIVER=developer@example.com | |||||||||
|
||||||||||
# Use real ip or X-Forwarded-For header | ||||||||||
TRUST_X_FORWARDED_FOR=false | ||||||||||
|
||||||||||
REDIS_HOST=valkey | ||||||||||
REDIS_PORT=6379 | ||||||||||
# REDIS_USERNAME= | ||||||||||
# REDIS_PASSWORD= | ||||||||||
|
||||||||||
WEB_AUTHN_RP_NAME=Cheese Community | ||||||||||
WEB_AUTHN_RP_ID=localhost | ||||||||||
WEB_AUTHN_ORIGIN=http://localhost:3000 | ||||||||||
TOTP_ENCRYPTION_KEY=sm2vSXU3SudEuBd2r6ewGiap1LbqGbjf | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove hardcoded TOTP encryption key. The hardcoded encryption key in the sample environment file poses a security risk if accidentally used in production. Replace the hardcoded key with a placeholder and add instructions for generating a secure key: -TOTP_ENCRYPTION_KEY=sm2vSXU3SudEuBd2r6ewGiap1LbqGbjf
+# Generate a secure 32-byte key for production using:
+# node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
+TOTP_ENCRYPTION_KEY=your_secure_random_key_here 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { IsString } from 'class-validator'; | ||
import { BaseResponseDto } from '../../common/DTO/base-response.dto'; | ||
|
||
export class ChangePasswordRequestDto { | ||
@IsString() | ||
srpSalt: string; // 新密码的 SRP 凭证 | ||
|
||
@IsString() | ||
srpVerifier: string; // 新密码的 SRP 凭证 | ||
} | ||
|
||
export class ChangePasswordResponseDto extends BaseResponseDto {} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -21,6 +21,10 @@ export class PasskeyRegistrationVerifyRequestDto { | |||||||||||||||||||||
export class PasskeyRegistrationVerifyResponseDto extends BaseResponseDto {} | ||||||||||||||||||||||
|
||||||||||||||||||||||
// Authentication DTOs | ||||||||||||||||||||||
export class PasskeyAuthenticationOptionsRequestDto { | ||||||||||||||||||||||
userId?: number; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
Comment on lines
+24
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add validation decorator for optional number field. The export class PasskeyAuthenticationOptionsRequestDto {
+ @IsNumber()
+ @IsOptional()
userId?: number;
} Import the decorator: + import { IsNumber, IsOptional } from 'class-validator'; 📝 Committable suggestion
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @HuanCheng65 See this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||
|
||||||||||||||||||||||
export class PasskeyAuthenticationOptionsResponseDto extends BaseResponseDto { | ||||||||||||||||||||||
data: { | ||||||||||||||||||||||
options: PublicKeyCredentialRequestOptionsJSON; | ||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,33 @@ | ||||||||||||||||||||||||||
/* | ||||||||||||||||||||||||||
* Description: This file defines the DTOs for SRP authentication. | ||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
import { BaseResponseDto } from '../../common/DTO/base-response.dto'; | ||||||||||||||||||||||||||
import { UserDto } from '../../users/DTO/user.dto'; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
export class SrpInitRequestDto { | ||||||||||||||||||||||||||
username: string; | ||||||||||||||||||||||||||
clientPublicEphemeral: string; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
Comment on lines
+8
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add validation decorators for required fields. The fields are required but lack validation decorators. Consider adding export class SrpInitRequestDto {
+ @IsString()
username: string;
+ @IsString()
clientPublicEphemeral: string;
} Import the decorator: + import { IsString } from 'class-validator'; 📝 Committable suggestion
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
export class SrpInitResponseDto extends BaseResponseDto { | ||||||||||||||||||||||||||
data: { | ||||||||||||||||||||||||||
salt: string; | ||||||||||||||||||||||||||
serverPublicEphemeral: string; | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
export class SrpVerifyRequestDto { | ||||||||||||||||||||||||||
username: string; | ||||||||||||||||||||||||||
clientProof: string; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
Comment on lines
+20
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add validation decorators for required fields. The fields are required but lack validation decorators. Consider adding export class SrpVerifyRequestDto {
+ @IsString()
username: string;
+ @IsString()
clientProof: string;
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
export class SrpVerifyResponseDto extends BaseResponseDto { | ||||||||||||||||||||||||||
data: { | ||||||||||||||||||||||||||
serverProof: string; | ||||||||||||||||||||||||||
accessToken: string; | ||||||||||||||||||||||||||
requires2FA: boolean; | ||||||||||||||||||||||||||
tempToken?: string; | ||||||||||||||||||||||||||
user?: UserDto; | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this change?