로그인 기능을 구현할 때, 가장 많이 사용하는 방식은 JWT와 Oauth2입니다.
오늘은 이 중에서 Oauth2에서 사용하는 Bearer토큰과 동장 방식에 대해 학습한 내용을 기록하려합니다.
일반적으로 사용하는 Bearer 토큰은 왜 앞에 Bearer이 붙는지 의문이 생겨 학습하게 되었습니다.
Bearer 토큰은 오늘날 인증 방식 중 가장 많이 사용되는 방식입니다. 클라이언트에서 서버에 요청을 보낼 때, Authentication Header에 Bearer xxx과 같은 형식으로 전송하여 서버에서는 해당 토큰을 통해 인증된 사용자인지 아닌지 판별합니다.
사실 Bearer는 널리 사용되는 스키마입니다. 다른 값이 들어갈 수 있습니다.
Authorization : 스키마 증명값
위와 같은 구조가 일반적으로 사용하는 구조이기 때문에 실제로 Bearer 이외에 다른 값을 넣는 경우가 있습니다.
Authorization: OAuth oauth_consumer_key="key", oauth_token="token", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1234567890", oauth_nonce="nonce", oauth_version="1.0", oauth_signature="signature"
Authorization: Digest username="user", realm="example", nonce="abc123", uri="/path", response="xyz456"
Authorization: OAuth oauth_consumer_key="key", oauth_token="token", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1234567890", oauth_nonce="nonce", oauth_version="1.0", oauth_signature="signature"
Authorization: MAC id="h480djs93hd8", ts="137131200", nonce="dj83hs9s", mac="bhCQXTVyfj5cmA9uKkPFx1zeOXM="
이 외에도 다양한 형태의 스키마를 통해 인증을 진행할 수 있습니다.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Bearer에서 토큰과 가장 자주 사용되는 방식은 JWT입니다. 위에서 기술되어 있듯이 Bearer JWT...와 같은 형태로 널리 사용됩니다.
JWT는 .(점)으로 구분된 세 개의 구분으로 구성되어 있습니다.
JWT의 타입과 서명 알고리즘을 정의하는 부분입니다
{
"alg": "HS256",
"typ": "JWT"
}
사용자의 정보(클레임, Claim)를 담고 있는 부분입니다.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1710000000,
"exp": 1710600000
}
토큰이 위변조되지 않았음을 보장하는 부분입니다.
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
그렇다면 왜 많고 많은 단어 중에서 Bearer라는 스키마가 가장 널리 사용될까요?
Bearer 스키마는 RFC6750에서 정의되었고 Oauth2.0에서 토큰을 전달하는 표준 방식입니다.
현대에 가장 많이 사용되는 인증 방식인 Oauth2.0에서 Bearer 토큰을 채택하면서 자연스럽게 Bearer 스키마가 가장 많이 사용되고 있습니다.
RFC 6750은 2012년에 발표되어 OAuth 2.0 인증 프로토콜에서 Bearer Token을 이용한 인증 방식을 정의하는 문서입니다
RFC 6750 공식 문서
GET /resource HTTP/1.1
Host: example.com
Authorization: Bearer <access_token>
Bearer라는 단어의 의미는 '소지자'입니다. 토큰을 가지고 있는 사용자는 '소지자'로 간주되어 해당 토큰을 가지고 있는 '소지자'만이 서버 리소스에 접근할 수 있다 라는 의미로 사용됩니다.
HTTP는 비연결을 지향하기 때문에 토큰을 한번만 보내는 것이 아닌 모든 요청마자 Authorization 헤더에 추가하여 전송해야합니다.
1️⃣ 간결하고 사용이 편리함
2️⃣ 세션 관리 불필요 (Stateless 인증)
이외에도 HTTPS를 사용하면 보안을 강화하거나 광범위한 표준이기 때문에 모바일, 웹, IOT 등 다양한 환경에서 사용할 수 있다는 장점이 있습니다.
1️⃣ 탈취되면 누구나 사용할 수 있습니다. → HTTPS를 강제하여 토큰이 암호화 된 상태로 전송을 해야합니다.
2️⃣ 유효 기간이 길면 보안 위험 증가합니다 → 짧은 토큰 만료 시간을 설정하고 토큰 만료 시 갱신할 수 있는 Refresh Token을 사용합니다.
HTTP/1.1 200 OK
Set-Cookie: access_token=JWT_TOKEN; HttpOnly; Secure; SameSite=Strict
Content-Type: application/json
{
"message": "Logged in successfully"
}
Rest API는 비연결성을 지향하기 때문에 매 요청마다 토큰을 전달해야합니다.
때문에 axios의 경우 interceptors를 사용하거나 다른 라이브러리의 경우에도 사전에 항상 토큰을 전달하거나 토큰이 없는 경우 로그인 페이지로 리다이렉션 시키는 방식을 사용합니다.
오늘은 다양한 로그인 방식과 Bearer 토큰에 대해 알아보았습니다. 왜 Bearer을 붙이는지에 대한 궁금증을 해소할 수 있어 재밌었습니다. 또한 RFC 6750, RFC 7519등 다양한 정의 문서를 직접 찾아볼 기회가 적었는데 이번 기회에 볼 수 있어서 좋았던 것 같습니다.