Skip to content

Commit

Permalink
refactor: auth API
Browse files Browse the repository at this point in the history
  • Loading branch information
timepresent95 committed Aug 20, 2024
1 parent 1168662 commit 1eec860
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 82 deletions.
139 changes: 77 additions & 62 deletions src/mocks/handlers/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,79 +4,94 @@ import {http, HttpResponse} from 'msw';

import {getApiUrl} from '../utils/api';

import {RequestSignIn, RequestSignUp, ResponseToken} from '@/api/auth';
import {
//NOTE: 로그인 실패 -> 회원 가입 로직
// RequestSignIn,
ResponseToken,
} from '@/api/auth';
import {authApis} from '@/api/routes';
import {createUser} from '@/mocks/fakers';
import {createFakeJWT} from '@/mocks/utils/token';
import {createFakeToken, setFakeToken} from '@/mocks/utils/token';

export default [
http.post(getApiUrl(authApis.signIn), async ({request}) => {
const body = (await request.json()) as Partial<RequestSignIn>;
const {OAuthProvider, AuthorizationCode} = body;
const oauthAgent = ['NATIVE', 'GOOGLE', 'NAVER', 'KAKAO', 'APPLE'];
if (
!OAuthProvider ||
!oauthAgent.includes(OAuthProvider) ||
!AuthorizationCode
) {
return new HttpResponse(null, {
status: 400,
statusText: 'Bad Request',
});
}
http.post(getApiUrl(authApis.signUp), () => {
const accessToken = createFakeToken();
const refreshToken = createFakeToken(true);

setFakeToken({accessToken, refreshToken});

const response = {
accessToken,
refreshToken,
grantType: 'Bearer',
} as ResponseToken;

return HttpResponse.json(response, {status: 201});
}),
http.post(getApiUrl(authApis.signIn), async () => {
//NOTE: 로그인 실패 -> 회원 가입 로직
// return HttpResponse.json(
// {
// code: 'AUTH-0001',
// message: '가입하지 않은 회원입니다. 회원가입을 진행해주세요.',
// data: {
// OAuthProvider,
// AuthorizationCode,
// email: faker.internet.email(),
// },
// },
// {
// status: 401,
// statusText: 'Unauthorized',
// const body = (await request.json()) as RequestSignIn;
// const {OAuthProvider, AuthorizationCode} = body;
// const userEmail = faker.internet.email();
// const response = {
// code: 'AUTH-0001',
// message: '가입하지 않은 회원입니다. 회원가입을 진행해주세요.',
// data: {
// OAuthProvider,
// AuthorizationCode,
// email: userEmail,
// },
// );
// };
// return HttpResponse.json(response, {
// status: 403,
// statusText: 'Forbidden',
// });

//NOTE: 로그인 성공 로직
return HttpResponse.json({
accessToken: createFakeJWT(createUser(true)),
refreshToken: createFakeJWT(createUser(true), 24 * 60 * 60),
const accessToken = createFakeToken();
const refreshToken = createFakeToken(true);

setFakeToken({accessToken, refreshToken});

const response = {
accessToken,
refreshToken,
grantType: 'Bearer',
} as ResponseToken);
} as ResponseToken;

return HttpResponse.json(response, {status: 201});
}),
http.get(getApiUrl(authApis.signOut), () => {
return new HttpResponse(null, {
status: 204,
statusText: 'No Content',
});
http.patch(getApiUrl(authApis.signOut), () => {
const accessToken = createFakeToken();
const refreshToken = createFakeToken(true);

setFakeToken({accessToken, refreshToken});

const response = {
accessToken,
refreshToken,
grantType: 'Bearer',
} as ResponseToken;

return HttpResponse.json(response, {status: 201});
}),
http.post(getApiUrl(authApis.signUp), async ({request}) => {
const body = (await request.json()) as RequestSignUp;
if (
!(
body.nickName &&
body.OAuthProvider &&
body.birth &&
body.birthType &&
body.email &&
body.groupRole &&
(body.familyCode || body.familyCode === null)
)
) {
return new HttpResponse(null, {
status: 400,
statusText: 'Bad Request',
});
}
return HttpResponse.json({
accessToken: createFakeJWT(createUser(true)),
refreshToken: createFakeJWT(createUser(true), 24 * 60 * 60),
http.patch(getApiUrl(authApis.reIssueToken), () => {
const accessToken = createFakeToken();
const refreshToken = createFakeToken(true);

setFakeToken({accessToken, refreshToken});

const response = {
accessToken,
refreshToken,
grantType: 'Bearer',
} as ResponseToken);
} as ResponseToken;

return HttpResponse.json(response, {status: 201});
}),
http.get(getApiUrl(authApis.validateFamilyCode), () => {
return HttpResponse.json({isValidate: true});
}),
http.patch(getApiUrl(authApis.reRegistrationAlertToken), () => {
return HttpResponse.json();
}),
];
36 changes: 19 additions & 17 deletions src/mocks/utils/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import {Buffer} from 'buffer';

import {faker} from '@faker-js/faker';

import {Member} from '@/types';

const SECRET_KEY = 'secret-key';

function base64Encode(str: string) {
Expand All @@ -14,10 +12,8 @@ function base64Decode(str: string) {
return Buffer.from(str, 'base64').toString('utf-8');
}

export function createFakeJWT(
payload: Member,
expiresInSeconds: number = 60 * 60,
) {
export function createFakeToken(isRefresh = false) {
const expiresInSeconds = isRefresh ? 24 * 60 * 60 : 60 * 60;
const header = {
alg: 'HS256',
typ: 'JWT',
Expand All @@ -30,32 +26,36 @@ export function createFakeJWT(
iat: currentTime,
exp: currentTime + expiresInSeconds,
noncee: faker.string.uuid(),
...payload,
}),
);
const signature = base64Encode(
`${encodedHeader}.${encodedPayload}.${SECRET_KEY}`,
);

const token = `${encodedHeader}.${encodedPayload}.${signature}`;

return token;
}

export function verifyFakeJWT(token: string) {
type FakeTokens = {accessToken: string | null; refreshToken: string | null};

let myFakeTokens: FakeTokens = {
accessToken: null,
refreshToken: null,
};

export function setFakeToken(tokens: Partial<FakeTokens>) {
myFakeTokens = {...myFakeTokens, ...tokens};
}

export function verifyFakeToken(token: string) {
try {
const parts = token.split('.');
if (parts.length !== 3) {
return false;
}

const [encodedHeader, encodedPayload, signature] = parts;
const validSignature = base64Encode(
`${encodedHeader}.${encodedPayload}.${SECRET_KEY}`,
);

if (signature !== validSignature) {
return false;
}
const [, encodedPayload] = parts;

const payload = JSON.parse(base64Decode(encodedPayload));

Expand All @@ -64,7 +64,9 @@ export function verifyFakeJWT(token: string) {
return false; // 토큰이 만료됨
}

return true;
return (
token === myFakeTokens.accessToken || token === myFakeTokens.refreshToken
);
} catch (error) {
return false;
}
Expand Down
6 changes: 3 additions & 3 deletions src/utils/token.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {Member} from '@/types';
import {UserInfo} from '@/types';

//NOTE: 유저 정보를 토큰에서 얻기 위한 함수
//FIXME: BE에서 전달해준 payload가 정해지면 수정해야 함
export function getUserFromToken(token: string): Member | null {
export function getUserFromToken(token: string): UserInfo | null {
try {
const parts = token.split('.');
if (parts.length !== 3) {
Expand All @@ -15,7 +15,7 @@ export function getUserFromToken(token: string): Member | null {
);
const payload = JSON.parse(decodedPayload);

return payload as Member;
return payload as UserInfo;
} catch (error) {
return null;
}
Expand Down

0 comments on commit 1eec860

Please sign in to comment.