이 글에서는 토큰 기반 인증에 대한 여러 글들을 조사하여 정리하였습니다. 참조한 레퍼런스는 하단에 링크 첨부하였습니다.
서버 기반 인증의 문제점
- 세션을 서버 메모리에 저장할 경우 사용자가 해당 서버로 접속해야만 세션이 유지됨
- 별도DB에 저장 할 경우 모든 웹 서버가 세션 DB에 의존성이 생김
- 세션 관리를 위해 쿠키가 많이 사용되는데 쿠키는 단일 도메인 또는 서브도메인에서만 작동하도록 설계 되어 있음 (CORS 문제). 즉, 쿠키 사용시 CORS 설정을 해야하기 때문에 도메인 분리가 번거러움
토큰 인증 방법
- 토큰에는 서버에서 정상적으로 발급된 토큰임을 증명하는 signature를 포함하고 있음
- 클라이언트에서는 토큰을 받급 받은 후 매 요청마다 토큰을 함께 서버에 전달
- 서버 전달 시 HTTP Header에 토큰을 포함
- 서버에서 토큰 검증이 성공해야만 응답을 받을 수 있음
토큰 사용 시 장점
- 토큰 정보를 클라이언트에 저장하기 때문에 의존성이 없다 (Stateless)
- 세션 정보를 저장하지 않기 때문에 확장이 자유롭다 (Scalability)
- 다른 서비스에 권한을 공유할 수 있다 (Extensibility)
- 토큰만 유효하다면 디바이스나 도메인에 상관없이 어디서나 정상적으로 처리할 수 있다. (CORS 해결)
- 서버에서 Response 시 "Access-Control-Allow-Origin: *" 헤더값을 포함하여 CORS 허용
JWT (JSON Web Token)
- 위에서 설명한 토큰 인증 방법 중 가장 많이 사용되고, 웹 표준
- JWT 토큰 발급 시 라이브러리를 사용하면 알아서 인코딩 및 해싱 작업을 해줌
- 인코딩 시에는 base64로 인코딩이 되는데 인코딩 시 뒤에 '=' 문자가 붙게됨
- 이는 base64의 padding 문자이고, 없어도 디코딩 시 문제되지 않음
- URL 파라미터로 base64가 전달 될 경우 url-safe하지 않기 때문에 제거되어야함
- JWT 토큰 발급 시에는 이 padding 값이 제거되어서 반환됨
포함되는 정보
- 토큰에 대한 기본 정보
- 클라이언트에 전달 할 사용자 정의 정보 (payload)
- 토큰이 검증되었음을 증명해주는 값 (signature)
전달 방법
- HTTP 헤더에 넣거나, URL의 파라미터로 전달
- 웹 서버는 대부분 HTTP 헤더에 포함
사용 예
- 회원 인증
- 사용자 로그인
- 서버에서 사용자 정보에 기반한 JWT 발급
- 사용자가 서버에 요청할 때마다 JWT를 포함하여 전달
- 서버에서는 요청을 받을 때마다 signature가 유효한지 검증하고, payload로 권한 확인
- 정보 교류
- 정보가 sign 되어 있기 때문에 정보를 보낸 사용자가 변경되지 않았는지, 정보가 조작되지 않았는지 검증
JWT 사용 방법
- JWT는 dot(.)을 구분자로하여 Header, Payload, Signature를 포함해야 함
- Header에는 토큰의 타입과 해싱 알고리즘을 지정
{ "typ": "JWT", "alg": "HS256" }
- 위 값을 base64로 인코딩
- Payload에는 토큰에 담을 정보를 포함
- 정보의 단위를 클레임(claim)이라고 하고, 3가지 유형이 있음. 모두 key-value 형식으로 지정
- registered claim : 미리 등록되어 있는 유형을 의미
- public claim : 충돌 방지를 위해 키를 URI 형식을 사용
- private claim : 클라이언트/서버 간의 협의 하에 사용되는 사용자정의 데이터
- 아래와 같이 claim을 혼합하여 Play로드를 생성
{ "iss": "yonghochoi.com", "https://yonghochoi.com/jwt": true, "username": "yonghochoi" }
- 위 값을 base64로 인코딩
- 정보의 단위를 클레임(claim)이라고 하고, 3가지 유형이 있음. 모두 key-value 형식으로 지정
- Signature에는 Header의 base64 인코딩 값과 Payload의 base64 인코딩 값을 dot(.)을 구분자로 하여 합친 후에 비밀키를 사용하여 해쉬값을 생성
- 이 때 해쉬 생성에는 앞서 지정한 해쉬 알고리즘이 사용됨
- 해시 값 또한 base 64로 인코딩
- Header, Payload, Signature 각각의 Base64 인코딩 값을 dot(.)을 구분자로 합치면 하나의 JWT 토큰이 완성됨
- 완성된 JWT 토큰은 아래 JWT Debugger 사이트를 사용하여 검증 테스트를 해볼 수 있음
참고
'Work > 개발 노트' 카테고리의 다른 글
[WEB] certbot으로 Let's Encrypt 인증서 발급 받기 (1) | 2020.09.07 |
---|---|
[WEB] 쿠키 개념 잡기 (0) | 2020.09.06 |
[LDAP] 개념 잡기 (3) | 2020.09.04 |
[파이썬] 모듈 사용하기 (0) | 2020.09.03 |
Go언어로 웹 서버 개발 시 Swagger 문서 자동 생성하기 (0) | 2020.05.05 |
댓글