https://docs.github.com/ko/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps
* github oauth
- 깃헙 > 세팅 > dev > oauth app 생성
- cid ,c pw 발급받기
- auth/github로 접근시 깃허브로 redirect -> get요청 보내기
dotenv.config(); // env환경변수 파일 가져오기
export class GitAuthController implements ControllerV6{
async process(req: Request, res: Response, paramMap: Map<string, string>, model: Map<string, object>) {
const clientId: string = process.env.GITHUB_CLIENT_ID;
const githubAuthURL = `https://github.com/login/oauth/authorize?client_id=${clientId}&scope=user:email`;
res.redirectGithub(githubAuthURL);
req.isEnd=true;
return "";
}
version6() {
}
}
public redirectGithub(path: string) {
this.status(302).header("Location", path).send();
}
- 승인을누르면 깃허브가 사용자에게 callbackurl로 code라는 쿼리파라미터를 가지고 다시요청하라고 명령한다.
- 내 서버는 이 code를 가지고 엑세스 토큰을 요청한다.
- accesstoken으로 github에서 받은 정보들로 회원가입 && 세션생성
- username은 깃허브username + _github 컨벤션 적용.
- 이때, 비밀번호는 uuid이용 => 수동 로그인 방지
/**
* email 배열중
* primary가 true인 email을 찾아서 사용
*/
const primaryEmail = emailsResponse.data.find((email: any) => email.primary).email;
/**
* 이메일로 회원가입 여부 확인 && 없으면 새로회원가입, 세션생성
* 비밀번호설정 : uuid로 설정 => 수동 로그인 막기
*/
let findMember = await this.memberRepositoryCustom.findByEmail(primaryEmail);
if (!findMember) {
const newMember = new Member(primaryEmail, userResponse.data.login +"_github", uuidv4());
await this.memberRepository.save(newMember);
findMember = newMember;
}
this.sessionMgr.createSession(findMember, res);
return "redirect:index";
- 전체코드
import {Request} from "../../was/request";
import {Response} from "../../was/response";
import {ControllerV6} from "../../frontcontroller/v6/ControllerV6";
import * as dotenv from 'dotenv';
import {MemberRepository} from "../member/MemberRepository";
import {SessionManager} from "../../utils/SessionManager";
import axios from 'axios';
import {Member} from "../member/Member";
import { v4 as uuidv4 } from 'uuid';
dotenv.config(); // env환경변수 파일 가져오기
export class GitAuthCallbackController implements ControllerV6{
private memberRepositoryCustom = MemberRepository.getInstance();
private memberRepository = MemberRepository.getInstance().getRepo();
private sessionMgr : SessionManager = SessionManager.getInstance();
async process(req: Request, res: Response, paramMap: Map<string, string>, model: Map<string, object>) {
const clientId: string = process.env.GITHUB_CLIENT_ID;
const clientSecret: string = process.env.GITHUB_CLIENT_SECRET;
const redirectURI = 'http://localhost:3000/auth/github/callback';
const { code } = req.query;
const tokenResponse = await axios.post('https://github.com/login/oauth/access_token', {
client_id: clientId,
client_secret: clientSecret,
code,
redirect_uri: redirectURI,
}, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
});
const accessToken = tokenResponse.data.access_token;
const userResponse = await axios.get('https://api.github.com/user', {
headers: {
Authorization: `token ${accessToken}`,
},
});
// console.log(userResponse);
/**
* email은 추가 요청해야함.
* 기본 응답에 포함되지않음.
* 이래서 처음 권한받을때 scope에 email을 받은것임.
*/
const emailsResponse = await axios.get('https://api.github.com/user/emails', {
headers: {
Authorization: `token ${accessToken}`,
},
});
/**
* email 배열중
* primary가 true인 email을 찾아서 사용
*/
const primaryEmail = emailsResponse.data.find((email: any) => email.primary).email;
/**
* 이메일로 회원가입 여부 확인 && 없으면 새로회원가입, 세션생성
* 비밀번호설정 : uuid로 설정 => 수동 로그인 막기
*/
let findMember = await this.memberRepositoryCustom.findByEmail(primaryEmail);
if (!findMember) {
const newMember = new Member(primaryEmail, userResponse.data.login +"_github", uuidv4());
await this.memberRepository.save(newMember);
findMember = newMember;
}
this.sessionMgr.createSession(findMember, res);
return "redirect:index";
}
version6() {
}
}
* 프론트 구현
- 간단하다. 로그인페이지에 링크하나 추가하면된다.
<div class="login-button-block-github">
<button type="button" class="github-button" onclick="location.href='/auth/github'">
<svg class="github-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="white">
<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
</svg>
깃허브로 로그인
</button>
</div>
/* git login css*/
.login-button-block-github {
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
font-family: Arial, sans-serif;
}
.github-button {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
background-color: #24292e;
color: white;
border: none;
border-radius: 6px;
padding: 10px 20px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: background-color 0.3s ease;
}
.github-button:hover {
background-color: #2c3238;
}
.github-icon {
width: 24px;
height: 24px;
}
.login-text {
font-size: 14px;
color: #586069;
}
.login-link {
color: #0366d6;
text-decoration: none;
font-weight: bold;
}
.login-link:hover {
text-decoration: underline;
}
* csrf 공격
- 배경
- 개념
* fetch vs axios
- 간단한 axois를 사용하고자 함.
'JS > boostCamp' 카테고리의 다른 글
24. 10. 17. 개발일지 // mysql, 인덱싱 (1) | 2024.10.18 |
---|---|
24.10.15. 개발일지 // oauth fix, 이미지 업로드, Not allowed to load local resource error 해결 (0) | 2024.10.16 |
24.10.11. 개발일지 // 배포, redis, 댓글, 조회수증가, 페이징, dns, 에러페이지 (3) | 2024.10.14 |
24. 10. 10. 개발일지 // 글쓰기 구현, 동적 url 매핑 , n+1 문제 (0) | 2024.10.10 |
24. 10. 9. 개발일지 // redirectAttributes, 로그인이완료된후 원래페이지 이동, db, n+1 문제 (1) | 2024.10.10 |