2025-03-05 07:05:19 +03:00

119 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
BadRequestException,
Injectable,
UnauthorizedException
} from '@nestjs/common'
import { TypeBaseProviderOptions } from './types/base-provider-options.types'
import { TypeUserInfo } from './types/user-info.types'
@Injectable()
export class BaseOAuthService {
private BASE_URL: string
public constructor(private readonly options: TypeBaseProviderOptions) {}
protected async extractUserInfo(data: any): Promise<TypeUserInfo> {
return {
...data,
provider: this.options.name
}
}
public getAuthUrl() {
const query = new URLSearchParams({
response_type: 'code',
client_id: this.options.client_id,
redirect_uri: this.getRedirectUrl(),
scope: (this.options.scopes ?? []).join(' '),
access_type: 'offline',
prompt: 'select_account'
})
return `${this.options.authorize_url}?${query}`
}
public async findUserByCode(code: string): Promise<TypeUserInfo> {
const client_id = this.options.client_id
const client_secret = this.options.client_secret
const tokenQuery = new URLSearchParams({
client_id,
client_secret,
code,
redirect_uri: this.getRedirectUrl(),
grant_type: 'authorization_code'
})
const tokensRequest = await fetch(this.options.access_url, {
method: 'POST',
body: tokenQuery,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Accept: 'application/json'
}
})
if (!tokensRequest.ok) {
throw new BadRequestException(
`Не удалось получить пользователя с ${this.options.profile_url}. Проверьте правильность токена доступа.`
)
}
const tokens = await tokensRequest.json()
if (!tokens.access_token) {
throw new BadRequestException(
`Нет токенов с ${this.options.access_url}. Убедитесь, что код авторизации действителен.`
)
}
const userRequest = await fetch(this.options.profile_url, {
headers: {
Authorization: `Bearer ${tokens.access_token}`
}
})
if (!userRequest.ok) {
throw new UnauthorizedException(
`Не удалось получить пользователя с ${this.options.profile_url}. Проверьте правильность токена доступа.`
)
}
const user = await userRequest.json()
const userData = await this.extractUserInfo(user)
return {
...userData,
access_token: tokens.access_token,
refresh_token: tokens.refresh_token,
expires_at: tokens.expires_at || tokens.expires_in,
provider: this.options.name
}
}
public getRedirectUrl() {
return `${this.BASE_URL}/auth/oauth/callback/${this.options.name}`
}
set baseUrl(value: string) {
this.BASE_URL = value
}
get name() {
return this.options.name
}
get access_url() {
return this.options.access_url
}
get profile_url() {
return this.options.profile_url
}
get scopes() {
return this.options.scopes
}
}