diff --git a/backend/server/src/auth/auth.service.spec.ts b/backend/server/src/auth/auth.service.spec.ts index f9238483..6539947d 100644 --- a/backend/server/src/auth/auth.service.spec.ts +++ b/backend/server/src/auth/auth.service.spec.ts @@ -4,7 +4,7 @@ import { JwtService } from '@nestjs/jwt'; import { Test, TestingModule } from '@nestjs/testing'; import { AuthService } from './auth.service'; -import { OauthService } from './oauth/oauth.service.interface'; +import { OauthService } from './oauth/oauth.service.base'; import { AccessTokenPayload, RefreshTokenPayload, TokenService } from './token/token.service'; import { OauthAuthorizeData } from './types/oauth-authorize-data.type'; import { OauthData } from './types/oauth-data.type'; @@ -25,16 +25,9 @@ describe('AuthService', () => { beforeEach(async () => { mockOauthServices = new Map(); - const mockTokenResponse = { - access_token: mockUser.oauthAccessToken, - expires_in: 3600, - refresh_token: mockUser.oauthRefreshToken, - refresh_token_expires_in: 3600, - scope: 'scope', - token_type: 'bearer', - }; - - const mockUserInfo = { + const mockOauthLoginData = { + oauthAccessToken: mockUser.oauthAccessToken, + oauthRefreshToken: mockUser.oauthRefreshToken, oauthId: mockUser.oauthId, oauthNickname: 'test', email: 'test@mail.com', @@ -43,13 +36,21 @@ describe('AuthService', () => { OAUTH_PROVIDERS.forEach((provider) => { const mockOauthService = { - requestToken: jest.fn().mockResolvedValue(mockTokenResponse), - requestUserInfo: jest.fn().mockResolvedValue(mockUserInfo), - requestTokenExpiration: jest.fn().mockResolvedValue(undefined), - requestTokenRefresh: jest.fn().mockResolvedValue(mockTokenResponse), - requestUnlink: provider === 'kakao' ? jest.fn().mockResolvedValue(undefined) : undefined, + login: jest.fn().mockResolvedValue(mockOauthLoginData), + signup: jest.fn().mockResolvedValue({ + oauthId: mockUser.oauthId, + oauthNickname: 'test', + email: 'test@mail.com', + profileImageUrl: 'test.jpg', + }), + logout: jest.fn().mockResolvedValue(undefined), + reissueTokens: jest.fn().mockResolvedValue({ + oauthAccessToken: 'new_' + mockUser.oauthAccessToken, + oauthRefreshToken: 'new_' + mockUser.oauthRefreshToken, + }), + deactivate: provider === 'kakao' ? jest.fn().mockResolvedValue(undefined) : undefined, }; - mockOauthServices.set(provider, mockOauthService as OauthService); + mockOauthServices.set(provider, mockOauthService as unknown as OauthService); }); const module: TestingModule = await Test.createTestingModule({ diff --git a/backend/server/src/auth/auth.service.ts b/backend/server/src/auth/auth.service.ts index 397252c8..b5c17431 100644 --- a/backend/server/src/auth/auth.service.ts +++ b/backend/server/src/auth/auth.service.ts @@ -2,8 +2,7 @@ import { Inject, Injectable, NotFoundException, UnauthorizedException } from '@n import { ConfigService } from '@nestjs/config'; import { Transactional } from 'typeorm-transactional'; -import { KakaoService } from './oauth/kakao.service'; -import { OauthService } from './oauth/oauth.service.interface'; +import { OauthService } from './oauth/oauth.service.base'; import { AccessTokenPayload, RefreshTokenPayload, TokenService } from './token/token.service'; import { AuthData } from './types/auth-data.type'; import { OauthAuthorizeData } from './types/oauth-authorize-data.type'; @@ -38,13 +37,11 @@ export class AuthService { async login({ authorizeCode, provider }: OauthAuthorizeData): Promise { const oauthService = this.getOauthService(provider); - const { access_token: oauthAccessToken, refresh_token: oauthRefreshToken } = await oauthService.requestToken( + const { oauthAccessToken, oauthRefreshToken, oauthId } = await oauthService.login( authorizeCode, this.REDIRECT_URI, ); - const { oauthId } = await oauthService.requestUserInfo(oauthAccessToken); - const refreshToken = await this.tokenService.signRefreshToken(oauthId, provider); this.logger.debug('login - signRefreshToken', { refreshToken }); @@ -70,7 +67,7 @@ export class AuthService { async signup({ oauthAccessToken, oauthRefreshToken, provider }: OauthData): Promise { const oauthService = this.getOauthService(provider); - const { oauthId, oauthNickname, email } = await oauthService.requestUserInfo(oauthAccessToken); + const { oauthId, oauthNickname, email } = await oauthService.signup(oauthAccessToken); const profileImageUrl = this.S3_PROFILE_IMAGE_PATH; const refreshToken = await this.tokenService.signRefreshToken(oauthId, provider); @@ -98,9 +95,7 @@ export class AuthService { const { oauthAccessToken } = await this.usersService.findOne({ where: { id: userId } }); this.logger.debug('logout - oauthAccessToken', { oauthAccessToken }); - if (provider === 'kakao') { - await (oauthService as KakaoService).requestTokenExpiration(oauthAccessToken); - } + await oauthService.logout(oauthAccessToken); } async reissueTokens({ oauthId, provider }: RefreshTokenPayload): Promise { @@ -112,11 +107,11 @@ export class AuthService { }); const [ - { access_token: newOauthAccessToken, refresh_token: newOauthRefreshToken }, + { oauthAccessToken: newOauthAccessToken, oauthRefreshToken: newOauthRefreshToken }, newAccessToken, newRefreshToken, ] = await Promise.all([ - oauthService.requestTokenRefresh(oauthRefreshToken), + oauthService.reissueTokens(oauthRefreshToken), this.tokenService.signAccessToken(userId, provider), this.tokenService.signRefreshToken(oauthId, provider), ]); @@ -137,11 +132,7 @@ export class AuthService { const { oauthAccessToken } = await this.usersService.findOne({ where: { id: userId } }); - if (provider === 'kakao') { - await (oauthService as KakaoService).requestUnlink(oauthAccessToken); - } else { - await oauthService.requestTokenExpiration(oauthAccessToken); - } + await oauthService.deactivate(oauthAccessToken); await this.deleteUserData(userId); } diff --git a/backend/server/src/auth/oauth/__mocks__/oauth.service.ts b/backend/server/src/auth/oauth/__mocks__/oauth.service.ts index 5dca161c..e11ea001 100644 --- a/backend/server/src/auth/oauth/__mocks__/oauth.service.ts +++ b/backend/server/src/auth/oauth/__mocks__/oauth.service.ts @@ -1,24 +1,28 @@ -import { RequestToken, RequestTokenRefresh, RequestUserInfo } from '../oauth.service.interface'; +import { OauthLoginData, OauthReissueData, OauthSignupData } from '../oauth.service.base'; export const MockOauthService = { - requestToken: jest.fn().mockResolvedValue({ - access_token: 'mock_oauth_access_token', - refresh_token: 'mock_oauth_refresh_token', - } as RequestToken), + login: jest.fn().mockResolvedValue({ + oauthAccessToken: 'mock_oauth_access_token', + oauthRefreshToken: 'mock_oauth_refresh_token', + oauthId: '12345', + oauthNickname: 'mock_oauth_nickname', + email: 'mock_email@example.com', + profileImageUrl: 'mock_profile_image.jpg', + } as OauthLoginData), - requestUserInfo: jest.fn().mockResolvedValue({ + signup: jest.fn().mockResolvedValue({ oauthId: '12345', oauthNickname: 'mock_oauth_nickname', email: 'mock_email@example.com', profileImageUrl: 'mock_profile_image.jpg', - } as RequestUserInfo), + } as OauthSignupData), - requestTokenExpiration: jest.fn(), + logout: jest.fn(), - requestUnlink: jest.fn(), + reissueTokens: jest.fn().mockResolvedValue({ + oauthAccessToken: 'new_mock_oauth_access_token', + oauthRefreshToken: 'new_mock_oauth_refresh_token', + } as OauthReissueData), - requestTokenRefresh: jest.fn().mockResolvedValue({ - access_token: 'new_mock_oauth_access_token', - refresh_token: 'new_mock_oauth_refresh_token', - } as RequestTokenRefresh), + deactivate: jest.fn(), }; diff --git a/backend/server/src/auth/oauth/google.service.ts b/backend/server/src/auth/oauth/google.service.ts index e0bcf001..f89934cd 100644 --- a/backend/server/src/auth/oauth/google.service.ts +++ b/backend/server/src/auth/oauth/google.service.ts @@ -4,11 +4,18 @@ import { ConfigService } from '@nestjs/config'; import axios from 'axios'; import { firstValueFrom } from 'rxjs'; -import { OauthService, RequestToken, RequestTokenRefresh, RequestUserInfo } from './oauth.service.interface'; +import { + OauthLoginData, + OauthReissueData, + OauthService, + OauthSignupData, + RequestTokenRefreshResponse, + RequestTokenResponse, +} from './oauth.service.base'; import { WinstonLoggerService } from '../../common/logger/winstonLogger.service'; -interface TokenResponse { +interface TokenResponse extends RequestTokenResponse { access_token: string; expires_in: number; refresh_token: string; @@ -23,7 +30,7 @@ interface UserInfoResponse { picture: string; } -interface TokenRefreshResponse { +interface TokenRefreshResponse extends RequestTokenRefreshResponse { access_token: string; expires_in: number; scope: string; @@ -31,12 +38,14 @@ interface TokenRefreshResponse { } @Injectable() -export class GoogleService implements OauthService { +export class GoogleService extends OauthService { constructor( - private readonly configService: ConfigService, - private readonly httpService: HttpService, - private readonly logger: WinstonLoggerService, - ) {} + readonly configService: ConfigService, + readonly httpService: HttpService, + readonly logger: WinstonLoggerService, + ) { + super(configService, httpService, logger); + } private readonly CLIENT_ID = this.configService.get('GOOGLE_CLIENT_ID'); private readonly CLIENT_SECRET = this.configService.get('GOOGLE_CLIENT_SECRET'); @@ -44,7 +53,44 @@ export class GoogleService implements OauthService { private readonly USER_INFO_API = this.configService.get('GOOGLE_USER_INFO_API')!; private readonly REVOKE_API = this.configService.get('GOOGLE_REVOKE_API')!; - async requestToken(authorizeCode: string, redirectURI: string): Promise { + async login(authorizeCode: string, redirectURI: string): Promise { + const tokens = await this.requestToken(authorizeCode, redirectURI); + const userInfo = await this.requestUserInfo(tokens.access_token); + + return { + oauthAccessToken: tokens.access_token, + oauthRefreshToken: tokens.refresh_token, + oauthId: userInfo.id, + oauthNickname: userInfo.name, + email: userInfo.email, + profileImageUrl: userInfo.picture, + }; + } + + async signup(oauthAccessToken: string): Promise { + const userInfo = await this.requestUserInfo(oauthAccessToken); + + return { + oauthId: userInfo.id, + oauthNickname: userInfo.name, + email: userInfo.email, + profileImageUrl: userInfo.picture, + }; + } + + async logout(_oauthAccessToken: string): Promise {} + + async reissueTokens(oauthRefreshToken: string): Promise { + const tokens = await this.requestTokenRefresh(oauthRefreshToken); + + return { oauthAccessToken: tokens.access_token, oauthRefreshToken: tokens.refresh_token }; + } + + async deactivate(oauthAccessToken: string): Promise { + await this.requestTokenExpiration(oauthAccessToken); + } + + private async requestToken(authorizeCode: string, redirectURI: string): Promise { try { const { data } = await firstValueFrom( this.httpService.post(this.TOKEN_API, { @@ -69,7 +115,7 @@ export class GoogleService implements OauthService { } } - async requestUserInfo(accessToken: string): Promise { + private async requestUserInfo(accessToken: string): Promise { try { const { data } = await firstValueFrom( this.httpService.get(this.USER_INFO_API, { @@ -81,12 +127,7 @@ export class GoogleService implements OauthService { this.logger.log('requestUserInfo', { ...data }); - return { - oauthId: data.id, - oauthNickname: data.name, - email: data.email, - profileImageUrl: data.picture, - }; + return data; } catch (error) { if (axios.isAxiosError(error) && error.response) { this.logger.error('Google: 유저 정보 조회 요청이 실패했습니다', { @@ -99,7 +140,7 @@ export class GoogleService implements OauthService { } } - async requestTokenExpiration(accessToken: string) { + private async requestTokenExpiration(accessToken: string): Promise { try { await firstValueFrom( this.httpService.post( @@ -127,7 +168,7 @@ export class GoogleService implements OauthService { } } - async requestTokenRefresh(refreshToken: string): Promise { + private async requestTokenRefresh(refreshToken: string): Promise { try { const { data } = await firstValueFrom( this.httpService.post(this.TOKEN_API, { diff --git a/backend/server/src/auth/oauth/kakao.service.ts b/backend/server/src/auth/oauth/kakao.service.ts index 8c8ec1d4..19781423 100644 --- a/backend/server/src/auth/oauth/kakao.service.ts +++ b/backend/server/src/auth/oauth/kakao.service.ts @@ -4,11 +4,18 @@ import { ConfigService } from '@nestjs/config'; import axios from 'axios'; import { firstValueFrom } from 'rxjs'; -import { OauthService, RequestToken, RequestTokenRefresh, RequestUserInfo } from './oauth.service.interface'; +import { + OauthLoginData, + OauthReissueData, + OauthService, + OauthSignupData, + RequestTokenRefreshResponse, + RequestTokenResponse, +} from './oauth.service.base'; import { WinstonLoggerService } from '../../common/logger/winstonLogger.service'; -interface TokenResponse { +interface TokenResponse extends RequestTokenResponse { token_type: string; access_token: string; id_token?: string; @@ -29,7 +36,7 @@ interface UserInfoResponse { }; } -interface TokenRefreshResponse { +interface TokenRefreshResponse extends RequestTokenRefreshResponse { token_type: string; access_token: string; expires_in: number; @@ -38,12 +45,14 @@ interface TokenRefreshResponse { } @Injectable() -export class KakaoService implements OauthService { +export class KakaoService extends OauthService { constructor( - private readonly configService: ConfigService, - private readonly httpService: HttpService, - private readonly logger: WinstonLoggerService, - ) {} + readonly configService: ConfigService, + readonly httpService: HttpService, + readonly logger: WinstonLoggerService, + ) { + super(configService, httpService, logger); + } private readonly CLIENT_ID = this.configService.get('KAKAO_CLIENT_ID'); private readonly CLIENT_SECRET = this.configService.get('KAKAO_CLIENT_SECRET'); @@ -52,7 +61,46 @@ export class KakaoService implements OauthService { private readonly LOGOUT_API = this.configService.get('KAKAO_LOGOUT_API')!; private readonly UNLINK_API = this.configService.get('KAKAO_UNLINK_API')!; - async requestToken(authorizeCode: string, redirectURI: string): Promise { + async login(authorizeCode: string, redirectURI: string): Promise { + const tokens = await this.requestToken(authorizeCode, redirectURI); + const userInfo = await this.requestUserInfo(tokens.access_token); + + return { + oauthAccessToken: tokens.access_token, + oauthRefreshToken: tokens.refresh_token, + oauthId: userInfo.id.toString(), + oauthNickname: userInfo.properties.nickname, + email: userInfo.kakao_account.email, + profileImageUrl: userInfo.properties.profile_image, + }; + } + + async signup(oauthAccessToken: string): Promise { + const userInfo = await this.requestUserInfo(oauthAccessToken); + + return { + oauthId: userInfo.id.toString(), + oauthNickname: userInfo.properties.nickname, + email: userInfo.kakao_account.email, + profileImageUrl: userInfo.properties.profile_image, + }; + } + + async logout(oauthAccessToken: string): Promise { + await this.requestTokenExpiration(oauthAccessToken); + } + + async reissueTokens(oauthRefreshToken: string): Promise { + const tokens = await this.requestTokenRefresh(oauthRefreshToken); + + return { oauthAccessToken: tokens.access_token, oauthRefreshToken: tokens.refresh_token }; + } + + async deactivate(oauthAccessToken: string): Promise { + await this.requestUnlink(oauthAccessToken); + } + + private async requestToken(authorizeCode: string, redirectURI: string): Promise { try { const { data } = await firstValueFrom( this.httpService.post( @@ -85,7 +133,7 @@ export class KakaoService implements OauthService { } } - async requestUserInfo(accessToken: string): Promise { + private async requestUserInfo(accessToken: string): Promise { try { const { data } = await firstValueFrom( this.httpService.get(this.USER_INFO_API, { @@ -97,12 +145,7 @@ export class KakaoService implements OauthService { this.logger.log('requestUserInfo', { ...data }); - return { - oauthId: data.id.toString(), - oauthNickname: data.properties.nickname, - email: data.kakao_account.email, - profileImageUrl: data.properties.profile_image, - }; + return data; } catch (error) { if (axios.isAxiosError(error) && error.response) { this.logger.error('Kakao: 유저 정보 조회 요청이 실패했습니다', { @@ -115,7 +158,7 @@ export class KakaoService implements OauthService { } } - async requestTokenExpiration(accessToken: string) { + private async requestTokenExpiration(accessToken: string): Promise { try { await firstValueFrom( this.httpService.post<{ id: number }>( @@ -141,7 +184,7 @@ export class KakaoService implements OauthService { } } - async requestUnlink(accessToken: string) { + private async requestUnlink(accessToken: string): Promise { try { await firstValueFrom( this.httpService.post<{ id: number }>( @@ -167,7 +210,7 @@ export class KakaoService implements OauthService { } } - async requestTokenRefresh(refreshToken: string): Promise { + private async requestTokenRefresh(refreshToken: string): Promise { try { const { data } = await firstValueFrom( this.httpService.post( diff --git a/backend/server/src/auth/oauth/naver.service.ts b/backend/server/src/auth/oauth/naver.service.ts index c5ed9d39..7d48b446 100644 --- a/backend/server/src/auth/oauth/naver.service.ts +++ b/backend/server/src/auth/oauth/naver.service.ts @@ -4,11 +4,18 @@ import { ConfigService } from '@nestjs/config'; import axios from 'axios'; import { firstValueFrom } from 'rxjs'; -import { OauthService, RequestToken, RequestTokenRefresh, RequestUserInfo } from './oauth.service.interface'; +import { + OauthLoginData, + OauthReissueData, + OauthService, + OauthSignupData, + RequestTokenRefreshResponse, + RequestTokenResponse, +} from './oauth.service.base'; import { WinstonLoggerService } from '../../common/logger/winstonLogger.service'; -interface TokenResponse { +interface TokenResponse extends RequestTokenResponse { access_token: string; refresh_token: string; token_type: string; @@ -26,26 +33,65 @@ interface UserInfoResponse { }; } -interface TokenRefreshResponse { +interface TokenRefreshResponse extends RequestTokenRefreshResponse { access_token: string; token_type: string; expires_in: number; } @Injectable() -export class NaverService implements OauthService { +export class NaverService extends OauthService { constructor( - private readonly configService: ConfigService, - private readonly httpService: HttpService, - private readonly logger: WinstonLoggerService, - ) {} + readonly configService: ConfigService, + readonly httpService: HttpService, + readonly logger: WinstonLoggerService, + ) { + super(configService, httpService, logger); + } private readonly CLIENT_ID = this.configService.get('NAVER_CLIENT_ID'); private readonly CLIENT_SECRET = this.configService.get('NAVER_CLIENT_SECRET'); private readonly TOKEN_API = this.configService.get('NAVER_TOKEN_API')!; private readonly USER_INFO_API = this.configService.get('NAVER_USER_INFO_API')!; - async requestToken(authorizeCode: string): Promise { + async login(authorizeCode: string, _redirectURI: string): Promise { + const tokens = await this.requestToken(authorizeCode); + const userInfo = await this.requestUserInfo(tokens.access_token); + + return { + oauthAccessToken: tokens.access_token, + oauthRefreshToken: tokens.refresh_token, + oauthId: userInfo.response.id, + oauthNickname: userInfo.response.nickname, + email: userInfo.response.email, + profileImageUrl: userInfo.response.profile_image, + }; + } + + async signup(oauthAccessToken: string): Promise { + const userInfo = await this.requestUserInfo(oauthAccessToken); + + return { + oauthId: userInfo.response.id, + oauthNickname: userInfo.response.nickname, + email: userInfo.response.email, + profileImageUrl: userInfo.response.profile_image, + }; + } + + async logout(_oauthAccessToken: string): Promise {} + + async reissueTokens(oauthRefreshToken: string): Promise { + const tokens = await this.requestTokenRefresh(oauthRefreshToken); + + return { oauthAccessToken: tokens.access_token, oauthRefreshToken: tokens.refresh_token }; + } + + async deactivate(oauthAccessToken: string): Promise { + await this.requestTokenExpiration(oauthAccessToken); + } + + private async requestToken(authorizeCode: string): Promise { try { const { data } = await firstValueFrom( this.httpService.get(this.TOKEN_API, { @@ -72,7 +118,7 @@ export class NaverService implements OauthService { } } - async requestUserInfo(accessToken: string): Promise { + private async requestUserInfo(accessToken: string): Promise { try { const { data } = await firstValueFrom( this.httpService.get(this.USER_INFO_API, { @@ -84,12 +130,7 @@ export class NaverService implements OauthService { this.logger.log('requestUserInfo', { ...data }); - return { - oauthId: data.response.id, - oauthNickname: data.response.nickname, - email: data.response.email, - profileImageUrl: data.response.profile_image, - }; + return data; } catch (error) { if (axios.isAxiosError(error) && error.response) { this.logger.error('Naver: 유저 정보 조회 요청이 실패했습니다', { @@ -102,7 +143,7 @@ export class NaverService implements OauthService { } } - async requestTokenExpiration(accessToken: string) { + private async requestTokenExpiration(accessToken: string): Promise { try { await firstValueFrom( this.httpService.get<{ access_token: string; result: string }>(this.TOKEN_API, { @@ -127,7 +168,7 @@ export class NaverService implements OauthService { } } - async requestTokenRefresh(refreshToken: string): Promise { + private async requestTokenRefresh(refreshToken: string): Promise { try { const { data } = await firstValueFrom( this.httpService.get(this.TOKEN_API, { diff --git a/backend/server/src/auth/oauth/oauth.module.ts b/backend/server/src/auth/oauth/oauth.module.ts index bc6d06e4..eab8c094 100644 --- a/backend/server/src/auth/oauth/oauth.module.ts +++ b/backend/server/src/auth/oauth/oauth.module.ts @@ -6,7 +6,7 @@ import { ConfigService } from '@nestjs/config'; import { GoogleService } from './google.service'; import { KakaoService } from './kakao.service'; import { NaverService } from './naver.service'; -import { OauthService } from './oauth.service.interface'; +import { OauthService } from './oauth.service.base'; import { WinstonLoggerService } from '../../common/logger/winstonLogger.service'; diff --git a/backend/server/src/auth/oauth/oauth.service.base.ts b/backend/server/src/auth/oauth/oauth.service.base.ts new file mode 100644 index 00000000..237cff46 --- /dev/null +++ b/backend/server/src/auth/oauth/oauth.service.base.ts @@ -0,0 +1,47 @@ +import { HttpService } from '@nestjs/axios'; +import { ConfigService } from '@nestjs/config'; + +import { WinstonLoggerService } from '../../common/logger/winstonLogger.service'; + +export interface RequestTokenResponse { + access_token: string; + refresh_token: string; + [key: string]: any; +} + +export interface RequestTokenRefreshResponse extends Omit { + refresh_token?: string; +} + +interface UserInfo { + oauthId: string; + oauthNickname: string; + email: string; + profileImageUrl: string; +} + +export interface OauthLoginData extends UserInfo { + oauthAccessToken: string; + oauthRefreshToken: string; +} + +export interface OauthSignupData extends UserInfo {} + +export interface OauthReissueData { + oauthAccessToken: string; + oauthRefreshToken?: string; +} + +export abstract class OauthService { + constructor( + protected readonly configService: ConfigService, + protected readonly httpService: HttpService, + protected readonly logger: WinstonLoggerService, + ) {} + + abstract login(authorizeCode: string, redirectURI: string): Promise; + abstract signup(oauthAccessToken: string): Promise; + abstract logout(oauthAccessToken: string): Promise; + abstract reissueTokens(oauthRefreshToken: string): Promise; + abstract deactivate(oauthAccessToken: string): Promise; +} diff --git a/backend/server/src/auth/oauth/oauth.service.interface.ts b/backend/server/src/auth/oauth/oauth.service.interface.ts deleted file mode 100644 index 3b341427..00000000 --- a/backend/server/src/auth/oauth/oauth.service.interface.ts +++ /dev/null @@ -1,28 +0,0 @@ -export interface RequestToken { - access_token: string; - refresh_token: string; - [key: string]: any; -} - -export interface RequestTokenRefresh extends Omit { - refresh_token?: string; -} - -export interface RequestUserInfo { - oauthId: string; - oauthNickname: string; - email: string; - profileImageUrl: string; -} - -export interface OauthService { - requestToken(authorizeCode: string, redirectURI?: string): Promise; - - requestUserInfo(accessToken: string): Promise; - - requestTokenExpiration(accessToken: string): Promise; - - requestUnlink?(accessToken: string): Promise; - - requestTokenRefresh(refreshToken: string): Promise; -} diff --git a/backend/server/test/performance/__mocks__/oauth.service.ts b/backend/server/test/performance/__mocks__/oauth.service.ts index b5d8eac4..33290f58 100644 --- a/backend/server/test/performance/__mocks__/oauth.service.ts +++ b/backend/server/test/performance/__mocks__/oauth.service.ts @@ -1,27 +1,28 @@ -import { RequestToken, RequestTokenRefresh, RequestUserInfo } from '../../../src/auth/oauth/oauth.service.interface'; +import { OauthLoginData, OauthReissueData, OauthSignupData } from '../../../src/auth/oauth/oauth.service.base'; export const MockOauthService = { - requestToken: () => - ({ - access_token: 'mock_oauth_access_token', - refresh_token: 'mock_oauth_refresh_token', - }) as RequestToken, + login: jest.fn().mockResolvedValue({ + oauthAccessToken: 'mock_oauth_access_token', + oauthRefreshToken: 'mock_oauth_refresh_token', + oauthId: '12345', + oauthNickname: 'mock_oauth_nickname', + email: 'mock_email@example.com', + profileImageUrl: 'mock_profile_image.jpg', + } as OauthLoginData), - requestUserInfo: () => - ({ - oauthId: '12345', - oauthNickname: 'mock_oauth_nickname', - email: 'mock_email@example.com', - profileImageUrl: 'mock_profile_image.jpg', - }) as RequestUserInfo, + signup: jest.fn().mockResolvedValue({ + oauthId: '12345', + oauthNickname: 'mock_oauth_nickname', + email: 'mock_email@example.com', + profileImageUrl: 'mock_profile_image.jpg', + } as OauthSignupData), - requestTokenExpiration: () => {}, + logout: jest.fn(), - requestUnlink: () => {}, + reissueTokens: jest.fn().mockResolvedValue({ + oauthAccessToken: 'new_mock_oauth_access_token', + oauthRefreshToken: 'new_mock_oauth_refresh_token', + } as OauthReissueData), - requestTokenRefresh: () => - ({ - access_token: 'new_mock_oauth_access_token', - refresh_token: 'new_mock_oauth_refresh_token', - }) as RequestTokenRefresh, + deactivate: jest.fn(), };