로그인 방식의 분류
로그인(인증) 방식은 크게 토큰 방식과 세션 방식으로 구현 된다
세션 방식(Session)
세션은 시스템 관리자가 일정 기간 서비스를 이용하는 것을 허락하는 구조이다.
세션 동안 사용자는 허락된 범위 안에서 서비스 자원 사용이 가능하다
세션 기반 인증에서는 서버는 사용자가 로그인하면, 사용자를 위한 세션을 생성한다
세션 ID는 사용자 브라우저 쿠키에 저장되어, 세션 유지하는 동안 사용자는 저장된 세션 ID와 요청을 서버에게 전송한다.
서버는 전송된 된 세션 ID와 메모리에 저장된 세션 정보를 비교하여 사용자의 신원을 확인 후 응답한다
토큰 방식(token)
토큰은 사용자가 자신을 인증하고, 고유한 액세스 토큰을 받는다. 해당 토큰은 웹페이지나 앱 등에 저장되어 토큰이 유효한 동안 자격 증명을 할 필요 없이 서비스를 사용할 수 있다.
토큰 기반 인증의 장점은 자격 증명을 다시 할 필요 없이 자원에 접근할 수 있다는 것이다
최근 토큰 방식 인증에는 많이 [[MOC/JWT 다루기|JWT]]가 사용되는데, JWT의 경우, 서버에서 무결성 체크, 사용자 인증, 권한 관리 등이에 용이하다
Token 내부에 클라이언트의 상태/권한 등을 저장하고, Token 자체로 인증이 가능하기 때문이다
또한 Token의 경우, 세션이 서버 메모리에 저장 되는 것과 달리, 클라이언트 측에 저장되기 때문에 확장성과 서버 자원을 확보할 수 있다
Token 구현의 Workflow
사용자가 로그인을 하면, 서버는 사용자에게 access_token과 refresh_token을 준다
access_token은 사용자가 서버에 자신을 증명할 때 사용한다
refresh_token은 access_token이 만료되었을 경우 Token 재발급에 사용된다
액세스가 만료되면 사용자는 refresh token을 전송해 서버로부터 access token을 재발급 받고 다시 요청한다
refresh token이 만료되면 다시 로그인 한다
난 JWT를 사용해서 구현했기 때문에, 스토리지에 발급 받은 토큰이 저장된다
실습
유저 인증 흐름은 통합 로그인(OAuth2) - 토큰 발행 순으로 이어진다.
통합 로그인은 @fastify/oauth2 라이브러리를 사용하여 구글 아이디로 로그인 하도록 한다.
yarn add @fastify/oauth2
: 라이브러리를 다운로드한다.- fastify 인스턴스에 oauthplugin 설정 값을 등록한다.
아래의 googleAuth가 설정 값이다. 보안을 위해 google에서 발급 받은 client id와 secret은 분리 후 불러와 사용한다.
import oauth2 from "@fastify/oauth2";
import {haqqaton, SERVER_URI} from "@config/haqqaton.config";
const _google = haqqaton.oauth.google;
let callbackUri = `${SERVER_URI}${_google.redirectUri}`;
const googleAuth = {
name: "googleOAuth2",
scope: ["email", "profile"],
credentials: {
client: {id: _google.clientId, secret: _google.clientSecret},
auth: oauth2.GOOGLE_CONFIGURATION,
},
startRedirectPath: _google.redirectPath,
callbackUri,
callbackUriParams: {
access_type: "offline",
},
};
google Auth 인자는 라이브러리 문서에 더 자세히 나와 있다
- name : 이름
- scope : 인증 후 가져올 데이터 값들
- credentials :
- client : 발급 받은 client id와 secret
- auth : 통합 로그인 플랫폼 명시 (공식 문서를 보면 미리 auth 프리셋이 만들어져 있다)
- startRedirectPath : 로그인 시작 시 리다이랙트 될 경로
- callbackUri : 로그인 후 call back 할 경로 명시
- callback Uri로 토큰을 보내 준다.
설정 파일이 완성되었다면, fastify에 등록하자.
- callback Uri로 토큰을 보내 준다.
fastify.register(oauthPlugin, googleAuth)
- 토큰 처리
로그인을 하면 callback uri로 토큰이 날라오므로, 토큰에서 데이터를 추출해야 한다.
export default async function (fastify: any) {
fastify.get("/callback", async (req: FastifyRequest, reply: FastifyReply) => {
const {token} = await fastify.googleOAuth2.getAccessTokenFromAuthorizationCodeFlow(req);
const {id_token}: any = token;
const data = parseJWT(id_token);
const ssoid = data?.sub;
const email = data?.email;
const nickname = data?.name;
const login = await checkSSO(LOGIN_TYPE.GOOGLE, ssoid, {email, nickname});
reply.send(login);
});
}
getAccessTokenFromAuthorizationCodeFlow()
로 code와 state를 다시 서버로 전송하고, 도착한 데이터에서 token을 추출한다.
좀 더 자세히 설명하면, callback url로 들어온 req에서 code,state를 추출하고, 서버로 부터 토큰을 발행 받는다
서버는 JWT로 데이터를 보내주는데, 이 안에는 access token과 id_token, scope,expire 시간 등이 들어있다.
우리가 찾는 유저 정보는 id_token 내에 들어있다
위의 과정을 거쳐 발급 받은 토큰에서 데이터를 추출하고, 데이터베이스에 저장된 유저의 데이터와 일치하면 로그인 시킨다
레퍼런스
'DEV > Backend' 카테고리의 다른 글
Typeorm unique란? (0) | 2023.01.30 |
---|---|
TypeORM의 Where In 절 (0) | 2023.01.30 |
JWT 다루기 (0) | 2023.01.26 |
TypeORM Releation 다루기 (0) | 2023.01.26 |
Mac에서 MySQL 설치 (0) | 2023.01.16 |