- Switch VK ID authentication to use JWT tokens
- Implement JWT verification and decoding
- Validate JWT issuer and app ID
- Add VKID OAuth integration and constants
This commit is contained in:
2025-01-25 22:52:04 +04:00
parent bb73b83edf
commit 05b195926b
3 changed files with 42 additions and 16 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "schedule-parser-next", "name": "schedule-parser-next",
"version": "3.0.0", "version": "3.0.1",
"description": "", "description": "",
"author": "N08I40K", "author": "N08I40K",
"private": true, "private": true,
@@ -41,6 +41,7 @@
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"firebase-admin": "^13.0.2", "firebase-admin": "^13.0.2",
"jsdom": "^26.0.0", "jsdom": "^26.0.0",
"jsonwebtoken": "^9.0.2",
"object-hash": "^3.0.0", "object-hash": "^3.0.0",
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",

View File

@@ -1,6 +1,7 @@
import { import {
ConflictException, ConflictException,
Injectable, Injectable,
NotAcceptableException,
UnauthorizedException, UnauthorizedException,
} from "@nestjs/common"; } from "@nestjs/common";
import { JwtService } from "@nestjs/jwt"; import { JwtService } from "@nestjs/jwt";
@@ -15,8 +16,8 @@ import SignUpErrorDto, { SignUpErrorCode } from "./dto/sign-up-error.dto";
import { SignInDto, SignInVKDto } from "./dto/sign-in.dto"; import { SignInDto, SignInVKDto } from "./dto/sign-in.dto";
import ObjectID from "bson-objectid"; import ObjectID from "bson-objectid";
import UserDto from "../users/dto/user.dto"; import UserDto from "../users/dto/user.dto";
import { decodeJwt, verifyJwtSignature } from "firebase-admin/lib/utils/jwt";
import { vkIdConstants } from "../contants"; import { vkIdConstants } from "../contants";
import * as jwt from "jsonwebtoken";
@Injectable() @Injectable()
export class AuthService { export class AuthService {
@@ -136,16 +137,6 @@ export class AuthService {
* } * }
*/ */
private static async parseVKID(idToken: string): Promise<number> { private static async parseVKID(idToken: string): Promise<number> {
try {
await verifyJwtSignature(idToken, vkIdConstants.jwtPubKey, {
issuer: "VK",
jwtid: "21",
});
} catch {
return null;
}
const decodedToken = await decodeJwt(idToken);
type TokenData = { type TokenData = {
iis: string; iis: string;
sub: number; sub: number;
@@ -155,9 +146,45 @@ export class AuthService {
jti: number; jti: number;
}; };
const payload = decodedToken.payload as TokenData; const payload = await new Promise<TokenData>((resolve, reject) => {
jwt.verify(idToken, vkIdConstants.jwtPubKey, (err, data) => {
if (err) return reject(new NotAcceptableException(err.message));
if (payload.app !== vkIdConstants.clientId) return null; const payload = data as unknown as TokenData;
if (typeof payload !== "object") {
return reject(
new NotAcceptableException("Invalid token payload"),
);
}
if (payload.iis !== "VK") {
return reject(
new NotAcceptableException(
`Unknown issuer, excepted "VK", got "${payload.iis}"`,
),
);
}
if (payload.jti !== 21) {
return reject(
new NotAcceptableException(
`Unknown type, excepted 21, got ${payload.jti}`,
),
);
}
if (payload.app !== vkIdConstants.clientId) {
return reject(
new NotAcceptableException(
`Invalid client_id ${payload.app}`,
),
);
}
resolve(payload);
});
});
return payload.sub; return payload.sub;
} }

View File

@@ -38,8 +38,6 @@ export class VKIDController {
const result = await this.vkidService.oauth(oAuthRequestDto); const result = await this.vkidService.oauth(oAuthRequestDto);
if (!result) throw new NotAcceptableException("OAuth process failed"); if (!result) throw new NotAcceptableException("OAuth process failed");
console.log("Access token exchanged!", result.accessToken);
return result; return result;
} }
} }