From d49b2cf7e5cd850cc3a9dd32f9c8e4d78e8bec7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Fri, 27 Mar 2026 11:36:20 +0300 Subject: [PATCH] feat: add generic from payload data --- lib/interfaces/token.interface.ts | 14 ++--------- lib/passport.service.ts | 39 ++++++++++++++----------------- 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/lib/interfaces/token.interface.ts b/lib/interfaces/token.interface.ts index 8dac8f5..fbeacbc 100644 --- a/lib/interfaces/token.interface.ts +++ b/lib/interfaces/token.interface.ts @@ -1,13 +1,3 @@ -export interface TokenPayload { - sub: string -} - -// роли храним в токене -export interface TokenRolePayload { - id: string | number - name: string -} - -export type VerifyResult = - | { valid: true; userId: string; jti: string; role: TokenRolePayload } +export type VerifyResult = + | { valid: true; payload: T; jti: string } | { valid: false; reason: string } diff --git a/lib/passport.service.ts b/lib/passport.service.ts index 90af7b6..57704b2 100644 --- a/lib/passport.service.ts +++ b/lib/passport.service.ts @@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common' import { createHmac, randomUUID } from 'crypto' import { PASSPORT_OPTIONS } from './constants' -import { PassportOptions, TokenRolePayload } from './interfaces' +import { PassportOptions } from './interfaces' import { base64UrlDecode, base64UrlEncode, constantTimeEqual } from './utils' const TOKEN_TYPES = { @@ -24,9 +24,8 @@ export class PassportService { this.SECRET_KEY = options.secretKey } - public generate( - userId: string, - role: TokenRolePayload, + public generate>( + payload: T, ttl: number, tokenType: TokenType = TOKEN_TYPES.AUTH ) { @@ -35,38 +34,38 @@ export class PassportService { const jti = randomUUID() - const userPart = base64UrlEncode(userId) - const rolePart = base64UrlEncode(JSON.stringify(role)) + const payloadPart = base64UrlEncode(JSON.stringify(payload)) const iatPart = base64UrlEncode(String(issuedAt)) const expPart = base64UrlEncode(String(expiresAt)) const jtiPart = base64UrlEncode(jti) const serialized = this.serialize( tokenType, - userPart, - rolePart, + payloadPart, iatPart, expPart, jtiPart ) const mac = this.computeHmac(this.SECRET_KEY, serialized) - return `${userPart}.${rolePart}.${iatPart}.${expPart}.${jtiPart}.${mac}` + return `${payloadPart}.${iatPart}.${expPart}.${jtiPart}.${mac}` } - public verify(token: string, expectedType: TokenType = TOKEN_TYPES.AUTH) { + public verify( + token: string, + expectedType: TokenType = TOKEN_TYPES.AUTH + ) { try { const parts = token.split('.') - if (parts.length !== 6) + if (parts.length !== 5) return { valid: false, reason: 'Не верный формат токена.' } - const [userPart, rolePart, iatPart, expPart, jtiPart, mac] = parts + const [payloadPart, iatPart, expPart, jtiPart, mac] = parts const serialized = this.serialize( expectedType, - userPart, - rolePart, + payloadPart, iatPart, expPart, jtiPart @@ -87,13 +86,10 @@ export class PassportService { if (this.now() > expNumber) return { valid: false, reason: 'Срок действия токена истёк.' } - const decodedRole = JSON.parse( - base64UrlDecode(rolePart) - ) as TokenRolePayload + const decodedPayload = JSON.parse(base64UrlDecode(payloadPart)) as T return { valid: true, - userId: base64UrlDecode(userPart), - role: decodedRole, + payload: decodedPayload, jti: base64UrlDecode(jtiPart) } } catch (error) { @@ -107,13 +103,12 @@ export class PassportService { private serialize( domain: string, - user: string, - role: string, + payload: string, iat: string, exp: string, jti: string ) { - return [domain, user, role, iat, exp, jti].join( + return [domain, payload, iat, exp, jti].join( PassportService.INTERNAL_SEPARATOR ) }