HTTP 인증
고친 사람 github-actions[bot]
HTTP 인증은 요청을 보낸 쪽이 누구인지 서버가 묻고 확인하는 규칙입니다. 서버가 신원을 밝히라고 요구합니다. 클라이언트는 요구받은 방식대로 신원 정보를 실어 다시 요청합니다. 여러 증명 방식이 모두 이 틀 하나를 나눠 씁니다.
쉽고 빠른 이해
HTTP 인증은 서버와 클라이언트가 「누구신가요」와 「저 이 사람입니다」를 주고받는 약속입니다. 관리자 페이지에서 브라우저가 아이디와 비밀번호를 묻는 창을 띄우는 것이 이 약속을 따르는 모습입니다.
이 약속이 없으면 서버마다 신원을 묻고 답하는 방법을 따로 정해야 합니다. 그러면 클라이언트는 서버를 새로 만날 때마다 그 서버만의 방법을 배워야 합니다. 약속이 하나로 정해져 있어서 어느 서버든 같은 헤더로 묻고 같은 헤더로 답합니다.
- 클라이언트가 신원 정보 없이 요청합니다
- 서버가 거절하면서 어떤 방식으로 신원을 밝히면 되는지 알려 줍니다
- 클라이언트가 그 방식대로 신원 정보를 실어 다시 요청합니다
방식을 미리 아는 앱은 1번부터 신원 정보를 실어 거절을 건너뜁니다.
대가는 요청마다 신원 정보를 다시 실어야 한다는 것입니다. 이 정보가 중간에서 읽히면 남이 그대로 가져다 쓸 수 있습니다. 그래서 오가는 내용을 암호화하는 연결 위에서만 씁니다.
웹 사이트의 로그인 화면은 대개 이 약속을 쓰지 않습니다. 입력 폼과 쿠키로 로그인을 따로 처리합니다.
상세
이 절은 HTTP 인증이 어떤 헤더와 응답으로 이루어지는지부터 봅니다. 그다음 그 틀 위에 얹히는 증명 방식을 봅니다. 마지막은 이 틀을 쓰지 않는 로그인 방식입니다.
HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜)는 클라이언트가 서버에 요청을 보내고 응답을 받는 규약입니다. 요청 하나에 응답 하나가 짝을 이룹니다.
인증은 요청을 보낸 쪽이 누구인지 확인하는 일입니다. 서버는 누가 보낸 요청인지 알아야 누구의 데이터를 돌려줄지 정할 수 있습니다. HTTP 인증은 이 확인을 요청과 응답 안에서 끝내는 규칙입니다.
헤더 한 쌍과 상태 코드 하나
HTTP 인증은 헤더 두 개와 상태 코드 하나로 이루어집니다. 헤더는 요청이나 응답 앞머리에 붙는 「이름: 값」 꼴의 줄입니다. 상태 코드는 요청이 어떻게 끝났는지 알리는 세 자릿수 값입니다.
서버가 보내는 헤더의 이름은 WWW-Authenticate 입니다. 앞머리의 WWW 는 World Wide Web(월드 와이드 웹)의 줄임말입니다. 셋을 모으면 아래 표가 됩니다.
| 구성 요소 | 누가 보내나 | 무엇을 알리나 |
|---|---|---|
| [[HTTP 401 | 401]] | 서버 |
| WWW-Authenticate | 서버 | 어떤 방식으로 신원을 밝히면 되는가 |
| [[Authorization 헤더 | Authorization]] | 클라이언트 |
서버는 401 응답에 WWW-Authenticate 헤더를 실어 보냅니다. 이렇게 신원을 밝히라고 요구하는 것이 챌린지입니다.
클라이언트가 신원을 밝히려고 싣는 정보를 자격 증명이라고 부릅니다. 아이디와 비밀번호 한 쌍이나 로그인 뒤 받은 토큰이 자격 증명입니다. 클라이언트는 이것을 Authorization 헤더에 실어 보냅니다.
Authorization 은 「인가」라는 뜻의 낱말입니다. 인가는 누구인지 확인된 쪽이 그 일을 해도 되는지 따지는 일입니다. 이 헤더에 싣는 것은 인가가 아니라 인증에 쓰는 정보입니다.
챌린지와 재요청
이 소절은 요청 한 번이 거절됐다가 다시 받아들여지기까지를 봅니다. 서버의 요구가 챌린지입니다. 클라이언트가 자격 증명을 실어 다시 보내는 요청은 그 챌린지에 대한 답입니다.
이렇게 묻고 답하는 방식을 챌린지-응답이라고 합니다. 이 이름의 「응답」은 서버가 돌려주는 HTTP 응답이 아닙니다. 클라이언트가 다시 보내는 요청을 가리킵니다.
sequenceDiagram
participant 클라이언트
participant 서버
클라이언트->>서버: 자격 증명 없이 요청
서버-->>클라이언트: 401 과 WWW-Authenticate
클라이언트->>서버: Authorization 을 실어 다시 요청
서버-->>클라이언트: 200 과 결과
그림은 두 번 오갑니다. 첫 왕복에서 클라이언트는 무엇을 실어야 하는지 배웁니다. 둘째 왕복에서 그것을 실어 보내고 결과를 받습니다.
아래는 둘째 화살표, 서버가 돌려준 401 응답입니다. 서버가 아이디와 비밀번호를 요구합니다.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="admin"
첫 줄에는 상태 코드 401 뒤에 Unauthorized 라는 문구가 붙습니다. 글자로는 「인가되지 않음」입니다. 뜻은 인증을 못 했다는 것이라 Authorization 헤더처럼 이름과 뜻이 어긋나 있습니다.
Basic 은 증명 방식의 이름입니다. realm 은 이 요구가 걸린 영역의 이름입니다. 둘은 아래 소절에서 차례로 풉니다.
다음은 셋째 화살표의 요청입니다. 클라이언트가 자격 증명을 Authorization 헤더에 실었습니다.
GET /admin HTTP/1.1
Host: example.com
Authorization: Basic dXNlcjpwYXNz
헤더 값에는 방식의 이름이 먼저 옵니다. 한 칸 띄운 뒤 자격 증명이 옵니다. 서버가 이 자격 증명을 믿으면 200 과 함께 결과를 돌려줍니다.
틀 위에 얹히는 인증 스킴
WWW-Authenticate 와 Authorization 에 적는 증명 방식을 인증 스킴이라고 부릅니다. HTTP 인증은 헤더 이름과 주고받는 순서만 정합니다. 무엇을 어떤 꼴로 실을지는 스킴마다 따로 정합니다.
새 스킴이 생겨도 헤더와 순서는 바뀌지 않습니다. 그래서 스킴이 달라도 헤더를 찾고 읽는 방법은 같습니다.
스킴마다 싣는 값을 보기 전에 낱말 둘을 먼저 풉니다. Base64 는 바이트를 영문자·숫자·기호 64 가지 글자로 옮겨 적는 방식입니다. 옮겨 적었을 뿐이라 누구나 원래 값으로 되돌릴 수 있습니다.
해시는 입력을 정해진 길이의 값으로 바꾸는 계산입니다. 결과에서 입력을 거꾸로 알아낼 수 없습니다.
세 스킴이 Authorization 에 싣는 값은 아래와 같습니다.
| 스킴 | Authorization 에 싣는 것 |
|---|---|
| [[Basic 인증 | Basic]] |
| [[Digest 인증 | Digest]] |
| [[Bearer 토큰 | Bearer]] |
Digest 는 비밀번호 대신 해시를 보냅니다. 해시는 되돌릴 수 없어서 가로챈 쪽도 비밀번호를 바로 읽어 내지 못합니다.
백엔드에서 가장 자주 만나는 것은 Basic 과 Bearer 입니다. 각 스킴이 어떻게 동작하는지는 그 스킴의 항목에서 다룹니다.
서버는 스킴 여럿을 한꺼번에 내밀 수 있습니다. 클라이언트는 그중 자기가 다룰 줄 아는 것을 하나 골라 답합니다.
realm 과 보호 영역
realm 은 서버가 자격 증명을 요구하는 영역에 붙인 이름입니다. 같은 서버 안에서도 관리자 화면과 일반 화면이 서로 다른 자격 증명을 요구할 수 있습니다. realm 은 그 둘을 가립니다.
같은 서버의 같은 realm 을 보호 영역이라고 부릅니다. 보호 영역 하나에서 통한 자격 증명은 그 영역의 다른 주소에도 다시 쓸 수 있습니다. 그래서 브라우저는 한 번 입력받은 자격 증명을 같은 보호 영역의 다음 요청에 다시 붙여 보냅니다.
요청마다 다시 싣는 자격 증명
HTTP 는 요청 하나하나를 따로 처리합니다. 앞 요청에서 누구였는지를 서버가 기억해 두지 않는 성질을 무상태라고 부릅니다. HTTP 인증도 이 성질을 따릅니다.
그래서 한 번 인증을 통과했어도 다음 요청에 자격 증명을 다시 실어야 합니다. 빠뜨리면 서버는 또 401 로 답합니다.
클라이언트는 401 을 기다리지 않고 첫 요청부터 Authorization 을 실어도 됩니다. 어떤 스킴을 쓸지 미리 알고 있으면 그렇게 합니다. 로그인 때 받은 액세스 토큰을 첫 요청부터 Authorization: Bearer <액세스 토큰> 으로 싣는 것이 이 경우입니다. 이러면 401 을 받는 왕복 하나가 줄어듭니다.
자격 증명이 읽히면 벌어지는 일
Basic 의 자격 증명은 Base64 로 옮겨 적었을 뿐입니다. 암호화가 아니라서 가로챈 쪽도 되돌릴 수 있습니다. 앞 예시의 값을 되돌리면 아이디와 비밀번호가 나옵니다.
base64 -d <<< dXNlcjpwYXNz # user:pass
Bearer 토큰은 가진 쪽이면 누구나 쓸 수 있습니다. 중간에서 토큰을 읽어 간 사람도 그 토큰으로 요청할 수 있습니다.
그래서 HTTP 인증은 HTTPS(HyperText Transfer Protocol Secure, 보안 하이퍼텍스트 전송 프로토콜) 위에서 씁니다. HTTPS 는 HTTP 에 암호화를 더해 오가는 내용을 중간에서 읽지 못하게 합니다. 자격 증명을 요청마다 다시 싣는 틀이라 이 보호도 그때마다 필요합니다.
프록시가 요구하는 407
프록시는 클라이언트와 서버 사이에서 요청을 대신 받아 넘겨 주는 중간 서버입니다. 프록시도 자격 증명을 요구할 수 있습니다.
프록시가 요구할 때도 틀은 같습니다. 상태 코드와 헤더 이름만 바뀝니다.
| 서버가 요구할 때 | 프록시가 요구할 때 | |
|---|---|---|
| 상태 코드 | 401 | [[HTTP 407 |
| 요구하는 헤더 | WWW-Authenticate | Proxy-Authenticate |
| 답하는 헤더 | Authorization | Proxy-Authorization |
이름이 갈려 있어서 요청 하나가 프록시와 서버에 각각 다른 자격 증명을 실을 수 있습니다.
401 과 403
서버는 누구인지 먼저 확인합니다. 그다음 그 사람이 이 일을 해도 되는지 따집니다. 뒤의 일이 앞에서 본 인가입니다. HTTP 인증이 맡는 것은 앞의 일뿐입니다.
자격 증명이 없거나 믿을 수 없으면 401 로 답합니다. 자격 증명은 믿을 수 있어도 권한이 모자라면 403 으로 답합니다. 403 은 같은 자격 증명으로 다시 보내도 결과가 안 바뀝니다.
이 틀을 쓰지 않는 로그인
웹 사이트의 로그인 화면은 대개 이 틀을 쓰지 않습니다. 사용자가 입력 폼에 아이디와 비밀번호를 적으면 서버가 확인한 뒤 세션을 만듭니다. 세션은 로그인한 사용자를 서버가 기억해 두는 기록입니다.
서버는 그 세션을 가리키는 값을 쿠키에 담아 브라우저에 줍니다. 쿠키는 브라우저가 저장해 두었다가 같은 사이트에 요청할 때마다 자동으로 붙이는 작은 값입니다. 이 방식에는 WWW-Authenticate 도 Authorization 도 나오지 않습니다.
웹 사이트가 폼과 쿠키를 고르는 까닭 하나는 화면입니다. 브라우저는 Basic 을 요구하는 401 을 받으면 아이디와 비밀번호를 묻는 창을 스스로 띄웁니다. 이 창은 브라우저에 들어 있는 것이라 사이트가 모양을 바꿀 수 없습니다.
반대로 프로그램끼리 부르는 서버에서는 이 틀이 흔합니다. 화면이 없으니 창 모양을 따질 일이 없습니다. 요청마다 Bearer 토큰을 Authorization 에 싣는 방식이 여기서 널리 쓰입니다.
관련 항목
HTTP 인증이 속하는 상위 분류
인증 · HTTP · RFC 9110 · 챌린지-응답 · 웹 보안
HTTP 인증을 이루는 헤더·상태 코드·영역
보호 영역 · WWW-Authenticate · Authorization 헤더 · Proxy-Authenticate · Proxy-Authorization · Authentication-Info · HTTP 401 · HTTP 407 · 헤더 · 상태 코드
HTTP 인증 위에 얹히는 인증 스킴
인증 스킴 · Basic 인증 · Digest 인증 · Bearer 토큰 · HOBA · Mutual 인증 · Negotiate 인증 · NTLM
HTTP 인증이 나르는 자격 증명
자격증명 · 액세스 토큰 · 리프레시 토큰 · JWT · API 키 · Base64 · 해시 · 논스
HTTP 인증이 따르는 HTTP 의 성질
무상태 · 요청-응답 · HTTP 메시지 · 헤더 필드
HTTP 인증과 맞세워지는 로그인 방식
세션 · 쿠키 · 폼 로그인 · OAuth 2.0 · OpenID Connect · 클라이언트 인증서 · 상호 TLS
HTTP 인증 다음에 오는 확인 단계
인가 · 인증과 인가 · HTTP 403 · 접근 제어 · 다중 인증
HTTP 인증의 자격 증명을 지키는 전송 보호
다른 이름: HTTP authentication · HTTP Authentication · HTTP 인증 프레임워크 · HTTP authentication framework