질문과 답변

OAuth 2 Simplified

https://aaronparecki.com/oauth-2-simplified/

roles

  • client - the third party application. 유저의 account에 대한 액세스 권한을 얻고자 한다.

  • resource server - the api. 유저의 정보에 접근하는데 사용한다.

  • the authorization server - 유저가 요청을 허가하거나 거절하는데 대한 인터페이스를 제공하는 서버.

  • resource owner - the user. the person who is giving access to some portion of their account.

creating an app

  • 먼저 새로운 앱을 등록해야 한다.

  • application name, website, logo 등의 기본 정보를 등록한다.

  • redirect uri를 등록하여, 유저를 redirect할 수 있게 한다.

redirect URIs

  • HTTP redirect URI는 https 로 서빙되어야 한다. 이로서 authorization process 중간에 토큰이 탈취되는 것을 막는다.

  • native app은 custom URL scheme을 등록하여야 한다. demoapp://redirect 같이 생겼다.

client ID and secret

  • 앱을 등록하면, 앱에 대한 client ID를 받는다.

  • client id는 public information으로 취급된다. login URL이나 javascript source code에 넣을 수 있다.

  • client secret 은 절대 공개되어선 안된다. 만일 SPA처럼 secret을 저장할 수 없는 환경이라면 이걸 제공해선 안된다.

authorization

  • oauth2는 여러개의 grant types를 제공한다. 각 타입은 다양한 use case에 따라 구분된다.

  • authorization code - web server, browser-based, mobile apps 등에 사용.

  • password - username, password로 로그인할때 사용. first party app일 경우만.

  • client credentials - user없이 application access할 수 있게 하기 위함.

  • implicit - secret 없는 client를 위해 권장되었으나,authorization code grant with PKCE를 활용하는 것으로 대체됨.

web server apps

  • oauth server와 작업할때 가장 많이 만나는 타입이 web server.

  • 이 web app은 server-side language로 작성되어 있으며, public에 공개되지 않은 server code로 동작한다.

  • 이말은 authorization server와 통신할 때 client secret 을 활용할 수 있다는 것.

  • 이는 많은 attack vectors를 피할 수 있다는 의미.

    • attack vectors - 해커가 컴퓨터나 네트워크 서버에 액세스를 얻을 수 있는 path나 수단.

authorization

  • login link를 만들어 유저에게 제공해 주어야 한다.

  • [https://authorization-server.com/auth?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=photos&state=1234zyx](https://authorization-server.com/auth?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=photos&state=1234zyx) 로 유저를 보내면, 유저는 authorization prompt로 리다이렉트하게 됨.

  • response_type=code - 서버가 authorizsation code를 받기를 기대한다는 의미.

  • client_id - application을 만들 때 받은 client_id.

  • redirect_uri - authorization이 완료되었을 때 redirect 하는 주소.

  • scope - 유저 계정의 어떤 부분에 액세스할지를 나타냄.

  • state - 추후 앱에서 검증할 random string.

  • 이 이후에 유저는 authorization prompt를 보게 된다.

  • 유저가 id, password 를 입력하는 등 해서 해당 앱의 access를 허가하면, 서비스는 authorization code와 함께 유저를 redirect 하게 된다.

  • [https://example-app.com/cb?code=AUTH_CODE_HERE&state=1234zyx](https://example-app.com/cb?code=AUTH_CODE_HERE&state=1234zyx) 로, code, state로 요청이 오게 된다.

  • 우선, state를 비교하여 이 state가 인증을 시작한 게 맞는지를 체크한다.

  • 이 state 값은 cookie나 session에 저장해 두었다가, 유저가 돌아올 때 체크하면 된다.

  • 이건 redirection endpoint가 이상한 authorization code로 trick 되는 것을 막는다.

getting an access token

  • 서버는 authorization code를 access token으로 교환해야 한다.

  • authorization server 의 token endpoint에 POST요청을 보낸다.

  • POST [https://api.authorization-server.com/token](https://api.authorization-server.com/token)

    POST https://api.authorization-server.com/token grant_type=authorization_code& // body. code=AUTH_CODE_HERE& redirect_uri=REDIRECT_URI& client_id=CLIENT_ID& client_secret=CLIENT_SECRET

  • grant_type=authorization_code - 이 flow의 grant type이 authorization_code라는 의미.

  • code=AUTH_CODE_HERE - query string에서 받았던 authorization code.

  • redirect_uri=REDIRECT_URI - original link에서 제공했던 것과 같아야 한다.

  • client_id=CLIENT_ID - 앱을 만들 때 받았던 client id.

  • client_secret=CLIENT_SECRET - 서버사이드에서 만들어진 요청이므로, secret이 포함된다.

  • 서버는 access_token, expires_in 두 정보가 담긴 정보를 받게 된다.

    { "access_token" : "blabla", "expires_in" : 3600 }

  • 에러가 있다면 에러 페이로드를 받게 된다.

Q. table 12.1: 서버가 www-authenticate 헤더에 protection area를 명시한다는 게 무슨 말일까?

basic authentication에서, 서버는 인증을 요구하는 요청이 왔을 때 www-authenticate 헤더에 protection area를 넣는데, 이게 realm과 관련이 있다. 인증 후에는, 같은 realm에 속하는 페이지는 같은 username, password공유하기에, 이게 하나의 protection area가 되는 것이다.

ref

Q. WWW-authenticate 헤더에 realm은 무엇을 의미할까? - 요즘은 보내지 않는데, 왜 보내지 않을까.

Q. Status code 407, Proxy-authenticate, proxy-authorization, proxy-authentication-info 헤더들은 어떻게 쓰이는 것일까?

  • basic auth에서 resource authentication과 구별하기 위해 활용됨.

Q. Basic authentication example - 왜 정보를 base64로 인코딩하는 것일까?

  • rfc 7617에 정의됨.

Q. 토큰 기반 인증이란?

세션 기반 인증

  1. 클라이언트가 로그인 요청을 보냄

  2. 서버는 유저의 정보를 DB에서 찾고, 해당 유저 정보가 유효하면 세션을 생성해 메모리 또는 DB에 저장함

  3. 서버는 응답에 세션 ID를 포함시켜 보내고, 클라이언트의 쿠키에 설정한다.

  4. 이후 클라이언트는 요청 쿠키에 세션 ID를 포함시킨다.

  5. 서버는 세션 저장소를 뒤져서 해당 세션 ID가 유효한지 검증한다.

  6. 세션 자체에 의미나 정보가 담겨 있지는 않으나, 이를 탈취하면 다른 사용자인 척 가장할 수 있다. (해결 방안: 세션 유효시간, HTTPS)

  7. 보통 Redis 같은 세션 저장소에 저장한다. 즉, 서버의 메모리를 사용한다.

  8. 서버 확장이 어렵다. 예를 들어 로드밸런싱을 위해 서버 여러 대가 돌아가고 있다면, 중앙 세션 관리 시스템이나 세션 동기화 작업이 필요하다.

  9. 웹 브라우저가 아닌 클라이언트(예: 모바일)에서는 사용이 어려울 수 있다. 쿠키를 사용하지 않을 수 있기 때문이다.

토큰 기반 인증

  1. 클라이언트가 로그인 요청을 보냄

  2. 서버는 유저의 정보를 DB에서 찾고, 해당 유저 정보가 유효하면 토큰을 생성함

  3. 서버는 응답에 토큰을 포함시켜 보내고, 클라이언트는 로컬 스토리지에 저장함

  4. 이후 클라이언트는 요청 헤더에 토큰을 포함시킨다.

  5. 서버는 토큰이 유효한지 검증한다.

  6. 쿠키는 해당 쿠키를 발급한 특정 도메인에서만 사용이 가능하지만, 토큰을 전달해서 플랫폼 간 토큰을 공유할 수 있다. (예: OAuth로 구글 로그인)

  7. 클라이언트가 쿠키를 사용하지 않아도 괜찮다. 토큰은 HTTP 헤더의 인증 부분에 담겨 보내진다.

  8. 토큰 역시 세션처럼 탈취될 수 있다. 만료기간을 짧게 설정하거나, refresh token을 사용하는 등의 보완이 필요하다.

토큰의 종류

  1. 일반 토큰: 랜덤 문자열. (예: OAuth에서 사용되는 토큰) 아무런 정보도 담겨 있지 않기 때문에, 유효기간이 없고, 쿠키와 마찬가지로 토큰을 검증하기 위해 DB에 접근해서 검사하는 일이 필요할 수 있다.

  2. 클레임 토큰: 토큰 안에 정보를 담고 있는 것. (예: JWT)

JWT(JSON Web Token)

JWT는 토큰이 작동하는 매커니즘이 아니라, 토큰을 어떻게 만들 것인가에 대한 규약이다. JWT 토큰의 구조는 aaa.bbb.ccc로, 점(.)을 기준으로 세 부분으로 나누어져 있다.

a. Header: 토큰의 타입, 암호화 방법 (base64) b. Payload: 데이터 (base64) c. Signature: 헤더와 페이로드를 비밀키를 이용해 해싱하고, 이를 다시 base64로 인코딩한 것.

  • JWT 토큰이 위조된 것인지 아닌지 검증할 때 유저 정보를 조회할 필요가 없다. 토큰 검증이 이루어지는 서버와 유저 정보를 관리하는 서버가 분리되어 있어도 상관없다. 이는 서버 확장을 용이하게 만든다

  • JWT 토큰이 탈취당하더라도 토큰 내용을 위변조할 수는 없다. 서버의 비밀키로 암호화된 Signature 부분은 위조할 수 없기 때문이다.

ref (정리하는 데 필요했던 글들)

ref (나중에 다시 읽어볼 글들)

Last updated