프로그래밍 공부/컴퓨터공학 기초

인증(Authentication)과 인가(Authorization)란 무엇인가?

Wonuk 2022. 1. 17. 23:31
반응형

용어정리

'인증'이란?

식별가능한 정보로 서비스에 등록된 유저의 신원을 입증하는 과정입니다.

 

예) 출입증으로 건물에 출입 할 수 있습니다.

 

'인가'란?

인증된 사용자에 대한 자원 접근 권한 확인입니다.

 

예) 출입증으로 건물에 출입한 후 자신의 회사에만 갈 수 있는것

(3층이 자신의 회사이고 4층이 다른 회사라면 3층에만 입장가능)

 


웹에서의 인증과 인가

간단한 게시판이 있다고 가정해봅시다.

해당 게시판에 글을 쓰고싶다면 회원가입, 로그인 과정을 거칩니다. -> 인증

이와 동시에 글을 쓸 수 있는 권한 획득합니다. -> 인가 포함

 

뿐만 아니라 다른 사람의 글을 읽을 수 있지만

다른 사람의 글을 수정할 수 없습니다. -> 권한이 없기 때문입니다.(인가)

 

정리

인증과 인가는 자원을 적절한/유효한 사용자에게 전달/공개 하기 위한 방법

자원
인터넷 강의, 건물에 회사가 위치 하고있는 층
혹은 글을쓰는 기능이나 글을 삭제하는 기능과같은 자원

이렇게 인증과 인가는 실생활에서도 쓰이는 개념입니다.


인증방법

인가는 인증보다 나중에 나온 개념입니다.

그렇기 때문에 선행되어야 하는것은 인증이 됩니다.

사전지식

클라이언트 - 서버 개념

클라이언트와 서버는 HTTP로 서로 통신합니다.

무상태성(Stateless)

서버는 클라이언트에서 보낸 첫번째 요청과

다음 요청에 대한 연관관계가 없다고 생각하고

요청을 받고 처리를 하게됩니다.

 

1. 인증하기

로그인하기로 생각하면 됩니다.

Request Header를 통해 간단하게 로그인하는 방식으로 진행합니다.

 

Request Header 활용하기

사용자 = 클라이언트

서버 = www.cocktailpick.com

db = 회원가입된 유저가 존재하는 상태 [ID : user, PW : 1q2w3e!]

이 상황에서 www.cocktailpick.com/login  url로 접근하면 login 요청을 보낼 수 있습니다.

ID와 PW를 user:1q2w3e!@www.cocktailpick.com/login 앞에 적어주기만 해도 

API 구축되어 있는 상황이라면 자동으로 로그인 요청이 됩니다.

 

user:1q2w3e!@www.cocktailpick.com/login은 브라우저에서 처리합니다.

 

들어온 url을 Base64라는 인코더를 통해 인코딩을 한 후에 전달하는 방식입니다.

url에서 user:1q2w3e! 부분을 파싱한 다음 인코더를 통해서 인코딩한 문자열을

가지게 됩니다.

그 후 요청 헤더 Authorization에 넣어서 전송하는 개념입니다.

실제로 HTTP로 전송하여 Server가 DB Checking을 하고 

DB에 실제로 값이 있으면 OK 사인을 해줍니다.

여기까지가 기본적인 로그인 상황입니다.

 

로그인을 했지만 여기서 문제점이 하나 발생합니다.

사용자가 매번 로그인을 계속 해주어야 합니다.

 

예를들어, 글을 쓸때 사용자가 로그인을 했고

수정을 하고싶은 상황에서 다시 한번 인증요청을 해야합니다.

지금과같은 상황이라면 매번 인증해야 합니다.

 

이 부분을 해결하기 위해서 Browser의 힘을 빌립니다.

 

 

2. 인증 유지하기

Browser를 사용하여 유지하는 방식으로 진행합니다.

 

Browser 활용하기

정확히 표현하면 Browser의 스토리지를 사용합니다.

스토리지는 Local, Session, cookie가 될 수 있지만

cookie로 설명하겠습니다.

 

간단하게 cookie에 ID와 PW를 집어넣습니다.

사용자가 인증이 필요한 요청을 할 때 같이 넣어서 보내줍니다.

Server -> DB를 거쳐 체크가되면 원하는 요청을 받을 수 있습니다.

사용자 입장에서 편리해집니다.

하지만 이방법은 해커입장에서도 편리한 방법입니다.

왜냐하면 스토리지에 사용자의 정보가 노출되어 있어서 쉽게 가져갈 수 있고

클라이언트는 서버보다 상대적으로 보안에 취약합니다.

 

이러한 보안적인 단점 두가지를 해결하기 위해서

Server를 활용합니다.

 

 

3. 안전하게 인증하기 

Server를 통해 수행합니다.

 

Session 활용하기

처음에는 이전(1번)과같이 로그인 요청을 보냅니다.

보낸 요청을 바탕으로 DB까지 검증을 완료합니다.

 

아까와 같은 상황이라면 원하는 자원을 

바로 클라이언트에 제공해야 합니다.

 

하지만 그러지 않고 Session이라는 개념이 도입됩니다.

Session은 인증된 사용자의 식별자(ID)와

랜덤한 문자열로 Session ID를 만들어서 

이를 응답 헤더로 넘겨주고

클라이언트가 저장할 수 있도록 만들어줍니다.

이렇게되면 클라이언트 쪽에서 사용자의 low한 데이터를 가지고있지 않기때문에

해커가 정보를 탈취하더라도 크게 위험하지 않습니다.

또한, Session에 만료기간을 정할 수 있기때문에

만료기간이 지난다면 아무리 해커가 가져가도 유효하지 않게됩니다.

 

Session의 관리는 Server에서 하기때문에 탈취된 Session을 Server에서 삭제한다면

Session 자체를 이용하지 못하게 됩니다.

 

하지만 이것또한 문제점이 있습니다.

서비스 이용자가 많아짐에 따라 Server의 개수가 증가한다면

로드 밸런서가 생깁니다.

이 상황에서 요청을 보내면 다음과같은 그림으로 이루어집니다.

한번 인증하여 Session을 받았을 때 다음 요청은 Session만 이용해서 요청합니다.

즉, DB까지 요청이 도달할 필요가 없다는 이야기입니다.

 

이상황에서 유저가 두번째 인증이 필요한 요청을 하게됩니다.

그런데 이번엔 로드밸런서가 세번째 서버가 아니라

두번째 서버로 요청을 전달하게 됩니다.

세번째 서버에만 Session ID 값이 있기때문에 인증이 실패합니다.

 

이런 문제가 발생하는 이유는

서버 하나하나 자체에서 Session을 관리하여 생기는 문제입니다.

 

이러한 문제는 세션 스토리지 라는것으로 해결할 수 있습니다.

서버들에 있는 모든 세션들을 한곳에서 관리하자는 취지입니다.

이렇게되면 로드밸런서가 요청을 분산하여도 결국엔

한곳을 바라보기 때문에 문제를 해결할 수 있습니다.

그런데 이곳에도 문제가 있습니다.

만약 클라이언트가 너무 많아진다면?

스토리지가 감당하지 못하게되는 문제가 발생합니다.

 

여기까지 클라이언트, 서버, 세션 저장소 세곳 모두 사용했지만

모두 문제가 발생했습니다.

 

그 이유는 HTTP 통신과 서버 자체가 지향하는 RestAPI가

무상태성을 기초로하기 때문입니다.

 

하지만 실제로 인증과 인가를 구현할 때는

사용자의 정보, 상태를 각자 가지고있게 됩니다.

즉, 상태성을 가지고 있다는 의미입니다.

 

두 패러다임이 충돌하고 있기때문에

이 패러다임을 해소해야 문제가 해결됩니다.

 

여기까지 클라이언트와, 서버 모두에게 

사용자의 상태를 맡겨보았습니다.

그럼 이제 남은것은 화살표에 해당하는것 뿐입니다.

이것은 화살표지만 사실은 정보의 흐름을 나타냅니다.

정보의 요청과 응답 안에 사용자의 상태를 담아보자,

그것으로만 사용자의 인증과 인가를 처리하자는 방법이 TOKEN입니다.

4. 효율적으로 인증하기

Token을 활용할 예정입니다.

 

JWT 활용하기

시큐리티를 사용해서 JWT를 만들어 냅니다.

그리고 시큐리티를 사용해서 JWT에 인증과정을 거칩니다.

 

JWT 자체는 해독하기가 무척 쉽습니다.

그래서 JWT안에는 민감한 정보를 담지 않습니다. ex) 비밀번호

 

그리고 이 시큐리티가 중요한만큼 노출되면 JWT도 노출됩니다.

그래서 TOKEN을 위해 시큐리티를 서버 내부에 잘 관리해야 합니다.

 

먼저 요청을 보내고 DB와 체킹합니다.

이전의 경우 세션 스토리지와 연결되었지만

시큐리티를 이용하여 토큰을 만들어냅니다.

그리고 그것을 헤더에 넣고 이후의 요청부터는

헤더에 있는 키를 이용하여 요청을 보내고 응답을 받게됩니다.

 

토큰이 클라이언트로부터 서버로 넘어갑니다.(요청)

그렇게되면 서버는 토큰의 유효성 검사를

본인이 가진 시큐리티로 진행합니다.

유효하지 않다면 버리고

유효하다면 다음 단계인 사용자 정보를 파악합니다.

 

JWT는 디코딩하기 쉽습니다.

토큰의 사용자 정보중에 이름이 있습니다.

그 이름으로 어떤 유저인지 찾아냅니다.

 

토큰에 만료시기가 있습니다.

유효한 토큰인지, 어떠한 사용자인지 알게되겠지만

이미 만료된 토큰이라면 사용하지 못하게 됩니다.

 

토큰에 권한 정보가 있습니다.

이 사용자는 Admin인지 여부또한 토큰하나로

확인할 수 있게됩니다.

 

하지만 비밀번호같은 민감한 정보는 담으면 안됩니다.

왜냐하면 디코딩이 쉬워 노출될 위험이 있기 때문입니다.

 

시큐리티를 통해서 유효성 검사를 통과한 토큰은

인증을 받은 토큰이라는 의미입니다.

 

JWT 활용하기 - 장점

서버가 여러대가 있는 상태에서

세션의 경우 세션 DB를 따로 두어 세션 DB와 연관성이 있었지만

이제는 로드밸런서가 분산한 요청들을 각자 자신이 가진 시크릿 키로

해독하여 인증을 진행하고 요청을 반환하면 됩니다.

이러한 장점은 더 나아가서 현대의 서버시스템에 중요한 확장성과도 연결됩니다.

세대였던 서버가 다섯대가 되어도 같은 방식으로 진행이 가능합니다.

 

토큰 활용하기 - 단점

Access Token이 해커에 의해 탈취당하면

해커는 사용자와 똑같은 지위를 가지고

원하는 자원에 접근이 가능해집니다.

 

이를 막기위해서 우리는 만료기한을 정합니다.

만료기한이 지나게되면 사용자, 해커 모두가 사용할 수 없게됩니다.

사용자 입장에서 조금 불편해지게 됩니다.

 

그래서 나온 개념이 Refresh Token입니다.

 

 

토큰 활용하기 - Refresh Token

이전과 같이 로그인 요청을 보냅니다.

보낸 로그인 요청에 따라서 시큐리티를 통해

토큰을 만들어냅니다.

 

이때 서버는 Access Token과 Refresh Token을 한번에 만들어냅니다.

그리고 Access Token은 저장하지 않고 

Refresh Token만 따로 저장소에 저장하게 됩니다.

그리고 Access Token과 Refresh Token을 한번에 응답의 헤더로 보내서

클라이언트가 둘다 저장하게 됩니다.

이후 요청부터는 Access Token을 사용하여 요청을 보내게됩니다.

 

Access Token이 만료된 경우라면?

14:18에 Token들을 받았는데 시간이 흘러

Access Token이 만료되었습니다.

 

사용자는 만료되었다는 사실을 모르고 알 필요도 없습니다.

그래서 그냥 요청을 보내게됩니다.

그때 서버는 토큰이 만료되었다고 알려줍니다.

이때 브라우저에서 자동으로 Access Token과 Refresh Token을 함께

다시 서버로 전송하고 서버는 돌아온 Refresh Token을 참고해서

일치한다면 새로 갱신한 Access Token을 반환합니다.

이렇게되면 클라이언트단 에서도 업데이트된 Access Token을

사용할 수 있게됩니다.

 

토근 활용하기 - 핵심

1. 토큰으로 상태관리를 하기에 따로 세션을 둘 필요가 없다.

효율성이 좋아지고 DB까지 갈필요가 없기 때문에 속도가 빠릅니다.

 

2. 토큰 관리를 해야한다. 결국 토큰도 탈취당할 수 있다.

보안에 대해 꾸준히 신경을 써야합니다.

-> 해결법 OAuth

5. 다른 채널을 통해 인증하기

OAuth 개념 -> 이부분은 다른 포스팅에 다루도록 하겠습니다.

생활코딩 OAuth 강의 or 테코톡 강의 참조

 

더 알아볼 내용

보안 

 

JWT

 

OAUTH

 

인증서버

 

HTTPONLY

서버에서 클라이언트로 정보를 보낼때 

보낸 정보에 달아주는 옵션입니다.

이렇게되면 스토리지에 저장된 정보를

아무나 접근할 수 없게됩니다.

 

Sliding Session

Refresh Token

위 두가지는 상호보완적인 관계입니다.

Refresh Token에 대한 이슈들이 많습니다.

 

SSL / TLS1.3

가장 접근하기 쉽고 가성비 좋은 보안방법 입니다.

HTTPS 사용

 

해킹방법

 


토큰은 어떤 부분에서 세션보다 메모리 부담에 적어지나요?

세션은 서버에 데이터를 관리하고 쿠키로 세션ID를 주고받는다면,

토큰은 주고받는 토큰자체에 데이터를 포함하고 있기에

서버 메모리에 따로 저장할 필요가 없습니다.

 

토큰은 서버입장에서는 따로 관리할 상태가 없어 세션보다 부담이 적저만,

그만큼 주고받는 토큰이 크기가 커서 네트워크비용이 증가하고

아무리 암호화 되었다한들 토큰자체를 탈취되면 안된다는 단점이있습니다.

 


출처

테코톡 - 토니의 인증과 인가

https://www.youtube.com/watch?v=y0xMXlOAfss

 

 

 

 

 

 

 

 

반응형

'프로그래밍 공부 > 컴퓨터공학 기초' 카테고리의 다른 글

Web Socket이란?  (0) 2022.01.25
쿠키(Cookie), 세션(Session), 토큰(Token)  (0) 2022.01.18
TCP/IP, 3, 4Way HandShaking  (0) 2022.01.06
Process와 Thread  (0) 2022.01.05
XML, JSON, YAML이 무엇인가?  (0) 2021.12.19