Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#232 [Feat] 소셜 로그인 시, 이메일 받아오는 로직 추가 #233

Merged
merged 3 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9,613 changes: 4,155 additions & 5,458 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
"@prisma/client": "^5.4.2",
"axios": "^1.3.4",
"dayjs": "^1.11.7",
"dotenv": "^16.0.3",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"express-validator": "^6.15.0",
"jsonwebtoken": "^9.0.0",
"multer": "^1.4.5-lts.1",
"multer-s3": "^3.0.1",
"multer-s3": "2",
"nodemailer": "^6.9.1",
"prisma": "^5.4.2"
},
Expand Down
31 changes: 16 additions & 15 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,31 @@ datasource db {

model User {
id Int @id @unique @default(autoincrement())
nickname String? @unique @db.VarChar(50)
nickname String? @db.VarChar(50)
profileImage String? @db.VarChar(500)
intro String? @db.VarChar(100)
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
social_platform String @db.VarChar(10)
social_id String @db.VarChar(50)
refresh_token String @db.VarChar(500)
updatedAt DateTime? @updatedAt @db.Timestamp(6)
social_platform String? @db.VarChar(10)
social_id String? @db.VarChar(50)
refresh_token String? @db.VarChar(500)
email String? @db.VarChar(100)
Alarm_Alarm_receiverIdToUser Alarm[] @relation("Alarm_receiverIdToUser")
Alarm_Alarm_senderIdToUser Alarm[] @relation("Alarm_senderIdToUser")
Block_Block_userIdToUser Block[] @relation("Block_userIdToUser")
Block_Block_friendIdToUser Block[] @relation("Block_friendIdToUser")
Bookshelf Bookshelf[]
Friend_Friend_receiverIdToUser Friend[] @relation("Friend_receiverIdToUser")
Friend_Friend_senderIdToUser Friend[] @relation("Friend_senderIdToUser")
recommendedByToUser Recommend[] @relation("Recommend_recommendedByToUser")
Friend_Friend_receiverIdToUser Friend[] @relation("Friend_receiverIdToUser")
recommendToToUser Recommend[] @relation("Recommend_recommendToToUser")
recommendedByToUser Recommend[] @relation("Recommend_recommendedByToUser")
Report_Report_userIdToUser Report[] @relation("Report_userIdToUser")
Report_Report_friendIdToUser Report[] @relation("Report_friendIdToUser")
}

model Book {
id Int @id @unique @default(autoincrement())
bookTitle String @db.VarChar(100)
bookTitle String @db.VarChar(500)
author String @db.VarChar(50)
bookImage String? @db.VarChar(500)
publisher String @db.VarChar(50)
Expand All @@ -48,7 +49,7 @@ model Bookshelf {
userId Int
bookId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
updatedAt DateTime? @updatedAt @db.Timestamp(6)
Book Book @relation(fields: [bookId], references: [id], onDelete: NoAction, map: "bookshelf_book_id_fk")
User User @relation(fields: [userId], references: [id], onDelete: Cascade, map: "bookshelf_user_id_fk")
NewBookAlarm NewBookAlarm[]
Expand All @@ -58,8 +59,8 @@ model Friend {
followId Int @id @unique @default(autoincrement())
receiverId Int
senderId Int
receiverIdToUser User @relation("Friend_receiverIdToUser", fields: [receiverId], references: [id], onDelete: Cascade, map: "friend_user_id_fk")
senderIdToUser User @relation("Friend_senderIdToUser", fields: [senderId], references: [id], onDelete: Cascade, map: "friend_user_id_fk_2")
receiverIdToUser User @relation("Friend_receiverIdToUser", fields: [receiverId], references: [id], onDelete: Cascade, map: "friend_user_id_fk")
}

model Alarm {
Expand All @@ -82,8 +83,8 @@ model Recommend {
bookId Int
createdAt DateTime @default(now())
Book Book @relation(fields: [bookId], references: [id], onDelete: Cascade, map: "recommend_book_id_fk")
recommendedByToUser User @relation("Recommend_recommendedByToUser", fields: [recommendedBy], references: [id], onDelete: Cascade, map: "recommend_user_id_fk")
recommendToToUser User @relation("Recommend_recommendToToUser", fields: [recommendTo], references: [id], onDelete: Cascade, map: "recommend_user_id_fk_2")
recommendedByToUser User @relation("Recommend_recommendedByToUser", fields: [recommendedBy], references: [id], onDelete: Cascade, map: "recommend_user_id_fk")
RecommendAlarm RecommendAlarm[]
}

Expand All @@ -104,8 +105,8 @@ model NewBookAlarm {
}

model AlarmType {
id Int @id(map: "alarmType_pkey") @default(autoincrement())
typeName String @db.VarChar(50)
id Int @id @default(autoincrement())
typeName String? @db.VarChar(50)
}

model Block {
Expand All @@ -117,10 +118,10 @@ model Block {
}

model Report {
id Int @id @default(autoincrement())
id Int @id @unique @default(autoincrement())
userId Int
friendId Int
reasonIndex Int @default(0)
reasonIndex Int?
etc String? @db.VarChar(300)
User_Report_userIdToUser User @relation("Report_userIdToUser", fields: [userId], references: [id], onDelete: Cascade, map: "report_user_id_fk")
User_Report_friendIdToUser User @relation("Report_friendIdToUser", fields: [friendId], references: [id], onDelete: Cascade, map: "report_user_id_fk_2")
Expand Down
16 changes: 8 additions & 8 deletions src/interfaces/alarm/AlarmResponseDTO.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export interface AlarmResponseDTO {
alarmId: number,
senderId: number,
senderName: string | null,
profileImage: string | null,
bookTitle?: string,
typeId: number,
createdAt: string
}
alarmId: number;
senderId: number;
senderName: string | null;
profileImage: string | null;
bookTitle?: string;
typeId: number;
createdAt: string;
}
4 changes: 4 additions & 0 deletions src/interfaces/social/AppleLoginVO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface AppleLoginVO {
socialId: string;
email: string;
}
3 changes: 2 additions & 1 deletion src/modules/jwtHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const sign = (userId: number) => {
};

const accessToken = jwt.sign(payload, privateKey, {expiresIn: "3d"});

return accessToken;
};

Expand Down Expand Up @@ -46,5 +47,5 @@ const getRefreshToken = () => {
export default {
sign,
verify,
getRefreshToken
getRefreshToken,
};
105 changes: 58 additions & 47 deletions src/modules/social.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import axios from "axios";
import { sc } from "../constants";
import jwt from 'jsonwebtoken';
import jwt from "jsonwebtoken";
import { createPublicKey } from "crypto";
import { AppleLoginVO } from "../interfaces/social/AppleLoginVO";

const signInKakao = async (socialToken: string) => {
try {
const user = await axios.get('https://kapi.kakao.com/v2/user/me', {
const user = await axios.get("https://kapi.kakao.com/v2/user/me", {
headers: {
Authorization: `Bearer ${socialToken}`,
},
Expand All @@ -21,70 +22,80 @@ const signInKakao = async (socialToken: string) => {
};

const getApplePublicKey = async () => {

try {
const user = await axios.get('https://appleid.apple.com/auth/keys');
const user = await axios.get("https://appleid.apple.com/auth/keys");
const { data } = user;

if (!data) {
throw sc.UNAUTHORIZED;
}

return data.keys;
} catch (err) {
throw sc.UNAUTHORIZED;
}

};

//* 애플 identityToken
const signInApple = async (identityToken: string) => {
const JWTSet = await getApplePublicKey();
const identityTokenHeader: string = identityToken?.split('.')[0];
const { kid } = JSON.parse(atob(identityTokenHeader));

let rightKeyN;
let rightKeyE;
let rightKeyKty;

JWTSet.map((key: any) => {
if (kid === key.kid) {
rightKeyN = key.n;
rightKeyE = key.e;
rightKeyKty = key.kty;
}
});
try {
const JWTSet = await getApplePublicKey();
const identityTokenHeader: string = identityToken?.split(".")[0];
const { kid } = JSON.parse(atob(identityTokenHeader));

let rightKeyN;
let rightKeyE;
let rightKeyKty;

JWTSet.map((key: any) => {
if (kid === key.kid) {
rightKeyN = key.n;
rightKeyE = key.e;
rightKeyKty = key.kty;
}
});

if (!rightKeyN || !rightKeyE) return null;
if (!rightKeyN || !rightKeyE) return null;

const key = {
n: rightKeyN,
e: rightKeyE,
kty: rightKeyKty,
};
const key = {
n: rightKeyN,
e: rightKeyE,
kty: rightKeyKty,
};

const nBuffer = Buffer.from(key.n, 'base64');
const eBuffer = Buffer.from(key.e, 'base64');
const nBuffer = Buffer.from(key.n, "base64");
const eBuffer = Buffer.from(key.e, "base64");

const publicKey = createPublicKey({
key: {
kty: key.kty,
n: nBuffer.toString('base64'),
e: eBuffer.toString('base64'),
},
format: 'jwk',
});
const publicKey = createPublicKey({
key: {
kty: key.kty,
n: nBuffer.toString("base64"),
e: eBuffer.toString("base64"),
},
format: "jwk",
});

//verify 실행
const user = jwt.verify(identityToken, publicKey) as jwt.JwtPayload;
const userSocialId = user.sub as string;
//verify 실행
const user = jwt.verify(identityToken, publicKey) as jwt.JwtPayload;
const userSocialId = user.sub as string;
const userEmail = user.email;

return userSocialId;
}
const appleLoginVO: AppleLoginVO = {
socialId: userSocialId,
email: userEmail,
};

export default {
signInKakao,
signInApple,
getApplePublicKey,
if (!appleLoginVO) {
throw sc.UNAUTHORIZED;
}
return appleLoginVO;
} catch (err) {
throw sc.UNAUTHORIZED;
}
};

};
export default {
signInKakao,
signInApple,
getApplePublicKey,
};
Loading
Loading