- 작성일
로그인 기본 용어
- Authors

- Name
- seren-wib
Contents
로그인이 어떻게 돌아가는지, 특히 "한 계정으로 여러 사이트에 로그인"이 어떻게 되는지 이해하는 데 필요한 용어. 쿠키, 세션, 리다이렉트 같은 더 기본적인 용어는 웹 기본 용어에 있다.
1. 기본 개념
인증과 인가
인증은 "누구인가", 인가는 "무엇을 해도 되는가". 이메일과 비밀번호로 로그인하는 것이 인증이다. 로그인한 사람이 "남의 주문"을 볼 수 없게 막는 것이 인가다. 건물로 치면 출입증을 확인하는 것이 인증, 그 출입증으로 몇 층까지 갈 수 있는지 정하는 것이 인가다.
해시
되돌릴 수 없게 뒤섞은 값. 비밀번호는 글자 그대로 저장하지 않고 해시로 바꿔 저장한다. 로그인할 때 입력한 비밀번호도 같은 방식으로 해시를 만들어 저장된 값과 비교한다. DB가 통째로 털려도 원래 비밀번호는 알 수 없다.
Stairno는 scrypt라는 방식을 쓴다. 일부러 계산을 무겁게 만든 방식이라, 해커가 비밀번호 후보를 하나씩 넣어 보는 공격이 느려진다. 그 대가로 서버도 로그인 한 번에 계산 시간을 꽤 쓴다.
속도 제한
같은 곳에서 너무 많이 시도하면 잠시 막는 장치. 비밀번호를 수천 번 바꿔 넣어 보는 공격을 막는다. 로그인, 가입, 비밀번호 재설정 메일 같은 곳에 건다.
유출 비밀번호 차단
이미 다른 곳에서 털린 적 있는 비밀번호는 가입할 때 거절하는 것. 공개된 유출 목록과 비교한다. 비밀번호 원문은 보내지 않고 해시의 앞부분만 보내서 확인하는 방식이라 비밀번호가 새지 않는다.
2. 한 계정으로 여러 사이트에 로그인하기
OAuth
"내 계정 정보 일부를 이 앱이 써도 된다"고 허락해 주는 표준. "이 앱이 내 구글 캘린더를 읽어도 됩니까?" 같은 화면이 OAuth다. 비밀번호를 앱에 주지 않고, 허락받은 범위만 쓸 수 있는 토큰을 준다.
OIDC
"다른 곳에서 신원을 확인받고 오는" 표준 로그인 방식(OpenID Connect). OAuth 위에 "이 사람이 누구인지" 알려 주는 기능을 얹은 것이다. "구글로 로그인"이 대표적인 예다.
역할은 둘이다.
- OIDC 공급자: 신분증 발급처. 로그인을 실제로 받고, "이 사람은 누구다"라는 증명을 발급한다. Stairno에서는 계정 센터(API)가 이 역할이다
- OIDC 클라이언트: 신분증을 받아 오는 쪽. Labs, Works 같은 사이트다. 사이트는 공급자에 미리 등록해서
client_id(사이트 이름표)와client_secret(사이트 비밀번호)을 받는다
흐름을 단계로 풀면 이렇다.
- 사용자가 사이트에서 "Stairno로 로그인"을 누른다
- 사이트가 사용자를 계정 센터로 보낸다(리다이렉트)
- 계정 센터에서 로그인한다. 이미 로그인한 상태면 이 단계는 건너뛴다
- 계정 센터가 사용자를 일회용 코드와 함께 사이트로 돌려보낸다
- 사이트 서버가 그 코드를 계정 센터에 내고 토큰으로 바꾼다
- 사이트는 토큰을 확인하고 자기 쿠키로 자기 세션을 만든다
핵심은 쿠키를 공유하지 않는다는 것이다. 각 사이트는 자기 쿠키만 가지고, 계정 센터와는 리다이렉트로만 만난다. 그래서 브라우저가 서드파티 쿠키를 막아도 문제가 없다.
토큰
"이 사람(또는 이 사이트)은 이걸 해도 된다"는 증명서. 요청에 붙여 보내면 API가 확인하고 처리한다. 기한이 있어서 시간이 지나면 못 쓴다. Stairno에 나오는 토큰은 셋이다.
| 토큰 | 누구의 증명서 | 기한 | 쓰는 곳 |
|---|---|---|---|
| 액세스 토큰 | 사용자 | 1시간 | 사이트가 사용자 대신 API를 부를 때 |
| 리프레시 토큰 | 사용자 | 90일 | 액세스 토큰이 만료됐을 때 새로 받을 때 |
| 사이트 토큰 | 사이트 자신 | 짧음 | "나는 등록된 Stairno 사이트다"라고 밝힐 때(주문 생성 등) |
사이트 토큰을 받는 방식을 OAuth 용어로 client credentials라고 한다. 사용자 없이 사이트의 이름표와 비밀번호만으로 받는 토큰이다.
JWT
위조할 수 없게 서명된 토큰 형식(JSON Web Token). 토큰 안에 "누구의 것인지, 어느 API용인지, 언제까지 유효한지"가 적혀 있고, 발급처의 전자 서명이 붙어 있다. 받은 쪽은 DB를 뒤지지 않고 서명만 확인해서 진짜인지 안다. 내용을 한 글자라도 고치면 서명이 맞지 않는다.
JWKS
JWT 서명을 확인하는 데 쓰는 공개 열쇠 목록(JSON Web Key Set). 서명은 "비밀 열쇠로 잠그고 공개 열쇠로 확인하는" 방식이다. 계정 서버는 비밀 열쇠로 토큰에 서명하고, 공개 열쇠는 정해진 주소(/auth/jwks)에 누구나 볼 수 있게 올려 둔다. API나 사이트는 그 공개 열쇠로 서명을 검사한다.
Stairno에서는 비밀 열쇠가 DB에 암호화된 채로 저장되고, 그 암호화에 쓰는 값이 서버 시크릿 BETTER_AUTH_SECRET이다. 이 값을 잃어버리면 DB에 있는 비밀 열쇠를 풀 수 없다.
디스커버리 문서
OIDC 공급자가 "나는 이런 주소들을 쓴다"고 공개하는 안내문. 로그인 페이지 주소, 토큰 받는 주소, JWKS 주소 등이 적혀 있다. 사이트는 이 문서 하나만 보고 공급자에 붙을 수 있다. 주소는 표준으로 정해져 있다(/.well-known/openid-configuration).
PKCE
로그인 중간에 코드를 가로채도 못 쓰게 하는 장치(피크시라고 읽는다). 위 OIDC 흐름 4단계의 일회용 코드를 누가 훔쳐 가면 어떻게 될까? PKCE는 이렇게 막는다.
- 사이트가 로그인을 시작할 때 비밀 값 하나를 만들고, 그 값의 "지문"(해시)만 계정 센터에 보낸다
- 나중에 코드를 토큰으로 바꿀 때 원래 비밀 값을 같이 낸다
- 계정 센터는 비밀 값의 지문이 처음 받은 지문과 같은지 본다
코드만 훔친 사람은 원래 비밀 값을 모르니 토큰을 받을 수 없다.
동의 화면
"이 사이트가 내 이름과 이메일을 받아도 됩니까?"라고 묻는 화면. 다른 회사 앱이면 꼭 필요하지만, Stairno 사이트끼리는 모두 같은 브랜드라서 처음부터 신뢰하는 사이트로 등록하고 이 화면을 건너뛴다.