인증(Authentication)& 인가(Authorization)
유저기능이란?
- 최근 유망한 웹서비스(gmail, amazon, netflix, instagram...)들은 회원가입, 로그인을 필수로 제공함
회원가입과 로그인을 기반으로 각 유저별 피드 내용도 달라짐
- 유저기능의 작동 원리에 대해 알아볼 예정
인증 workflow
- 유저는 회원가입 페이지에서 이메일, 비밀번호와 같은 필수 정보 입력 > 회원가입 버튼을 누름
- 서버에 회원가입 url로 유저를 생성해달라는 POST request를 보냄, 정보는 body로 보냄
서버는 자연수 id를 붙여서 id, email, pw를 저장하는 유저모델을 생성함
- 유저가 사이트에서 본인만의 이메일과 비밀번호를 입력하고 로그인 버튼을 누름
- 서버에 로그인 url로 유저를 찾아달라는 POST request를 보냄, 정보는 body로 보냄
첫 로그인의 경우 무조건 id, pw를 입력해야 하지만 두번째, 세번째 로그인부터는 로그인 상태를 유지할 수 있도록 하는 기능은 첫번째 로그인을 성공하고 나면 서버측에서 유저를 식별할 수 있는 인증서 같은 문자열을 함께 반환하기 때문임. 따라서 이후 다시 로그인을 시도할 때마다 해당 인증서 문자열을 함께 서버측으로 보내고, 서버측은 누가 로그인을 시도중인지 식별할 수 있어서 로그인 과정이 간소화됨 (인증서에는 만료기한이 있음)
- 그렇다면 인증서를 다시 서버에게 전달하는 방식에는 무엇이 있을까?
1. 쿠키 인증
- 쿠키🍪? 서버 response나 client code에 따라 브라우저에 저장되는 작은 단위의 문자열 파일들
이름 = 값; 속성1; 속성2; ... 형태로, 속성들에는 서버에서 정한 만료일, 보안설정 등의 내용등이 담김
- 쿠키가 브라우저에 저장되는 방식:
- 서버 리스폰스: 브라우저에 저장된 쿠키는 서버에 리퀘스트를 보낼 때 함께 전송되어서 서버가 유저를 식별하는데 도움을 줌
- 클라이언트 코드
- 쿠키 인증이란? 서버에서 response의 Set-Cookie 헤더를 통해 클라이언트에 인증서를 저장하고, request의 Cookie 헤더를 통해 인증서를 다시 서버로 보내는 인증방식
- 보안 설정을 제대로 하지 않으면 CSRF 공격을 당할 수 있음
- 서버가 Set-Cookie를 통해 저장한 쿠키는 클라이언트에서 아무 코드를 쓰지 않아도 자동으로 모든 리퀘스트에 같이 전달됨
- 한 브라우저에 저장된 쿠키가 루트 도메인이 서로 다른 서버에(example.com과 somesite.com) 전달될 수는 없음
2. Authorization 헤더 인증
- 특징
- 수동으로 인증 관리하는 방식임 (쿠키 인증은 브라우저가 자동으로 관리해주는데에 반해)
- Set-Cookie 헤더가 없으므로 브라우저가 자동으로 쿠키를 저장하지는 않음
- 개발자가 직접 작성한, 클라이언트의 자바스크립트 코드로 쿠키에 접근해서 쿠키나 로컬스토리지에 저장함
- 장점
- request에 인증서를 붙일지 안 붙일지를 선택할 수 있음
- 서로 다른 root domain 사이에서 인증이 가능함 (cookie는 서로 다른 root domain에는 전달되지 않으므로)
✨ 유의점: 비밀번호와 같이 민감한 정보는 쿠키던 로컬스토리지던 절대 저장하지 않음
1. 세션 기반 인증
- 인증에 세션을 사용하여 로그인 정보들을 세션에 저장함

2. 토큰 기반 인증
-
인증토큰을 사용해서 request를 보낸 유저를 파악함
-
인증토큰: 유저에 대한 정보를 암호화한 문자열 (=접근토큰이라고도 부름)

-
비밀키를 통해 암호를 생성하거나 품
-
workflow: 서버가 토큰을 발행 > 클라이언트에게 전달 (response body를 통해서) > 클라이언트가 로그인 시 서버에게 토큰을 authorization header를 통해 돌려줌 > 서버는 다시 비밀키를 사용해서 해석해서 유저를 특정지음
-
최근에 주로 사용되는 토큰의 형식? JWT
-
토큰기반인증의 장점? 효율성, 유연성, restful한 API 서버와 더 적합함, 무효화 등
https://www.codeit.kr/topics/user-system-theory/lessons/5513
인코딩
- HTTP 헤더 이름과 값들은 ASCII 표준에 포함된 256개의 문자만 사용해야 함
- 만약 ASCII 외의 문자를 사용하고자 할 경우, 인코딩을 통해 ASCII에 속한 문자로 변환 후 사용해야 함
- 인코딩 방식으로는 base64url이 가장 많이 사용됨
기본 인증
- 인증서의 개념을 아예 사용하지 않은 채로 온전히 이메일과 비밀번호만을 사용한 인증
- request의 Authorization 헤더를 사용해서
Authorization: Basic email:password의 형태의 헤더를 서버로 보냄 (이 때, 이메일과 비밀번호는 인코딩을 거침)
- 그러나 최근에는 보안 등의 문제로 인해 주로 사용되지는 않는 방식임
Refresh 토큰
- Access 토큰이 보유한 유저에게 특정 권한을 주기 위한 목적으로 사용되지만 아무런 안전장치 없이 단독으로 사용되면 안정성 문제가 생길 수 있음
- 이를 해결하기 위해 Refresh 토큰을 사용
- Refresh 토큰: access 토큰이 만료됐을 때, 이메일 비밀번호를 사용하지 않고 access 토큰을 새롭게 발급받는 데 사용되는 토큰
JWT (JSON Web Token)
- Header: 토큰 자체에 대한 정보(암호화에 사용된 알고리즘, 토큰형식) 저장
- PayLoad: 토큰이 실질적으로 저장하려는 데이터가 저장되며, 저장하고자 하는 데이터 종류의 제약이 없음, 최대한 짧고 간결하게 저장함, 공식 이름을 최대한 활용하는 것이 권장됨 (공식이름들:
exp(expiration time), iat(issued at), jti(jwt id) 등)
- Signiture: 토큰을 믿을 수 있는지 확인하기 위한 데이터 저장
Header, Payload를 인코딩한 값 + 시크릿 키까지 3가지 정보가 합쳐져서 만들어짐 > 확인 시에도 직접 Header, Payload, 시크릿 키를 활용해서 signiture를 만들어본 후 토큰의 signiture와 비교해서 동일한지를 확인함

인가: Authorization
- 인가: request가 어떤 권한이 있는지 파악
- 인증 vs 인가
예시: 페이스북에서는 작성자와 관리자만이 게시물을 삭제할 수 있음
서버가 게시물 삭제 request를 받으면 > 보낸 유저를 파악하고 해당 유저에게 게시글을 삭제할 수 있는 권한이 있는지를 확인함
해당 예시에서, request와 함께 온 인증서, 세션ID나 토큰 등을 확인해서 request를 보낸 유저가 누구인지를 파악하는 과정이 인증, 해당 유저가 게시글을 삭제할 권한이 있는지를 확인하는 과정이 인가이다.
- 일반적으로 인증 > 인가의 순서로 이루어짐
- Authorization 헤더는 인증이 아닌 인가를 위한 헤더임
위임
접근권한 위임과 OAuth
- 접근위임: 한 서비스가 다른 서비스에 있는 보호된 리소스에 대한 접근 권한을 위임하거나 받는 기능
- OAuth (Open Authorization) : 개방형 접근 권한 위임 표준
OAuth 주체와 설정
- 예시: 코드잇 웹페이지에 학습일정관리 기능을 추가하기 위해 구글 캘린더와 연동한다고 가정하자.
- Client ID와 Secret: request가 코드잇으로부터 온다는 것을 증명하기 위해 필요한 값들이며, 코드잇 백엔드 서버에 저장해둬야 함
- Scope: 인가 서버로부터 넘겨받으려는 권한의 범위로, 예를 들어 코드잇이 유저 대신 스케줄 데이터를 읽어올 수 있다, 수정, 삭제, 생성을 할 수 있다, 유저와 동일한 권한을 가진다 등이 있음
OAuth workflow
- 접근권한을 특정 방식으로 주고받기 위해서 각 주체들이 해야 하는 작업들과 그 순서

- Authorization code: 유저 본인이 권한 위임을 정말 원한다는 것을 확인시켜주는 데이터
- access token: 미리 설정된, scope(토큰의 소유자가 요청할 수 있는 작업의 범위)에 대한 내용도 포함함
OpenID Connect (OIDC)
- OIDC = OAuth + 인증
- 예시: 유저가 코드잇 사이트에 로그인할 때 구글 계정으로 로그인하고자 한다고 가정
- OIDC 서비스 사용을 위한 준비단계들:
- Open ID Provider에서 코드잇 고유의 Client ID와 Client Secret 발급받고 코드잇 백엔드에 저장하기
- Scope: 성, 이름, 프로필사진, 생년월일 등 어떤 데이터나 기능에 접근하고자 하는지 정하기

- id token: 유저의 신원을 파악하기 위해 사용하며, 유저의 이메일, 성, 이름, 나이가 저장되어있음 (OIDC에서는 JWT 형식으로 발행됨)