본문 바로가기
프론트엔드 상식

인증과 인가

by Whiimsy 2024. 6. 4.

우아한 테크코스 2기

내용

  • 인증과 인가란
  • 인증의 방법

목표

  • 인증과 인가에 대한 지식 습득 및 복습
  • 프로젝트에서 선택한 인증 방식에 대한 근거

인증이란

식별 가능한 정보로 서비스에 등록된 유저의 신원을 입증하는 과정

인가란

인증된 사용자에 대한 자원 접근 권한 확인

인증과 인가란

자원을 적절한/유효한 사용자에게 전달/공개하기 위한 방법

인증 단계

1. 인증하기 (Request Header)

무상태성(Stateless): 서버는 클라이언트에서 오는 요청이 각각 연관관계가 없다고 생각하고 처리한다

Request Header 활용하기

사용자가 http://www.cocktailpick.com/login 에 로그인 요청을 보내기 위해 직접 타이핑해http://user:1q2w3e!@www.cocktailpick.com/login 요청 시 브라우저에서 위 url을 Base64 인코더로 인코딩 후 전달. 예를 들어, url에서 user:1q2w3e! 부분을 파싱 후 인코딩된 문자열을 요청 헤더의 Authorization에 넣어 보내주는 방법

 

Request Header만 활용할 시 문제점

요청마다 매번 인증해야 한다 이를 해결하기 위해 등장한 것이 바로~

2. 인증 유지하기 (Browser)

Storage 활용하기(로컬/세션 스토리지, 쿠키): 예를 들어 ID 값이랑 비밀번호 값을 쿠키에 넣어놨다가 요청 보낼때마다 담아보내기만 하면 되서 사용하기 매우 EASY 해킹도 EASY 그래서~

3. 안전하게 인증하기 (Server)

서버의 도움 받아 Session 활용하기

인증된 사용자의 식별자와 랜덤한 문자열로 SESSIONID를 만들어 응답 헤더에 넘겨주고(Set-Cookie) 이 값을 클라이언트가 저장

 

 

장점

  • 클라이언트에서 사용자의 Raw한 데이터를 가지고 있지 않기 때문에 해킹 위험이 크진 않다
  • 세션 만료 기간을 정할 수 있음
  • 세션 관리를 서버에서 해서 탈튀된 세션의 경우 서버에서 삭제하면 되기 때문에 보안상 GOOD

문제점

서버가 여러개 생기면서 서버 하나하나 자체에서 세션을 관리하고 로드밸런서가 생기면서 로드밸런서가 클라이언트에서 첫번째 요청 때 보낸 서버와 다른 서버로 다음 요청을 보낼 수 있음. 그니까 세번째 서버에 SESSIONID 값이 있는데 두번째 서버로 연결해서 에러가 발생하는거

 

해결1: 세션스토리지

서버에서 관리하는 모든 세션들을 한 곳에서 관리 근데 이거도 문제있음 클라이언트가 많아져서 계속 SESSIONID가 쌓이면.. 터진다

 

해결2: 그럼 어덕캐요

클라이언트, 서버, 세션 저장소 모두 사용자의 상태를 관리 맡겨봤는데 다 문제점이 있음 그 이유는 HTTP와 서버 자체가 지향하는 REST API는 무상태성을 기초로 하는데 실제로 인증과 인가를 구현할 때는 사용자의 상태를 클라이언트, 서버, 세션 저장소 모두 가지고 있고 상태성을 띄고 있기 때문. 이 두 패러다임이 충돌해서 문제 그럼 클라이언트도 안되고 서버도 안되면 누구한테 인증/인가를 맡기냐(이제 누가 인증/인가해주냐) 화살표한테 맡겨보자!

 

4. 효율적으로 인증하기 (Token)

화살표는 정보의 흐름 나타내고 각각 요청, 응답 나타냄. 각각 요청과 응답 컨텐츠 안에 사용자의 상태를 담아보자

JWT(JSON WEB TOKEN)

  • 시크릿키를 사용해 JWT 만듦
  • 시크릿키로 JWT 인증과정 거침
  • JWT 자체는 해독이 무지 쉬움 비밀번호는 담으면 안됨 시크릿키가 노출되면 절대!!!! 안됨 서버 내부에서 잘 관리해줘야 함

JWT 활용하기

세션스토리지가 아닌 시크릿키 이용해 토큰 생성 이제부터 이 토큰을 헤더에 넣어서 요청/응답 주고 받으면 됨

 

JWT 장점

서버가 여러개가 있을 때 세션스토리지 사용할 땐 세션DB가 있어서 모든 서버와 세션DB가 연관성이 있었는데 토큰 사용하면 로드밸런서가 쏘는 서버마다 각자 다른 시크릿키로 해독을 해서 인증을 진행하면 됨 또 세개에서 다섯개로 늘어도 걍 똑같이 각자 시크릿키 가지고 해독하면 됨 확장성 용이, 토큰으로 상태관리를 하기에 따로 세션을 둘 필요가 없다. 효율성이 좋아지고 DB를 찌르지 않아도 되기 때문에 속도가 빠르다.

 

JWT 문제점

해킹.. 엑세스토큰을 탈취하면 해커=사용자됨 원하는 자원에 쉽게 접근 가능 이를 막기위해!

만료기한 사용. 근데 만료기한 지나면 사용자도 못써서 불편하자나요.. 해서 나온게!!

리프레시 토큰

  • 로그인 요청
  • 시크릿키로 토큰 생성
    • Access Token (DB 저장 X)
    • Refresh Token (DB 저장)
  • 두 토큰을 응답헤더로 보냄
  • 클라이언트가 두 토큰 저장
    • Access Token 만료기한 30분
    • Refresh Token 만료기한 2주
  • 클라이언트가 서버로 Access Token 담아 요청
  • 시간 지나 Access Token 만료 후 담아 요청
  • 서버가 만료되었는데요 응답
  • 클라이언트가 Access Token, Refresh Token 담아 요청
  • 서버가 DB에서 Refresh Token 찾아서 맞으면 새로 갱신한 Access Token 발급
  • 클라이언트에서 Access Token 갱신

핵심: 토큰으로 상태관리를 하기에 따로 세션을 둘 필요가 없다. 토큰 관리를 해야한다. 결국 토큰도 탈취당할 수 있다

5. 다른 채널을 통해 인증하기 (OAuth)