mirror of
https://github.com/n08i40k/schedule-parser-next.git
synced 2025-12-06 09:47:46 +03:00
Switch VK ID authentication to use JWT tokens
- Replace access token with JWT id token - Add JWT public key for VK ID - Implement JWT verification and decoding - Validate JWT issuer and app ID
This commit is contained in:
@@ -9,13 +9,14 @@ import { compare, genSalt, hash } from "bcrypt";
|
|||||||
import UserRole from "../users/user-role.enum";
|
import UserRole from "../users/user-role.enum";
|
||||||
import User from "../users/entity/user.entity";
|
import User from "../users/entity/user.entity";
|
||||||
import ChangePasswordDto from "./dto/change-password.dto";
|
import ChangePasswordDto from "./dto/change-password.dto";
|
||||||
import axios from "axios";
|
|
||||||
import SignInErrorDto, { SignInErrorCode } from "./dto/sign-in-error.dto";
|
import SignInErrorDto, { SignInErrorCode } from "./dto/sign-in-error.dto";
|
||||||
import { SignUpDto, SignUpVKDto } from "./dto/sign-up.dto";
|
import { SignUpDto, SignUpVKDto } from "./dto/sign-up.dto";
|
||||||
import SignUpErrorDto, { SignUpErrorCode } from "./dto/sign-up-error.dto";
|
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";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
@@ -123,7 +124,7 @@ export class AuthService {
|
|||||||
/**
|
/**
|
||||||
* Парсит VK ID пользователя по access token
|
* Парсит VK ID пользователя по access token
|
||||||
*
|
*
|
||||||
* @param accessToken - Access token пользователя VK
|
* @param idToken - Access token пользователя VK
|
||||||
* @returns Promise, который разрешается в VK ID пользователя или null в случае ошибки
|
* @returns Promise, который разрешается в VK ID пользователя или null в случае ошибки
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -134,26 +135,31 @@ export class AuthService {
|
|||||||
* console.error('Ошибка при получении VK ID');
|
* console.error('Ошибка при получении VK ID');
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
private static async parseVKID(accessToken: string): Promise<number> {
|
private static async parseVKID(idToken: string): Promise<number> {
|
||||||
const form = new FormData();
|
try {
|
||||||
form.append("access_token", accessToken);
|
await verifyJwtSignature(idToken, vkIdConstants.jwtPubKey, {
|
||||||
form.append("v", "5.199");
|
issuer: "VK",
|
||||||
|
jwtid: "21",
|
||||||
const response = await axios.post(
|
});
|
||||||
"https://api.vk.com/method/account.getProfileInfo",
|
} catch {
|
||||||
form,
|
|
||||||
{ responseType: "json" },
|
|
||||||
);
|
|
||||||
|
|
||||||
const data: { error?: any; response?: { id: number } } =
|
|
||||||
response.data as object;
|
|
||||||
|
|
||||||
if (response.status !== 200 || data.error !== undefined) {
|
|
||||||
console.warn(data);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.response.id;
|
const decodedToken = await decodeJwt(idToken);
|
||||||
|
type TokenData = {
|
||||||
|
iis: string;
|
||||||
|
sub: number;
|
||||||
|
app: number;
|
||||||
|
exp: number;
|
||||||
|
iat: number;
|
||||||
|
jti: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const payload = decodedToken.payload as TokenData;
|
||||||
|
|
||||||
|
if (payload.app !== vkIdConstants.clientId) return null;
|
||||||
|
|
||||||
|
return payload.sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,6 +6,21 @@ configDotenv();
|
|||||||
export const vkIdConstants = {
|
export const vkIdConstants = {
|
||||||
clientId: +process.env.VKID_CLIENT_ID,
|
clientId: +process.env.VKID_CLIENT_ID,
|
||||||
redirectUri: process.env.VKID_REDIRECT_URI,
|
redirectUri: process.env.VKID_REDIRECT_URI,
|
||||||
|
jwtPubKey:
|
||||||
|
"-----BEGIN PUBLIC KEY-----\n" +
|
||||||
|
"MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvsvJlhFX9Ju/pvCz1frB\n" +
|
||||||
|
"DgJs592VjdwQuRAmnlJAItyHkoiDIOEocPzgcUBTbDf1plDcTyO2RCkUt0pz0WK6\n" +
|
||||||
|
"6HNhpJyIfARjaWHeUlv4TpuHXAJJsBKklkU2gf1cjID+40sWWYjtq5dAkXnSJUVA\n" +
|
||||||
|
"UR+sq0lJ7GmTdJtAr8hzESqGEcSP15PTs7VUdHZ1nkC2XgkuR8KmKAUb388ji1Q4\n" +
|
||||||
|
"n02rJNOPQgd9r0ac4N2v/yTAFPXumO78N25bpcuWf5vcL9e8THk/U2zt7wf+aAWL\n" +
|
||||||
|
"748e0pREqNluTBJNZfmhC79Xx6GHtwqHyyduiqfPmejmiujNM/rqnA4e30Tg86Yn\n" +
|
||||||
|
"cNZ6vLJyF72Eva1wXchukH/aLispbY+EqNPxxn4zzCWaLKHG87gaCxpVv9Tm0jSD\n" +
|
||||||
|
"2es22NjrUbtb+2pAGnXbyDp2eGUqw0RrTQFZqt/VcmmSCE45FlcZMT28otrwG1ZB\n" +
|
||||||
|
"kZAb5Js3wLEch3ZfYL8sjhyNRPBmJBrAvzrd8qa3rdUjkC9sKyjGAaHu2MNmFl1Y\n" +
|
||||||
|
"JFQ3J54tGpkGgJjD7Kz3w0K6OiPDlVCNQN5sqXm24fCw85Pbi8SJiaLTp/CImrs1\n" +
|
||||||
|
"Z3nHW5q8hljA7OGmqfOP0nZS/5zW9GHPyepsI1rW6CympYLJ15WeNzePxYS5KEX9\n" +
|
||||||
|
"EncmkSD9b45ge95hJeJZteUCAwEAAQ==\n" +
|
||||||
|
"-----END PUBLIC KEY-----",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const jwtConstants = {
|
export const jwtConstants = {
|
||||||
|
|||||||
@@ -21,16 +21,16 @@ export class VKIDService {
|
|||||||
`redirect_uri=${vkIdConstants.redirectUri}`,
|
`redirect_uri=${vkIdConstants.redirectUri}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const accessToken: string = (response.data as { access_token: string })
|
const idToken: string = (response.data as { id_token: string })
|
||||||
.access_token;
|
.id_token;
|
||||||
|
|
||||||
if (!accessToken) {
|
if (!idToken) {
|
||||||
console.error(response.data);
|
console.error(response.data);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new OAuthResponseDto({
|
return new OAuthResponseDto({
|
||||||
accessToken: accessToken,
|
accessToken: idToken,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user