Unit7 - [Backend] 인증 / 보안

예진·2022년 11월 16일
0

: 어떤 웹 사이트에 들어갔을 때, 서버가 일방적으로 클라이언트에 전달하는 작은 데이터
=> 서버에서 클라이언트에 영속성있는 데이터를 저장하는 방법 & HTTP 프로토콜의 무상태성을 보완해주는 도구

  • '쿠키를 이용한다'라는 것은 서버 -> 클라이언트의 쿠키 전송과 클라이언트 -> 서버 전송을 포함한다.
  • 서버가 클라이언트에 특정 데이터를 저장하고, 이 데이터를 다시 불러와 사용할 수 있다.
    But, 아무 때나 가능한 것이 아닌 데이터를 저장한 이후 특정 조건들이 만족되어야 가능하다.

위에서 언급한 특정 조건은 아래 코드와 같이 쿠키 옵션으로 표현할 수 있다.

'Set-Cookie':[
            'cookie=yummy', 
            'Secure=Secure; Secure',
            'HttpOnly=HttpOnly; HttpOnly',
            'Path=Path; Path=/cookie',
            'Doamin=Domain; Domain=codestates.com'
        ]

Domain

: www.google.com 과 같은 서버에 접속할 수 있는 이름
쿠키 옵션에서 도메인은 포트 및 서브 도메인 정보, 세부 경로를 포함하지 않는다.
( 만약 쿠키 옵션에서 도메인 정보가 존재한다면 클라이언트에서는 쿠키의 도메인과 서버의 도메인이 일치해야만 쿠키를 전송할 수 있다. )

ex. URL이 http://www.localhost.com:3000/users/login이면 도메인은 localhost.com이다.

Path

: 세부 경로로써 서버가 라우팅할 때 사용하는 경로
Path를 명시하지 않으면 기본적으로 /으로 설정된다.
( 설정된 경로를 포함하는 하위 경로로 요청해도 쿠키를 서버에 전송할 수 있다. )

ex. URL이 http://www.localhost.com:3000/users/login이면 세부 경로는 /users/login이다.

MaxAge or Expires

: 쿠키가 유효한 기간을 정하는 옵션 ( 유효 기간을 설정하는 것이 보안 측면에서 중요 )

- MaxAge : 쿠키가 유효한 시간을 초 단위로 설정하는 옵션

- Expires : MaxAge와 비슷하지만 언제까지 쿠키가 유효한지 심판의 날을 지정 (값은 클라이언트 시간 기준)

쿠키는 위 옵션에 따라 세션 쿠키(Session Cookie)와 영속성 쿠키(Persistent Cookie)로 나뉜다.

  • 세션 쿠키(Session Cookie) : MaxAge 또는 Expires 옵션이 없는 쿠키
    ( 브라우저가 실행 중일 때 사용할 수 있는 임시 쿠키, 브라우저 종료 시 해당 쿠키 삭제 )

  • 영속성 쿠키(Persistent Cookie) : 브라우저의 종료 여부와 상관없이 MaxAge 또는 Expires에 지정된 유효시간만큼 사용가능한 쿠키

Secure

: 사용하는 프로토콜에 따른 쿠키의 전송 여부를 결정하는 옵션
Secure 옵션이 true로 설정된 경우, HTTPS를 이용하는 경우에만 쿠키를 전송할 수 있다.

ex. http://... 또는 https://... 에 모두 쿠키를 전송할 수 있다.

HttpOnly

: 자바스크립트에서 브라우저의 쿠키에 접근 여부를 결정
해당 옵션이 true로 설정된 경우, 자바스크립트로 쿠키에 접근이 불가능하다.
옵션을 지정하지 않으면 false값이고 이때는 XSS 공격에 취약하다.

SameSite

: Cross-Origin 요청을 받은 경우, 요청에서 사용한 메소드와 해당 옵션의 조합으로 서버의 쿠키 전송 여부를 결정

  • Lax : Cross-Origin 요청이라면 GET 메소드에 대해서만 쿠키 전송 가능
  • Strict : Cross-Origin이 아닌 same-site인 경우에만 쿠키 전송 가능 (가장 엄격한 옵션)
  • None : Cross-Origin 요청에 항상 쿠키 전송 가능하지만, Secure 옵션이 필요

쿠키를 이용한 상태 유지

위 쿠키의 특성을 이용해 서버는 클라이언트에 인증정보를 담은 쿠키를 전송하고, 클라이언트는 전달받은 쿠키를 서버에 요청과 같이 전송하여 Stateless한 인터넷 연결을 Stateful하게 유지할 수 있다.

but, 기본적으로 쿠키는 오랜 시간 동안 유지될 수 있고, HttpOnly 옵션을 사용하지 않았다면 자바스크립트를 이용해 쿠키에 접근 가능하기 때문에 쿠키에 민감한 정보를 담는 것은 위험하다.


Axios

: 브라우저와 Node.js에서 사용할 수 있는 Promise 기반 HTTP 클라이언트 라이브러리

Fetch API & Axios

Axios 사용법

Axios는 써드파티 라이브러리이기 때문에 사용하기 위해서는 설치해야 한다.
npm으로 설치하기 : npm install axios
( Axios는 fetch API와 기본 원리는 같다. 공식문서 링크 참고 )

  • GET 요청 : 정보를 요청하기 위해 사용되는 메서드
axois.get("url"[,confing])

첫 번째 인자 : url 주소 ( url주소는 필수로 작성해야 한다. )
두 번째 인자 : 요청 시 사용할 수 있는 옵션들을 설정 ( 필수로 작성해야 하는 건 아니다. )

// axios는 써드파티 라이브러리이기 때문에 설치한 모듈을 불러와야 함
import axios from 'axios';

axios
	.get('https://koreanjson.com/users/1')
	.then((res) => {
  const { data } = res;  // axios는 자동으로 JSON 데이터 형식으로 변환하기 때문에 .json() 안써도 됨
})
.catch((error) => console.log(error));

HTTPS 서버 열기

서버 폴더 안에서 mkcert를 사용해 인증서를 만들어서 HTTPS 서버로 바꿔준다.

mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 ::1

2. Session

: 웹 사이트의 여러 페이지에 걸쳐 사용되는 사용자 정보를 저장하는 방법

  • 서버가 Client에 유일하고 암호화된 ID를 부여
  • 중요 데이터는 서버에서 관리

세션기반 인증 (Session-based Authentication)

- 로그인

  • 사용자가 웹 사이트에서 아이디 및 비밀번호를 이용해서 로그인을 시도한 경우,
    사용자가 정확한 아이디와 비밀번호를 입력했다면 서버는 인증(Authentication)에 성공했다고 판단한다.
  • 만약 다음번에 인증을 필요로 하는 작업을 요청할 경우,
    서버가 "해당 유저는 인증에 성공했다" 는 것을 알고 있다면, 유저가 매번 로그인 할 필요가 없다.
    ( 인증에 따라 리소스의 접근 권한(Authorization)이 달라진다. )

- 서버 : 사용자가 인증에 성공했음을 알고 있어야 한다.
- 클라이언트 : 인증 성공을 증명할 수단을 갖고 있어야 한다.

  • 사용자가 인증에 성공한 상태 : 세션(Session) => 서버는 일종의 저장소에 세션을 저장한다.
  • 세션이 만들어지면, 각 세션을 구분할 수 있는 세션 아이디도 만들어진다.
    => 보통 클라이언트에 세션 성공을 증명할 수단으로 세션 아이디를 전달한다.

웹 사이트에서 로그인을 유지하기 위한 수단으로 쿠키를 사용한다. ( 쿠키에 서버에서 발급한 세션 아이디 저장 )

쿠키를 통해 세션 아이디가 서버에 전달되고, 세션 스토어에 해당 세션이 존재한다면 서버는 해당 요청에 접근 가능하다고 판단한다. 그러나 쿠키에 세션 아이디 정보가 없는 경우 서버는 해당 요청이 인증되지 않았음을 알려준다.

- 로그아웃

세션 아이디가 담긴 쿠키는 클라이언트에 저장되어 있으며, 서버는 세션을 저장하고 있고, 세션 아이디로만 인증 여부를 판단한다.

- 서버 : 세션 정보를 삭제해야 한다.
- 클라이언트 : 쿠키를 갱신해야 한다.

서버는 클라이언트의 쿠키를 임의로 삭제할 수 없다.
대신, set-cookie 로 클라이언트에게 쿠키를 전송할 때 세션 아이디의 키 값을 무효한 값으로 갱신할 수 있다.

express-session

Node.js에는 이런 세션을 대신 관리해 주는 express-session이라는 모듈이 존재합니다.

아래 설명을 참고하여 모듈의 역할 및 사용법을 알아봅시다.

express-session은 세션을 위한 미들웨어로, express 서버에서 쉽게 세션을 위한 공간을 다룰 수 있도록 만들어줍니다.

const express = require('express');
const session = require('express-session');

const app = express();

app.use(
  session({
    secret: '@codestates',
    resave: false,
    saveUninitialized: true,
    cookie: {
      domain: 'localhost',
      path: '/',
      maxAge: 24 * 6 * 60 * 10000,
      sameSite: 'none',
      httpOnly: false,
      secure: true,
    },
  })
);

express-session를 사용해 위와 같이 세션의 옵션을 지정할 수 있습니다. 언뜻 보면 쿠키 옵션과 비슷해 보입니다. 하지만 세션의 경우 secret 옵션의 비밀키를 이용해 암호화해 세션 id라는 것을 생성합니다. 그리고 이것을 클라이언트에게 쿠키로 전송합니다.

쿠키로 전송된 세션 id는 이에 종속되는 고유한 세션 객체를 가지며 이는 서버에 저장됩니다. 이때 세션 객체는 유저별로 독립적으로 생성된 객체이므로 유저별로 각각 다른 데이터를 저장할 수 있습니다.

따라서 클라이언트에 유저의 개인정보를 담지 않고도 서버가 클라이언트의 세션 id를 이용해 유저의 인증여부를 판단할 수 있습니다.

세션 객체는 req.session으로 접근할 수 있으며 앞서 말했듯 이를 통해 세션에 임의의 데이터를 저장하거나 불러올 수 있습니다.

이 세션 객체에 값을 담거나, 값을 불러오는 법, 세션을 파괴하는 법은 다음 문서를 참고해 보세요.
GitHub: express-session

🔥 Token

1. Hashing

2. Token


🔥 OAuth


profile
😊

0개의 댓글