개발 공부 일지/CS

유저 기능 - 인증 (쿠키, 세션, 토큰)

yelimu 2024. 10. 16. 19:35

초코 쿠키면 좋았을텐데 ...

 

 

[기본 개념]

유저기능

  1. 인증 - 특정 유저임을 확인
  2. 인가 - 해당 유저의 권한 여부 확인

인증 Authentication

유저 - 모델 (또는 클래스) 의 인스턴스
: id(email), pw 등의 정보를 갖는다.

회원가입 - 유저 모델의 body(email, pw) 를 서버에 저장하는 것
: 회원가입 API(POST 리퀘스트)를 보내면 성공/실패 반환

로그인 - email, pw 정보를 로그인 API 리퀘스트 로 보내면
서버는 '어떤' 유저인지 확인후 성공/실패 반환
성공인 경우 인증서를 클라이언트에게 전달

이후 클라이언트가 리퀘스트를 보낼때 (= 유저가 보호된 리소스에 접근하려고 할때)
인증서를 서버에 같이 보낸다 
-> 각 리퀘스트를 보낸 유저를 알 수 있다 (인증)

로그아웃 : 인증서 만료 기간이 지남

인증서 종류에 따라 보관 위치나 특징이 다르다 - 쿠키, 토큰(JWT, OAuto 토큰, 세션 토큰)

*비밀번호 전송 및 저장 시 반드시 해시 처리한 값으로 다루기


인증서의 관리 주체에 따라 나눠보면

1. 브라우저

2. 클라이언트 

 

먼저 브라우저가 자동으로 저장하고 전송해주는 인증서의 형태로..

 

쿠키 기반 인증

리퀘스트를 보낼때마다 브라우저가 저장, 전송 등의 관리를 알아서 해준다.

클라이언트 : 로그인 리퀘스트
-> 서버 : 인증서 발급 & 리스폰스에 전달
Set-Cookie 헤더에 쿠키 정보 (쿠키 이름 = 값 ; 속성(만료일, 보안설정))

// HTTP response 예시
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure; SameSite=Strict; 
Expires=Wed, 18 Oct 2024 07:28:00 GMT
Content-Length: 123
Connection: keep-alive
Date: Tue, 17 Oct 2023 07:28:00 GMT
//SameSite 옵션 : None/ Lax/ Strict
-> 클라이언트 (브라우저)에 저장

-> 리퀘스트 보낼때마다 Cookie : 이름 넣어서 보낸다 (주체 : 브라우저)
쿠키를 발급해준 도메인에 리퀘스트를 보낼때만 쿠키를 보낸다.

GET /protected-resource HTTP/1.1
Host: example.com
Cookie: sessionId=abc123

-> 서버는 쿠키 헤더를 보고 유저를 특정한다.

 


반면 브라우저가 알아서 저장, 전송해주지 않는

클라이언트가 관리하는 인증 방법

(JWT 또는 Access 토큰이 포함됨)

클라이언트: 로그인 리퀘스트
-> 서버 : 정보 확인 후 인증서 생성
Set-Cookie가 아닌! 바디에 인증서 추가 & 리스폰스로 보냄
-> 클라이언트는 Set-Cookie 헤더가 없으니 쿠키를 브라우저에 저장하지 않는다.

인증서를 로컬스토리지, 세션스토리지, 쿠키 에 저장할 수 있다. (브라우저가 처리 해주지않음)
JS 코드로 저장, 접근해야한다

둘 다 필요할 때 JS 코드로 읽어오면 된다.
ex.

// 로그인 성공 후 받은 토큰을 로컬스토리지에 저장
localStorage.setItem('authToken', 'your-jwt-token');

// 이후 요청할 때 직접 로컬스토리지에서 토큰을 꺼내서 사용
const token = localStorage.getItem('authToken');
fetch('/protected-resource', {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${token}`
 

// 세션스토리지 데이터 저장, 가져오기
sessionStorage.setItem('key', 'value'); 
const value = sessionStorage.getItem('key');

 

이 경우 인증서를 서버에 전달할때는 

Authorization 헤더 인증

클라이언트 관리 인증서를 서버에 전달하는 방법

리퀘스트 보낼때 Authorization 헤더에 인증서 정보를 같이 보낸다.
-> 서버가 유저를 특정 (=인증)할 수 있게 함

브라우저가 관리해주지 않는다
개발자의 JS 코드로 읽어와서 Authorization 헤더에 붙여줘야한다.

Authorization 헤더에 값을 보내는 유형

  1. Bearer Token 방식
    Authorization: Bearer <토큰 값>
    ex. JWT
  2. Basic Auth 방식
    Authorization: Basic <base64 인코딩된 (username:password)>
  3. Custom 방식
    Authorization: certificate <인증서 값>
    ex. 특정 어플리케이션이나 API에서 요청하는 경우

클라이언트에서 인증서를 관리할 때 장점

  1. 인증서 붙일지 말지 결정할 수 있다
  2. 쿠키 탈취 위험이 적다 - 민감한 정보는 담지 말자
  3. 서로 다른 루트 도메인 사이의 인증이 가능하다 (쿠키와 반대)
더보기

잠깐 로컬스토리지와 세션 스토리지를 정리하면, 

 

로컬스토리지, 세션 스토리지는 브라우저의 웹 스토리지 API 이지만 실제 저장되는 곳은 컴퓨터의 메모리 이다.
로컬 스토리지 - 하드디스크 : 영구, 컴퓨터 꺼도 데이터 보존
세션스토리지 - RAM : 휘발, 탭(세션) 닫으면 데이터 사라짐


인증서 종류

  1. 세션 기반
  2. 토큰 기반

세션 기반 인증 - 세션 ID

: 쿠키 기반 인증
세션은 방문에 대한 기록을 저장 (IP, 최근 접속일 등.. 세션 ID )
리퀘스트에 대한 리스폰스의 Set-Cookie 헤더에 세션 id를 추가해서 전달
-> 같은 사용자가 리퀘스트를 보내면 같은 쿠키를 갖고 있기 때문에 세션 id 가 같이 옴
쿠키에 세션 id가 없다면 첫 방문

사용자가 로그인 하면 세션에 user id 를 저장 (로그인 안하면 user id = null)
세션 아이디는 만료 시간이 지나거나 로그아웃하면 만료된다

토큰 기반 인증

: 클라이언트가 관리
인증 토큰 - 유저 정보를 암호화한 문자열 = Access Token (ex. JWT)

로그인 리퀘스트를 보낼때
토큰에 유저정보 + 비밀키 로 암호화한 값을 추가
-> 이 토큰을 리스폰스 바디에 넣어서 전달한다 (Set-Cookie 헤더 X)
-> JS 코드로 토큰을 저장하고, 보낼때는 Authorization 헤더에 붙여주기
-> 서버는 비밀키로 값을 해독해서 유저를 특정하게 된다 (인증)

로그아웃 : 클라이언트에서 토큰 삭제


구분 세션 기반 인증 토큰 기반 인증
관리 주체 쿠키 (브라우저가 관리)  클라이언트가 관리
인증 방법 세션 ID Token (유저 정보 + 비밀키) 

 

이제야 헷갈리던것들이 조금 정리되는 것 같다.