인증/보안 - hashing, token

jeongjwon·2023년 5월 3일
0

SEB FE

목록 보기
46/56

Hashing

해시함수(항상 같은 길이의 문자열 리턴, 서로 다른 문자열에 동일한 해시 함수를 사용 시 반드시 다른 결과값, 동일한 문자열에 동일한 해시함수 사용 시 항상 같은 결과값)를 사용하여 암호화를 진행하는 방식이다. 해시함수는 레인보우 테이블를 이용하여 이전의 값을 알아낼 수 있도록 한다. 레인보우 테이블을 때문에 데이터 유출 가능성이 있어 보안상 위협이 될 수 있다. 이때, 솔트라는 임의 값을 더하여 해싱 이전의 값을 알아내기 힘들게 많드는 방법을 사용한다.

해시함수는 레인보울 테이블과 솔트를 이용하여 불가역(단방향)한 성질을 가지는데, 바로 해싱의 목적이 동일한 데이터읹 아닌지에 대한 여부만 확인하는 것이기 때문에 복호화가 불가능한 암호화방식을 사용한다.



Token

✅ 인증과 권한 정보를 담고 있는 암호화된 문자열로 사용자에게 접근 권한을 부여할 수 있다.


토큰 인증 방식

  • 세션 기반 인증이 가지고 있는 한계 극복 (서버에서 유저의 상태를 관리 ➡️ 서버에 부담)
  • 클라이언트에서 사용자 인증 상태를 저장 ➡️ 서버의 부하나 메모리 부족 문제 감소

  1. 사용자가 인증 정보를 담아 서버에 로그인 요청을 한다.
  2. 서버는 데이터베이스에 저장된 사용자의 인증 정보를 확인한다.
  3. 인증에 성공하면 해당 사용자의 인증 및 권한 정보를 서버의 비밀키와 함께 토큰으로 암호화한다.
  4. 생성된 토큰을 Authorization 헤더를 사용하거나 쿠키를 이용하여 클라이언트에 전달한다.
  5. 클라이언트는 전달받은 토큰을 Local Storage 나 Session Storage, Cookie 등에 저장한다.
  6. 클라이언트는 서버에 리소스를 요청할 때 Authorization 헤더를 사용하거나 쿠키를 이용하여 토큰을 서버에 전달한다.
  7. 서버는 전달받은 토큰이 유효한지의 여부를 서버의 비밀 키를 통해 검증한다.
  8. 토큰이 유효하면 클라이언트의 요청에 대한 응답 데이터를 전송한다.



JWT (JSON Web Token)

  • 토큰 기반 인증 구현을 대표하며 JSON 객체를 정보(Payload)를 담아 토큰으로 암호화하여 전송할 수 있는 기술
  • 클라이언트가 서버에 요청을 보낼 때 , 인증정보를 암호화된 JWT 토큰으로 제공하고, 서버는 이 토큰을 유효 검증하여 인증정보를 확인할 수 있다.

  • Header : 토큰 설명(토큰 종류, 시그니처 생성 시 사용할 알고리즘) ➡️ JSON 형태에서 base64로 인코딩
  • Payload : 전달하려고 하는 데이터 정보 (접근 가능한 권한, 개인 정보, 발급시간, 만료 시간) ➡️ JSON 형태에서 base64로 인코딩
  • Signature : 토큰의 무결성 확인, 서버의 비밀키와 Header에서 지정한 알고리즘을 사용하여 해싱



토큰 인증 방식의 장단점

장점단점
① 무상태성 : 서버가 유저의 인증 상태를 관리하지 않고 비밀키를 통해 토큰의 유효 검증만 하기 때문에① 무상태성 : 서버가 인증상태를 관리하는 주체가 아니라, 토큰이 탈취되면 강제로 만료 시킬 수 없다
② 확장성 : 다수의 서버가 공통된 세션 데이터를 가질 필요가 없기 때문에② 유효기간 : 탈취 상황을 대비해 유효기간을 짧게 설정하면 로그인을 매번해야 해서 사용자 경험 감소, 길게 설정하면 탈취 시 위험
③ 어디서나 토큰 생성 가능 : 토큰의 생성과 검증이 꼭 하나의 서버에서 이루어질 필요가 없기 때문에③ 토큰의 크기 : 많은 데이터를 담으면 암호화 과정도 길어지고 토큰의 크기도 커져 네트워크 비용문제 발생
④ 권한 부여에 용이 : 토큰에 인증상태나 접근 권한 등의 다양한 정보를 담을 수 있기 때문에



Access Token + Refresh Token - 유효 기간 극복

✅ 액세스 토큰 : 사용자가 서버 리소스에 접근할 수 있도록 접근 권한을 제공하는 토큰으로 보안을 위해 만료 주기가 짧다.

✅ 리프레시 토큰 : 토큰의 짧은 만료 주기로 인해 사용자 경험 하락을 막기 위해 고안된 토큰으로 기존에 발급받은 액세스 토큰이 만료되었을 때 액세스 토큰을 얻기 위해 사용한다.

  • 리프레시 토큰이 모든 문제를 해결하지는 않지만 액세스토큰보다는 긴 유효기간을 가지고 있기 때문에 이 토큰 마저 탈취 당할 수 있다.



    [과제]

  1. 사용자가 ID, PW를 통해 로그인

  2. 서버에서는 회원 DB에서 값을 비교한다.(보통 PW는 일반적으로 암호화해서 들어간다.)

  3. 사용자 인증이 되면 서버에서 Access Token, Refresh Token을 발급, 보통 회원 DB에 Refresh Token을 저장해준다.

  4. 서버는 사용자에게 Access Token, Refresh Token 을 보낸다.

  5. 사용자는 Refresh Tokendms 은 안전한 저장소에 저장 후, Access Token을 헤더에 실어 요청을 보낸다.

  6. 서버는 Access Token을 검증하고 로그인 성공 신호를 보낸다.

  7. 로그인 성공 신호에 맞는 데이터를 사용자에게 보내준다.

    ~ 시간이 흘러 Access Tokendl 만료 ~

  8. 사용자는 만료된 Access Token을 헤더에 실어 요청을 보낸다.

  9. 서버는 Access Token이 만료된을 확인한다.

  10. 만료된 토큰임을 알리고 권한없음을 신호로 보낸다. Access Token이 만료될때 마다 9~11 과정을 거칠 필요는 없다. Access Token의 Payload를 통해 유효기간을 알수 있다. 따라서 프론트엔드 단에서 API 요청 전에 토큰이 만료 됐다면 바로 재발급 요청 가능.

  11. 사용자는 Refresh Token과 Access Token을 함께 서버로 보낸다.

  12. 서버는 받은 Access Token이 조작되지 않았는지 확인한후, Refresh Token과 사용자의 DB에 저장되어 있던 Refresh Token을 비교한다.

  13. 서버는 Token이 동일하고 유효기간도 지나지 않았다면 새로운 Access Token을 사용자에게 보내준다. 새로운 Access Token을 헤더에 실어 API 요청을 한다.



[기능 구현]

🧩 login.js

  1. 입력한 정보(아이디와 패스워드)가 DB 정보와 일치하는 경우 클라이언트에게 로그인 성공에 대한 응답 전송 + 쿠키에 JWT 담아 전송 ( 302 , /userInfo 로 리다이렉트 )
  • 로그인 유지 체크시 -> access token & refresh token(영속성 쿠키)
  • 로그인 유지 노 체크시 -> access token(세션 쿠키)
  1. 일치하지 않는 경우 로그인 실패에 대한 응답 전송 ( 401 , Not Authorized )

🧩 userinfo.js

토큰 검증
1. access token 검증이 성공하면 payload 를 통해 DB 에 유저 정보를 조회
1-1. 조회가 된다면 로그인 성공에 대한 응답 + 비밀번호를 삭제하고 유저 정보 전송
1-2. 조회가 되지 않는다면 로그인 실패에 대한 응답 전송 ( 401, Not Authorized )
2. access token 검증이 실패(=만료)되었다면 refresh toekn 검증하기
2-1. refresh token 검증이 실패하면 로그인 실패에 대한 응답 전송 ( 401, Not Authorized )
2-2. 검증 성공하면 DB 에 유저 정보를 조회
2-3. 조회 된다면 access token 재발급 + 쿠키에 JWT 다시 담아 전송 ( /userInfo 로 리다이렉트 )
2-4. 조회 되지 않는다면 로그인 실패에 대한 응답 전송 ( 401, Not Authorized )
3. access token, refresh token 검증 실패시 로그인 실패에 대한 응답 전송 ( 401, Not Authorized )

🧩 logout.js

쿠키 삭제 ➡️ 기본적으로 access token 삭제, refresh token 존재한다면 이것도 삭제

로직

  1. OPTIONS /login CORS 요청
  2. POST /login
  • 로그인 성공 : 302 ➡️ redirect(/userinfo)
    • 로그인 유지 체크시 access token + refresh token 전송
    • 로그인 유지 노 체크시 access token 만 전송
  • 로그인 실패 : 401 Not Authorized
  1. OPTIONS /userinfo CORS 요청
  2. GET /userinfo 304 로그인된 상태로 브라우저 새로고침 및 재접속 시 여기부터 시작
  • access token 검증
    • 검증 성공 후 DB 정보 대조
      • 정보 대조 성공시 GET 요청 성공
      • 정보 대조 실패시 로그인 실패 : 401 Not Authorized
  • access token 검증 실패 + refresh token 검증
    • 검증 성공 후 DB 정보 대조
      • 정보 대조 성공시 새로운 access token 재발급 후 쿠키로 전달 ➡️ redirect(/userinfo)
      • 정보 대조 실패시 로그인 실패 : 401 Not Authorized
  • access token 검증 실패 + refresh token 검증 실패시 로그인 실패 : 401 Not Authorized
  1. POST /logout 205
  • access token 과 refresh token 포함하는 쿠키 삭제 ➡️ 즉시 로그아웃 상태

0개의 댓글