개발기록장

[Web] 인증을 유지시키는 여러가지 방법 본문

TIL/Web

[Web] 인증을 유지시키는 여러가지 방법

yangahh 2021. 2. 21. 21:42

HTTT의 stateless 특성 : 서버는 클라이언트기 보낸 요청과 이 다음 요청에 대한 연관관계가 없다고 생각하고 요청을 받고 처리한다.

 

1. 인증하기 (= 로그인) : Request Headers를 통해

2. 인증 유지하기 : Browser를 통해 유지

3. 안전하게 인증하기 : Server를 통해 수행

4. 효율적으로 인증하기 : Token 활용

5. 다른 채널을 통해 인증하기 : OAuth 개념

 

 

1. 요청이 들어온 url을 Base64라는 인코더를 이용해서 인코딩을 한 후에 http request를 전달 (이 부분은 클라이언트. 즉, 브라우저가 한다)

url에서 로그인에 관한 부분을  파싱한 후에 인코더를 통해서 인코딩한 문자열을 가지고 있음(브라우저가).

이를 request header의 Authorization에 넣어서 보내주는 개념.

이렇게 브라우저가 http를 통해 서버로 날려주면 서버에서는 DB 체킹을하고 일치여부를 판다.

 

2. http는 stateless하기 때문에 로그인이 필요한 서비스는 매번 인증을 해줘야하는 상황이 발생. (1번 상황 반복)

이를 해결하기 위해 Browser의 스토리지를 이용. 스토리지는 로컬스토리지, 세션스토리지, 쿠키가 있다. 

쿠키로 설명을 하자면, 쿠키에 사용자 id, pw를 집어 넣어서 사용자가 인증이 필요한 요청을 할 때 이 쿠키를 같이 넣어서 보내준다.

그러면 DB 체킹이 되어 원하는 자원을 받을 수 있게 된다.

사용자 입장에서 편리하지만, 보안에 취약. 스토리지에 사용자 정보가 raw하게 노출되어 있기 때문. 그리고 클라이언트가 서버보다 상대적으로 보안에 취약하다는 단점도 있다.

 

3. 2번의 단점(보안)을 해결하기 위해서 서버를 통해 인증을 수행.

http request header로 로그인 요청을 보내면 원하는 자원을 바로 클라이언트로 보내줬다면, 이번에는 세션이라는 개념을 보낸다.

세션은 인증된 사용자의 식별자(pk 등)와 랜덤한 문자열로 '세션 id'를 만들어서 이를 response header로 넘겨주고 이를 클라이언트가 저장할 수 있도록 한다. (DB에서 체킹 -> 서버로 {session id : 사용자 식별자}를 응답 해더로 보냄. 클라이언트측에서는 {id: session id} 를 저장)

이 방법의 장점은, 클라이언트가 사용자의 raw한 데이터를 가지고 있지 않기 때문에 해커가 정보를 가져가더라도 크게 위험이 없다는 것과, 세션의 만료기간을 지정할 수 있다는 것이다. 만료가 지난 세션은 해커가 가져가더라도 유효하지 않은 정보가 됨.

그리고 세션 관리를 서버 자체에서 하기때문에 만일에 탈취가 된 세션을 서버에서 삭제해버리면 이 세션 자체를 이용하지 못하게 됨.

 

하지만 단점은, 로드밸런서를 이용해서 서버를 여러 대 두는 상황에서는 처음 인증을 처리했던 한 대의 서버에서만 그 사용자에 대한 세션정보를 가지고 있기 때문에 다음 요청에서 그 서버로 요청이 오지 않는다면 문제가 발생하게 된다. 

이 문제는 별도의 세션 스토리지를 사용함으로써 해결할 수 있다. 각 서버들에 있는 모든 세션들을 한 곳에서 관리하는 것이다. 세션 스토리지를 사용하게 되면 로드밸런서가 어떤 서버로 요청을 보내더라도 결국에는 모두 하나의 세션 스트로지로 요청이 들어오기 때문에 문제를 피할 수 있다.

그러나 클라이언트가 많아진다면 세션 스토리지가 터진다는 문제도 있다. (애초에 로드밸런싱을 쓰는 문제가 서버 분산을 위한 것인데 세션 스토리지를 쓰면 결국에는 한 스토리지가 요청을 다 받아야 하므로 로드밸런서를 쓰는 의미가 없어짐...)

 

4. 2, 3번에서 각각 클라이언트, 서버, 세션 스토리지(세션 저장소)에서 모두 한 번씩 사용자의 정보를 관리할 수 있게 했더니 문제가 발생했다. 이유는 클라이언트, 서버, 세션스토리지가 통신할 때 사용하는 http와 서버 자체가 지향하는 rest api가 무상태성을 기초로 하기 때문.

하지만 인증/인가를 할 때는 사용자의 정보, 사용자의 상태를 가지고 있어야 함. 그 말은 상태성을 가지고 있다는 의미. 두 개념이 충돌.

이번에는 클라이언트, 서버에 사용자 정보를 저장하는게 아닌 http 요청과 응답 안에 사용자 상태를 담아보자. 이걸로 사용자의 인증/인가를 처리하는게 토큰을 활용한 인증 인가 방식이다.

토큰 중에 JSON Web Token을 사용할 것이다. JWT는 시크릿 키를 이용해서 만든다. JWT 자체는 해독하기가 쉽다. 그래서 JWT내에는 민감한 정보(비밀번호 등)를 담지 않는다. JWT 보안에 중요한 것은 시크릿키이다. 따라서 시크릿 키가 노출이 안되게 하는 것이 중요하기 때문에 시크릿 키를 서버 내부에 잘 관리해야 한다.

토큰을 이용한 인증 프로세스는 아래와 같다.

사용자가 로그인 요청을 보냄 -> DB체킹 해서 일치하면 시크릿 키를 이용해서 토큰을 만들어냄 ->응답 헤더에 넣어서 보내면 클라이언트가 이이 엑세스 토큰을 저장해두고, 다음부터는 이 키(토큰)를 이용해서 요청을 보내고 응답을 받는 형태.

 

토큰을 발급 받은 이후(인가)

클라이언트는 서버에 토큰이 담긴 요청을 보냄. 서버는 이 토큰에 대한 유효성 검사를 본인이 가지고 있는 시크릿 키로 진행. 유효하지 않으면 버리고 유효하면 사용자 정보(사용자 이름, 토튼 만료시기, 권한 등)를 파악.

 

장점: 로드밸런서를 이용한 서버에서도 문제가 없음. 각 서버에서 시크릿 키만 가지고 있으면 되기때문. 서버가 확장되더라도(여러대가 추가되더라도) 문제가 없음. 각자 해독을 해서 인증을 하면됨

단점: 보안문제. 이를 위해 만료기간을 정해둠. 보안 문제를 줄일 수 있지만 사용자의 불편함은 증가됨. 이를 보완하기 위해 나온게 '리프레쉬 토큰' 개념이다.

리프레쉬 토큰은 엑세스 토큰을 발급했던 방법과 동일하게 진행되며 기존에는 인증된 사용자에 대해 엑세스 토큰만 발급을 했다면 이번에는 엑세스 토큰과 리프레쉬 토큰을 동시에 발급하여 엑세스 토큰은 저장하지 않고 리프레쉬 토큰만 따로 저장소에 저장을 함.(refresh token, expire time을 저장) 그리고 이 두 토큰을 한번에 응답 해더에 보내서 클라이언트가 둘 다 저장(인증 시 최초 한 번). 

클라이언트는 요청을 보낼 때 엑세스토큰을 담에서 보낸다. 만약 이 토큰이 만료가 되었다면, 서버에서 만료된 토큰임을 알려주고 브라우저에서 자동을 엑세스 토큰과 리스레쉬 토큰을 함께 서버로 다시 보낸다. 서버는 이때 리프레쉬 토큰을 참고해서 DB를 찔러서 이게 가지고 있는 리프레쉬 토큰 정보와 일치한다면 새로 access토큰을 발급해서 클라이언트에 보내고 클라이언트는 엑세스 토큰을 업데이트하여 저장한다.

이 단계에서 사용자는 이 토큰이 만료되었다는 것을 모르고 알 필요도 없다.

 

정리

- 토큰으로 상태관리를 하기에 따로 세션을 둘 필요가 없다. 효율성이 좋아지고 DB를 찔러도 되지 않기 때문에 속도가 빠르다는 장점이 있다.

- 토큰 관리를 해야한다. 결국 토큰도 탈취당할 수 있다. 보안에 신경을 써야한다.

 

 

5. OAuth

OAuth란? 다른 웹사이트 상의 자신들의 정보에 대해 접근 권한을 부여할 수 있는 공통적인 수단.

구글 로그인, 페이스북 로그인, 카카오 로그인, 깃허브 로그인 등 이런 로그인들이 사용하는 인증절차가 OAuth이다.

 

OAuth 2.0 : Authorization Code Grant. 클라이언트가 다른 사용자 대신 특정 리소스에 접근을 요청할 때 사용

 

 

OAuth 1.0과 2.0 차이점

- 인증 절차 간소화 

- 용어 변경

- 다양한 인증 방식 제공 : Authorization Code Grant, Implicit Grant, Resource Owner Password Credentials Grant 등등

 

장점 :  사용자는 이용하고자 하는 서비스에 ID/PW를 알려주지 않아도 됨. 원할 때 엑세스 토큰의 권한 취소가 가능.

서비스 측에서는 유저의 엑세스 토큰만 가지고 있으면되고, 사용자의

ID/PW를 몰라도 허가 받은 API로 접근 가능

 

 

참고 : www.youtube.com/watch?v=y0xMXlOAfss&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9CTech