feat: remove unused packages, config
This commit is contained in:
parent
bc4dcc26ef
commit
e52c9acf2d
@ -23,7 +23,6 @@
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/config": "^3.3.0",
|
||||
"@nestjs/core": "^10.0.0",
|
||||
"@nestjs/jwt": "^10.2.0",
|
||||
"@nestjs/mapped-types": "^2.0.6",
|
||||
"@nestjs/platform-express": "^10.4.11",
|
||||
"@nestjs/platform-socket.io": "^10.4.12",
|
||||
@ -34,6 +33,7 @@
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.1",
|
||||
"joi": "^17.13.3",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"jwks-rsa": "^3.1.0",
|
||||
"nestjs-prisma": "^0.23.0",
|
||||
"prisma": "^6.0.1",
|
||||
|
@ -1,7 +1,6 @@
|
||||
import env from "@Config/env";
|
||||
import { Module } from "@nestjs/common";
|
||||
import { ConfigModule, ConfigService } from "@nestjs/config";
|
||||
import { JwtModule } from "@nestjs/jwt";
|
||||
import { ConfigModule } from "@nestjs/config";
|
||||
import { envValidation } from "@Validations/env.validation";
|
||||
|
||||
import { AuthModule } from "@Modules/auth/auth.module";
|
||||
@ -17,16 +16,6 @@ import { ClassModule } from "./modules/class/class.module";
|
||||
load: [env],
|
||||
validationSchema: envValidation,
|
||||
}),
|
||||
JwtModule.registerAsync({
|
||||
global: true,
|
||||
inject: [ConfigService],
|
||||
useFactory: async (configService: ConfigService) => ({
|
||||
secret: configService.get<string>("JWT.secret"),
|
||||
signOptions: {
|
||||
expiresIn: configService.get<string>("JWT.expiresIn"),
|
||||
},
|
||||
}),
|
||||
}),
|
||||
PrismaModule.forRoot({
|
||||
isGlobal: true,
|
||||
}),
|
||||
@ -34,6 +23,6 @@ import { ClassModule } from "./modules/class/class.module";
|
||||
AuthModule,
|
||||
ClassModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
controllers: [AppController]
|
||||
})
|
||||
export class AppModule {}
|
||||
|
@ -1,19 +1,6 @@
|
||||
export default () => ({
|
||||
JWT: {
|
||||
secret: process.env.JWT_SECRET,
|
||||
expiresIn: process.env.JWT_EXPIRES_IN,
|
||||
refresh: {
|
||||
secret: process.env.REFRESH_JWT_SECRET,
|
||||
expiresIn: process.env.REFRESH_JWT_EXPIRES_IN,
|
||||
},
|
||||
},
|
||||
oauth2: {
|
||||
authorizationURL: process.env.OAUTH2_AUTHORIZATION_URL,
|
||||
tokenURL: process.env.OAUTH2_TOKEN_URL,
|
||||
clientID: process.env.OAUTH2_CLIENT_ID,
|
||||
clientSecret: process.env.OAUTH2_CLIENT_SECRET,
|
||||
callbackURL: process.env.OAUTH2_CALLBACK_URL,
|
||||
profileURL: process.env.OAUTH2_PROFILE_URL,
|
||||
scopes: process.env.OAUTH2_SCOPES,
|
||||
auth: {
|
||||
jwksURL: process.env.AUTH_JWKS_URI,
|
||||
usernameField: process.env.AUTH_USERNAME_FIELD
|
||||
},
|
||||
});
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { UserModule } from "@Modules/user/user.module";
|
||||
import { Module } from "@nestjs/common";
|
||||
import { AuthService } from "./auth.service";
|
||||
|
||||
@Module({
|
||||
imports: [UserModule],
|
||||
providers: [AuthService],
|
||||
exports: [AuthService],
|
||||
})
|
||||
export class AuthModule {}
|
||||
|
@ -1,41 +1,49 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { Injectable, UnauthorizedException } from "@nestjs/common";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import { JwtService } from "@nestjs/jwt";
|
||||
import * as jwt from "jsonwebtoken";
|
||||
import JwksRsa, * as jwksRsa from "jwks-rsa";
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(
|
||||
private readonly jwtService: JwtService,
|
||||
private readonly configService: ConfigService,
|
||||
) {}
|
||||
private jwksClient: JwksRsa.JwksClient;
|
||||
|
||||
accessToken(user: { id: string }) {
|
||||
return this.jwtService.sign(
|
||||
{ id: user.id },
|
||||
{
|
||||
secret: this.configService.get<string>("JWT.secret"),
|
||||
expiresIn: this.configService.get<string>("JWT.expiresIn"),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
refreshToken(user: { id: string }) {
|
||||
return this.jwtService.sign(
|
||||
{ id: user.id },
|
||||
{
|
||||
secret: this.configService.get<string>("JWT.refresh.secret"),
|
||||
expiresIn: this.configService.get<string>(
|
||||
"JWT.refresh.expiresIn",
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async verifyToken(token: string): Promise<{
|
||||
id: string;
|
||||
}> {
|
||||
return await this.jwtService.verifyAsync(token, {
|
||||
secret: this.configService.get<string>("JWT.secret"),
|
||||
constructor(configService: ConfigService) {
|
||||
this.jwksClient = jwksRsa({
|
||||
jwksUri: configService.get<string>("AUTH_JWKS_URI"),
|
||||
cache: true,
|
||||
rateLimit: true,
|
||||
jwksRequestsPerMinute: 10,
|
||||
});
|
||||
}
|
||||
|
||||
async getSigningKey(kid: string): Promise<string> {
|
||||
const key = await this.jwksClient.getSigningKey(kid);
|
||||
return key.getPublicKey();
|
||||
}
|
||||
|
||||
decodeJwt(token: string) {
|
||||
return jwt.decode(token, { complete: true });
|
||||
}
|
||||
|
||||
verifyJwt(token: string, key: string) {
|
||||
return jwt.verify(token, key, {
|
||||
algorithms: ["RS256"],
|
||||
});
|
||||
}
|
||||
|
||||
async checkToken(token: string): Promise<jwt.JwtPayload> {
|
||||
const decodedHeader = this.decodeJwt(token);
|
||||
const kid = decodedHeader?.header?.kid;
|
||||
|
||||
if (!kid) throw "Token kid not found";
|
||||
|
||||
const key = await this.getSigningKey(kid);
|
||||
|
||||
const jwtPayload = this.verifyJwt(token, key);
|
||||
|
||||
if (typeof jwtPayload == "string")
|
||||
throw new UnauthorizedException("Invalid token");
|
||||
|
||||
return jwtPayload;
|
||||
}
|
||||
}
|
||||
|
@ -5,25 +5,16 @@ import {
|
||||
Injectable,
|
||||
UnauthorizedException,
|
||||
} from "@nestjs/common";
|
||||
import { AuthService } from "../auth.service";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import * as jwt from "jsonwebtoken";
|
||||
import * as jwksRsa from "jwks-rsa";
|
||||
|
||||
@Injectable()
|
||||
export class JwtAuthGuard implements CanActivate {
|
||||
private jwksClient: jwksRsa.JwksClient;
|
||||
|
||||
constructor(
|
||||
private readonly userService: UserService,
|
||||
configService: ConfigService,
|
||||
) {
|
||||
this.jwksClient = jwksRsa({
|
||||
jwksUri: configService.get<string>("AUTH_JWKS_URI"),
|
||||
cache: true,
|
||||
rateLimit: true,
|
||||
jwksRequestsPerMinute: 10,
|
||||
});
|
||||
}
|
||||
private readonly authService: AuthService,
|
||||
private readonly configService: ConfigService,
|
||||
) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
@ -34,25 +25,11 @@ export class JwtAuthGuard implements CanActivate {
|
||||
}
|
||||
|
||||
try {
|
||||
const decodedHeader: any = jwt.decode(token, { complete: true });
|
||||
const kid = decodedHeader?.header?.kid;
|
||||
|
||||
if (!kid) {
|
||||
throw new UnauthorizedException("Token kid not found");
|
||||
}
|
||||
|
||||
const key = await this.getSigningKey(kid);
|
||||
|
||||
const verifiedToken = jwt.verify(token, key, {
|
||||
algorithms: ["RS256"],
|
||||
});
|
||||
|
||||
if (typeof verifiedToken == "string")
|
||||
throw new UnauthorizedException("Invalid token");
|
||||
const jwtPayload = await this.authService.checkToken(token);
|
||||
|
||||
let user = await this.userService.findOrCreateByProviderId({
|
||||
providerId: verifiedToken.sub.toString(),
|
||||
username: verifiedToken.preferred_username,
|
||||
providerId: jwtPayload.sub.toString(),
|
||||
username: jwtPayload[this.configService.get("auth.usernameField")],
|
||||
});
|
||||
|
||||
request.user = user;
|
||||
@ -74,9 +51,4 @@ export class JwtAuthGuard implements CanActivate {
|
||||
|
||||
return parts[1];
|
||||
}
|
||||
|
||||
private async getSigningKey(kid: string): Promise<string> {
|
||||
const key = await this.jwksClient.getSigningKey(kid);
|
||||
return key.getPublicKey();
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { ClassService } from "./class.service";
|
||||
import { ClassController } from "./class.controller";
|
||||
import { UserService } from "../user/user.service";
|
||||
import { UserModule } from "../user/user.module";
|
||||
|
||||
@Module({
|
||||
imports: [UserModule],
|
||||
controllers: [ClassController],
|
||||
providers: [ClassService, UserService],
|
||||
providers: [ClassService],
|
||||
})
|
||||
export class ClassModule {}
|
||||
|
@ -9,12 +9,14 @@ import {
|
||||
import { Server, Socket } from "socket.io";
|
||||
import { AuthService } from "../auth/auth.service";
|
||||
import { UserService } from "./user.service";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
|
||||
@WebSocketGateway()
|
||||
export class UserGateway implements OnGatewayConnection, OnGatewayDisconnect {
|
||||
constructor(
|
||||
private readonly authService: AuthService,
|
||||
private readonly userService: UserService,
|
||||
private readonly configService: ConfigService,
|
||||
) {}
|
||||
|
||||
@WebSocketServer() io: Server;
|
||||
@ -22,16 +24,21 @@ export class UserGateway implements OnGatewayConnection, OnGatewayDisconnect {
|
||||
public clients: Socket[] = [];
|
||||
|
||||
async handleConnection(client: Socket) {
|
||||
const Authorization = client.handshake.headers.authorization;
|
||||
const token = client.handshake.headers.authorization;
|
||||
|
||||
try {
|
||||
var jwtDecoded = await this.authService.verifyToken(Authorization);
|
||||
var jwtPayload = await this.authService.checkToken(token);
|
||||
|
||||
if (!jwtPayload) throw "Invalid token";
|
||||
} catch (error) {
|
||||
client.emit("auth", error);
|
||||
return client.disconnect();
|
||||
}
|
||||
|
||||
const user = await this.userService.findOne(jwtDecoded.id);
|
||||
const user = await this.userService.findOrCreateByProviderId({
|
||||
providerId: jwtPayload.sub.toString(),
|
||||
username: jwtPayload[this.configService.get("auth.usernameField")],
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
client.emit("auth", "User not found");
|
||||
|
@ -7,8 +7,8 @@ import { UserGateway } from "./user.gateway";
|
||||
import { UserService } from "./user.service";
|
||||
|
||||
@Module({
|
||||
providers: [UserService, PrismaService, UserGateway, AuthService],
|
||||
providers: [UserService, AuthService, PrismaService, UserGateway],
|
||||
controllers: [UserController],
|
||||
exports: [UserService],
|
||||
exports: [UserService, AuthService],
|
||||
})
|
||||
export class UserModule {}
|
||||
|
@ -52,10 +52,9 @@ export class UserService {
|
||||
providerId: string;
|
||||
username: string;
|
||||
}) {
|
||||
let user = await this.prisma.user.findUnique({
|
||||
let user = await this.prisma.user.findFirst({
|
||||
where: {
|
||||
providerId,
|
||||
username,
|
||||
OR: [{ providerId }, { username }],
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -4,6 +4,7 @@ export const envValidation = Joi.object({
|
||||
DATABASE_URL: Joi.string().required(),
|
||||
|
||||
AUTH_JWKS_URI: Joi.string().uri().required(),
|
||||
AUTH_USERNAME_FIELD: Joi.string().required(),
|
||||
|
||||
PORT: Joi.number().optional(),
|
||||
});
|
||||
|
17
yarn.lock
17
yarn.lock
@ -318,14 +318,6 @@
|
||||
path-to-regexp "3.3.0"
|
||||
tslib "2.8.1"
|
||||
|
||||
"@nestjs/jwt@^10.2.0":
|
||||
version "10.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@nestjs/jwt/-/jwt-10.2.0.tgz#6aa35a04922d19c6426efced4671620f92e6dbd0"
|
||||
integrity sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==
|
||||
dependencies:
|
||||
"@types/jsonwebtoken" "9.0.5"
|
||||
jsonwebtoken "9.0.2"
|
||||
|
||||
"@nestjs/mapped-types@2.0.6", "@nestjs/mapped-types@^2.0.6":
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.6.tgz#d2d8523709fd5d872a9b9e0c38162746e2a7f44e"
|
||||
@ -617,13 +609,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||
|
||||
"@types/jsonwebtoken@9.0.5":
|
||||
version "9.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz#0bd9b841c9e6c5a937c17656e2368f65da025588"
|
||||
integrity sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/jsonwebtoken@^9.0.2":
|
||||
version "9.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz#e49b96c2b29356ed462e9708fc73b833014727d2"
|
||||
@ -2301,7 +2286,7 @@ jsonfile@^6.0.1:
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonwebtoken@9.0.2:
|
||||
jsonwebtoken@^9.0.2:
|
||||
version "9.0.2"
|
||||
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3"
|
||||
integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==
|
||||
|
Loading…
Reference in New Issue
Block a user