feat: add telegram verification
This commit is contained in:
parent
6cb3d0d6f3
commit
0341b2eafe
@ -21,6 +21,8 @@ model Account {
|
|||||||
|
|
||||||
role Role @default(USER)
|
role Role @default(USER)
|
||||||
|
|
||||||
|
telegramId String? @unique @map("telegram_id")
|
||||||
|
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
updatedAt DateTime @updatedAt @map("updated_at")
|
updatedAt DateTime @updatedAt @map("updated_at")
|
||||||
|
|
||||||
|
|||||||
@ -1,24 +1,34 @@
|
|||||||
import { Module } from '@nestjs/common'
|
import { Module } from '@nestjs/common'
|
||||||
import { ConfigModule } from '@nestjs/config'
|
import { ConfigModule } from '@nestjs/config'
|
||||||
|
|
||||||
import { dabataseEnv, grpcEnv, passportEnv, redisEnv } from './config'
|
import {
|
||||||
|
dabataseEnv,
|
||||||
|
grpcEnv,
|
||||||
|
passportEnv,
|
||||||
|
redisEnv,
|
||||||
|
telegramEnv
|
||||||
|
} from './config'
|
||||||
import { PrismaModule } from './infra/prisma/prisma.module'
|
import { PrismaModule } from './infra/prisma/prisma.module'
|
||||||
import { RedisModule } from './infra/redis/redis.module'
|
import { RedisModule } from './infra/redis/redis.module'
|
||||||
import { AccountModule } from './modules/account/account.module'
|
import { AccountModule } from './modules/account/account.module'
|
||||||
import { AuthModule } from './modules/auth/auth.module'
|
import { AuthModule } from './modules/auth/auth.module'
|
||||||
import { OtpModule } from './modules/otp/otp.module'
|
import { OtpModule } from './modules/otp/otp.module'
|
||||||
|
import { TelegramModule } from './modules/telegram/telegram.module'
|
||||||
|
import { TokenModule } from './modules/token/token.module'
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
load: [dabataseEnv, grpcEnv, redisEnv, passportEnv]
|
load: [dabataseEnv, grpcEnv, redisEnv, passportEnv, telegramEnv]
|
||||||
}),
|
}),
|
||||||
PrismaModule,
|
PrismaModule,
|
||||||
RedisModule,
|
RedisModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
OtpModule,
|
OtpModule,
|
||||||
AccountModule
|
AccountModule,
|
||||||
|
TelegramModule,
|
||||||
|
TokenModule
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
|||||||
1
src/config/env/index.ts
vendored
1
src/config/env/index.ts
vendored
@ -2,3 +2,4 @@ export * from './grpc.env'
|
|||||||
export * from './database.env'
|
export * from './database.env'
|
||||||
export * from './redis.env'
|
export * from './redis.env'
|
||||||
export * from './passport.env'
|
export * from './passport.env'
|
||||||
|
export * from './telegram.env'
|
||||||
|
|||||||
17
src/config/env/telegram.env.ts
vendored
Normal file
17
src/config/env/telegram.env.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { registerAs } from '@nestjs/config'
|
||||||
|
|
||||||
|
import { validateEnv } from '@/shared/utils'
|
||||||
|
|
||||||
|
import { TelegramConfig } from '../interfaces/telegram.interface'
|
||||||
|
import { TelegramValidator } from '../validators'
|
||||||
|
|
||||||
|
export const telegramEnv = registerAs<TelegramConfig>('telegram', () => {
|
||||||
|
validateEnv(process.env, TelegramValidator)
|
||||||
|
|
||||||
|
return {
|
||||||
|
telegramBotId: process.env.TELEGRAM_BOT_ID,
|
||||||
|
telegramBotToken: process.env.TELEGRAM_BOT_TOKEN,
|
||||||
|
telegramBotUsername: process.env.TELEGRAM_BOT_USERNAME,
|
||||||
|
telegramRedirectOrigin: process.env.TELEGRAM_REDIRECT_ORIGIN
|
||||||
|
}
|
||||||
|
})
|
||||||
@ -2,10 +2,12 @@ import { DatabaseConfig } from './database.interface'
|
|||||||
import { GrpcConfig } from './grpc.interface'
|
import { GrpcConfig } from './grpc.interface'
|
||||||
import { PassportConfig } from './passport.interface'
|
import { PassportConfig } from './passport.interface'
|
||||||
import { RedisConfig } from './redis.interface'
|
import { RedisConfig } from './redis.interface'
|
||||||
|
import { TelegramConfig } from './telegram.interface'
|
||||||
|
|
||||||
export interface AllConfigs {
|
export interface AllConfigs {
|
||||||
database: DatabaseConfig
|
database: DatabaseConfig
|
||||||
grpc: GrpcConfig
|
grpc: GrpcConfig
|
||||||
redis: RedisConfig
|
redis: RedisConfig
|
||||||
passport: PassportConfig
|
passport: PassportConfig
|
||||||
|
telegram: TelegramConfig
|
||||||
}
|
}
|
||||||
|
|||||||
6
src/config/interfaces/telegram.interface.ts
Normal file
6
src/config/interfaces/telegram.interface.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface TelegramConfig {
|
||||||
|
telegramBotId: string
|
||||||
|
telegramBotToken: string
|
||||||
|
telegramBotUsername: string
|
||||||
|
telegramRedirectOrigin: string
|
||||||
|
}
|
||||||
@ -2,3 +2,4 @@ export * from './grpc.validator'
|
|||||||
export * from './database.validator'
|
export * from './database.validator'
|
||||||
export * from './redis.validator'
|
export * from './redis.validator'
|
||||||
export * from './passport.validator'
|
export * from './passport.validator'
|
||||||
|
export * from './telegram.validator'
|
||||||
|
|||||||
16
src/config/validators/telegram.validator.ts
Normal file
16
src/config/validators/telegram.validator.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { IsString, IsUrl } from 'class-validator'
|
||||||
|
|
||||||
|
export class TelegramValidator {
|
||||||
|
@IsString()
|
||||||
|
public TELEGRAM_BOT_ID: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
public TELEGRAM_BOT_TOKEN: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
public TELEGRAM_BOT_USERNAME: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsUrl()
|
||||||
|
public TELEGRAM_REDIRECT_ORIGIN: string
|
||||||
|
}
|
||||||
@ -1,9 +1,7 @@
|
|||||||
import { Module } from '@nestjs/common'
|
import { Module } from '@nestjs/common'
|
||||||
import { ConfigService } from '@nestjs/config'
|
|
||||||
import { PassportModule } from '@teacinema/passport'
|
|
||||||
|
|
||||||
import { getPassportConfig } from '@/config'
|
|
||||||
import { OtpService } from '@/modules/otp/otp.service'
|
import { OtpService } from '@/modules/otp/otp.service'
|
||||||
|
import { TokenService } from '@/modules/token/token.service'
|
||||||
import { UserRepository } from '@/shared/utils/repositories'
|
import { UserRepository } from '@/shared/utils/repositories'
|
||||||
|
|
||||||
import { AuthController } from './auth.controller'
|
import { AuthController } from './auth.controller'
|
||||||
@ -11,13 +9,13 @@ import { AuthRepository } from './auth.repository'
|
|||||||
import { AuthService } from './auth.service'
|
import { AuthService } from './auth.service'
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
|
||||||
PassportModule.registerAsync({
|
|
||||||
useFactory: getPassportConfig,
|
|
||||||
inject: [ConfigService]
|
|
||||||
})
|
|
||||||
],
|
|
||||||
controllers: [AuthController],
|
controllers: [AuthController],
|
||||||
providers: [AuthService, AuthRepository, UserRepository, OtpService]
|
providers: [
|
||||||
|
AuthService,
|
||||||
|
AuthRepository,
|
||||||
|
UserRepository,
|
||||||
|
OtpService,
|
||||||
|
TokenService
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class AuthModule {}
|
export class AuthModule {}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable } from '@nestjs/common'
|
||||||
import { ConfigService } from '@nestjs/config'
|
|
||||||
import { RpcException } from '@nestjs/microservices'
|
import { RpcException } from '@nestjs/microservices'
|
||||||
import { Account } from '@prisma/generated/client'
|
import { Account } from '@prisma/generated/client'
|
||||||
import { RpcStatus } from '@teacinema/common'
|
import { RpcStatus } from '@teacinema/common'
|
||||||
@ -11,33 +10,22 @@ import {
|
|||||||
VerifyOtpRequest,
|
VerifyOtpRequest,
|
||||||
VerifyOtpResponse
|
VerifyOtpResponse
|
||||||
} from '@teacinema/contracts/gen/auth'
|
} from '@teacinema/contracts/gen/auth'
|
||||||
import { PassportService } from '@teacinema/passport'
|
|
||||||
|
|
||||||
import { AllConfigs } from '@/config'
|
|
||||||
import { OtpService } from '@/modules/otp/otp.service'
|
import { OtpService } from '@/modules/otp/otp.service'
|
||||||
import { UserRepository } from '@/shared/utils/repositories'
|
import { UserRepository } from '@/shared/utils/repositories'
|
||||||
|
|
||||||
|
import { TokenService } from '../token/token.service'
|
||||||
|
|
||||||
import { AuthRepository } from './auth.repository'
|
import { AuthRepository } from './auth.repository'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
private readonly ACCESS_TOKEN_TTL: number
|
|
||||||
private readonly REFRESH_TOKEN_TTL: number
|
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly configService: ConfigService<AllConfigs>,
|
|
||||||
private readonly authRepository: AuthRepository,
|
private readonly authRepository: AuthRepository,
|
||||||
private readonly userRepository: UserRepository,
|
private readonly userRepository: UserRepository,
|
||||||
private readonly otpService: OtpService,
|
private readonly otpService: OtpService,
|
||||||
private readonly passportService: PassportService
|
private readonly tokenService: TokenService
|
||||||
) {
|
) {}
|
||||||
this.ACCESS_TOKEN_TTL = configService.get('passport.accessTtl', {
|
|
||||||
infer: true
|
|
||||||
})
|
|
||||||
this.REFRESH_TOKEN_TTL = configService.get('passport.refreshTtl', {
|
|
||||||
infer: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
public async sendOtp(data: SendOtpRequest): Promise<SendOtpResponse> {
|
public async sendOtp(data: SendOtpRequest): Promise<SendOtpResponse> {
|
||||||
const { identifier, type } = data
|
const { identifier, type } = data
|
||||||
@ -99,39 +87,21 @@ export class AuthService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.generateTokens(account.id)
|
return this.tokenService.generateTokens(account.id)
|
||||||
}
|
|
||||||
|
|
||||||
private generateTokens(userId: Account['id']) {
|
|
||||||
const payload = {
|
|
||||||
sub: userId,
|
|
||||||
iat: Date.now(),
|
|
||||||
exp: Date.now() + this.ACCESS_TOKEN_TTL
|
|
||||||
}
|
|
||||||
const accessToken = this.passportService.generate(
|
|
||||||
payload.sub,
|
|
||||||
this.ACCESS_TOKEN_TTL
|
|
||||||
)
|
|
||||||
const refreshToken = this.passportService.generate(
|
|
||||||
payload.sub,
|
|
||||||
this.REFRESH_TOKEN_TTL
|
|
||||||
)
|
|
||||||
|
|
||||||
return { accessToken, refreshToken }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public refresh(data: RefreshRequest): RefreshResponse {
|
public refresh(data: RefreshRequest): RefreshResponse {
|
||||||
const { refreshToken } = data
|
const { refreshToken } = data
|
||||||
const result = this.passportService.verify(refreshToken)
|
const result = this.tokenService.verify(refreshToken)
|
||||||
|
|
||||||
if (!result.valid) {
|
if (!result.valid) {
|
||||||
throw new RpcException({
|
throw new RpcException({
|
||||||
code: RpcStatus.UNAUTHENTICATED,
|
code: RpcStatus.UNAUTHENTICATED,
|
||||||
// @ts-ignore
|
// @ts-expect-error -- TODO: fixme
|
||||||
details: result.reason
|
details: result.reason
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.generateTokens(result.userId)
|
return this.tokenService.generateTokens(result.userId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
src/modules/telegram/telegram.controller.ts
Normal file
24
src/modules/telegram/telegram.controller.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Controller } from '@nestjs/common'
|
||||||
|
import { GrpcMethod } from '@nestjs/microservices'
|
||||||
|
import type {
|
||||||
|
TelegramInitResponse,
|
||||||
|
TelegramVerifyRequest,
|
||||||
|
TelegramVerifyResponse
|
||||||
|
} from '@teacinema/contracts/gen/auth'
|
||||||
|
|
||||||
|
import { TelegramService } from './telegram.service'
|
||||||
|
|
||||||
|
@Controller()
|
||||||
|
export class TelegramController {
|
||||||
|
constructor(private readonly telegramService: TelegramService) {}
|
||||||
|
|
||||||
|
@GrpcMethod('AuthService', 'TelegramInit')
|
||||||
|
public getAuthUrl(): TelegramInitResponse {
|
||||||
|
return this.telegramService.getTelegramUrl()
|
||||||
|
}
|
||||||
|
|
||||||
|
@GrpcMethod('AuthService', 'TelegramVerify')
|
||||||
|
public verify(data: TelegramVerifyRequest): Promise<TelegramVerifyResponse> {
|
||||||
|
return this.telegramService.verify(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/modules/telegram/telegram.module.ts
Normal file
13
src/modules/telegram/telegram.module.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
|
||||||
|
import { TelegramRepository } from '@/modules/telegram/telegram.repository'
|
||||||
|
import { TokenService } from '@/modules/token/token.service'
|
||||||
|
|
||||||
|
import { TelegramController } from './telegram.controller'
|
||||||
|
import { TelegramService } from './telegram.service'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
controllers: [TelegramController],
|
||||||
|
providers: [TelegramService, TelegramRepository, TokenService]
|
||||||
|
})
|
||||||
|
export class TelegramModule {}
|
||||||
15
src/modules/telegram/telegram.repository.ts
Normal file
15
src/modules/telegram/telegram.repository.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { Account } from '@prisma/generated/client'
|
||||||
|
|
||||||
|
import { PrismaService } from '@/infra/prisma/prisma.service'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TelegramRepository {
|
||||||
|
constructor(private readonly prismaService: PrismaService) {}
|
||||||
|
|
||||||
|
public findByTelegramId(id: Account['telegramId']) {
|
||||||
|
return this.prismaService.account.findUnique({
|
||||||
|
where: { telegramId: id }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
105
src/modules/telegram/telegram.service.ts
Normal file
105
src/modules/telegram/telegram.service.ts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { ConfigService } from '@nestjs/config'
|
||||||
|
import { RpcException } from '@nestjs/microservices'
|
||||||
|
import { RpcStatus } from '@teacinema/common'
|
||||||
|
import {
|
||||||
|
TelegramInitResponse,
|
||||||
|
TelegramVerifyRequest
|
||||||
|
} from '@teacinema/contracts/gen/auth'
|
||||||
|
import { createHash, createHmac, randomBytes } from 'node:crypto'
|
||||||
|
|
||||||
|
import { AllConfigs } from '@/config'
|
||||||
|
import { RedisService } from '@/infra/redis/redis.service'
|
||||||
|
import { TokenService } from '@/modules/token/token.service'
|
||||||
|
|
||||||
|
import { TelegramRepository } from './telegram.repository'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TelegramService {
|
||||||
|
private readonly BOT_ID: string
|
||||||
|
private readonly BOT_TOKEN: string
|
||||||
|
private readonly BOT_USERNAME: string
|
||||||
|
private readonly REDIRECT_ORIGIN: string
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private readonly redisService: RedisService,
|
||||||
|
private readonly configService: ConfigService<AllConfigs>,
|
||||||
|
private readonly telegramRepository: TelegramRepository,
|
||||||
|
private readonly tokenService: TokenService
|
||||||
|
) {
|
||||||
|
this.BOT_ID = configService.get('telegram.telegramBotId', { infer: true })
|
||||||
|
this.BOT_TOKEN = configService.get('telegram.telegramBotToken', {
|
||||||
|
infer: true
|
||||||
|
})
|
||||||
|
this.BOT_USERNAME = configService.get('telegram.telegramBotUsername', {
|
||||||
|
infer: true
|
||||||
|
})
|
||||||
|
this.REDIRECT_ORIGIN = configService.get(
|
||||||
|
'telegram.telegramRedirectOrigin',
|
||||||
|
{ infer: true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTelegramUrl(): TelegramInitResponse {
|
||||||
|
const url = new URL('https://oauth.telegram.org/auth')
|
||||||
|
url.searchParams.append('bot_id', this.BOT_ID)
|
||||||
|
url.searchParams.append('origin', this.REDIRECT_ORIGIN)
|
||||||
|
url.searchParams.append('request_access', 'write')
|
||||||
|
url.searchParams.append('return_to', `${this.REDIRECT_ORIGIN}`)
|
||||||
|
|
||||||
|
return { url: url.href }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async verify(data: TelegramVerifyRequest) {
|
||||||
|
const isValid = this.checkTelegramAuth(data.query)
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
throw new RpcException({
|
||||||
|
code: RpcStatus.UNAUTHENTICATED,
|
||||||
|
message: 'Invalid telegram login response'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const telegramId = data.query.id
|
||||||
|
const exists = await this.telegramRepository.findByTelegramId(telegramId)
|
||||||
|
|
||||||
|
if (exists && exists.phone) {
|
||||||
|
return this.tokenService.generateTokens(exists.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const sessionId = randomBytes(16).toString('hex')
|
||||||
|
|
||||||
|
await this.redisService.set(
|
||||||
|
`telegram_session:${sessionId}`,
|
||||||
|
JSON.stringify({ telegramId, username: data.query.username }),
|
||||||
|
'EX',
|
||||||
|
300
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: `https://t.me/${this.BOT_USERNAME}?start=${sessionId}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkTelegramAuth(query: Record<string, string>) {
|
||||||
|
const hash = query.hash
|
||||||
|
|
||||||
|
if (!hash) return false
|
||||||
|
|
||||||
|
const dataCheckArr = Object.keys(query)
|
||||||
|
.filter(k => k !== 'hash')
|
||||||
|
.sort()
|
||||||
|
.map(k => `${k}=${query[k]}`)
|
||||||
|
|
||||||
|
const dataCheckString = dataCheckArr.join('\n')
|
||||||
|
const secretKey = createHash('sha256')
|
||||||
|
.update(`${this.BOT_ID}:${this.BOT_TOKEN}`)
|
||||||
|
.digest('hex')
|
||||||
|
|
||||||
|
const hmac = createHmac('sha256', secretKey)
|
||||||
|
.update(dataCheckString)
|
||||||
|
.digest('hex')
|
||||||
|
|
||||||
|
return hmac === hash
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/modules/token/token.module.ts
Normal file
19
src/modules/token/token.module.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
import { ConfigService } from '@nestjs/config'
|
||||||
|
import { PassportModule } from '@teacinema/passport'
|
||||||
|
|
||||||
|
import { getPassportConfig } from '@/config'
|
||||||
|
|
||||||
|
import { TokenService } from './token.service'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
PassportModule.registerAsync({
|
||||||
|
useFactory: getPassportConfig,
|
||||||
|
inject: [ConfigService]
|
||||||
|
})
|
||||||
|
],
|
||||||
|
providers: [TokenService],
|
||||||
|
exports: [TokenService]
|
||||||
|
})
|
||||||
|
export class TokenModule {}
|
||||||
46
src/modules/token/token.service.ts
Normal file
46
src/modules/token/token.service.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { ConfigService } from '@nestjs/config'
|
||||||
|
import { Account } from '@prisma/generated/client'
|
||||||
|
import { PassportService } from '@teacinema/passport'
|
||||||
|
|
||||||
|
import { AllConfigs } from '@/config'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TokenService {
|
||||||
|
private readonly ACCESS_TOKEN_TTL: number
|
||||||
|
private readonly REFRESH_TOKEN_TTL: number
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly configService: ConfigService<AllConfigs>,
|
||||||
|
private readonly passportService: PassportService
|
||||||
|
) {
|
||||||
|
this.ACCESS_TOKEN_TTL = configService.get('passport.accessTtl', {
|
||||||
|
infer: true
|
||||||
|
})
|
||||||
|
this.REFRESH_TOKEN_TTL = configService.get('passport.refreshTtl', {
|
||||||
|
infer: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public generateTokens(userId: Account['id']) {
|
||||||
|
const payload = {
|
||||||
|
sub: userId,
|
||||||
|
iat: Date.now(),
|
||||||
|
exp: Date.now() + this.ACCESS_TOKEN_TTL
|
||||||
|
}
|
||||||
|
const accessToken = this.passportService.generate(
|
||||||
|
payload.sub,
|
||||||
|
this.ACCESS_TOKEN_TTL
|
||||||
|
)
|
||||||
|
const refreshToken = this.passportService.generate(
|
||||||
|
payload.sub,
|
||||||
|
this.REFRESH_TOKEN_TTL
|
||||||
|
)
|
||||||
|
|
||||||
|
return { accessToken, refreshToken }
|
||||||
|
}
|
||||||
|
|
||||||
|
public verify(token: string) {
|
||||||
|
return this.passportService.verify(token)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1383,9 +1383,9 @@
|
|||||||
integrity sha512-q3DURJbSk3k8MNWFIYaSM4LEcBgPbWa+HJmBz/nzYT4kuYitJVSXxpZ97kr0Ea+81AZwAU3JhQKlkK0SBWUi0A==
|
integrity sha512-q3DURJbSk3k8MNWFIYaSM4LEcBgPbWa+HJmBz/nzYT4kuYitJVSXxpZ97kr0Ea+81AZwAU3JhQKlkK0SBWUi0A==
|
||||||
|
|
||||||
"@teacinema/contracts@^1.0.0":
|
"@teacinema/contracts@^1.0.0":
|
||||||
version "1.0.7"
|
version "1.0.8"
|
||||||
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcontracts/-/1.0.7/contracts-1.0.7.tgz#2c75a3118e4126d30f5c8193c4518bac3f1812ff"
|
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcontracts/-/1.0.8/contracts-1.0.8.tgz#4e31c3a370b0808629d9c93900c5f27958ef82e6"
|
||||||
integrity sha512-lE14PO/yBphYCu0BGFGyGAyvJ74v+ACz34MXA3fFo/PwThPVpudBReSG6oRyUACRybkN882GKXFU6LrJXvGbrQ==
|
integrity sha512-xyPyifbVwWelgo4MsvhhRl//To+b0Tnp8DtANCzwLBUhwPj3ZG19QgfPB7Ih7PsBU5TD6F80aNlITDxJbFgkFQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nestjs/microservices" "^11.1.12"
|
"@nestjs/microservices" "^11.1.12"
|
||||||
protoc "33.4.0"
|
protoc "33.4.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user