포스트

OAuth 2.0부터 HMAC까지 실무 인증 패턴 정리

OAuth 2.0부터 HMAC까지 실무 인증 패턴 정리

1편에서 세션과 토큰 개념을 정리했는데요, 이번에는 실무에서 실제로 사용하는 인증 패턴들을 정리해보겠습니다.

OAuth 2.0, Basic Auth, HMAC… 정확히 파악하지 못한 채 일해온 사람.. 저뿐이지는 않겠죠//_//


OAuth 2.0

OAuth가 뭔가요?

Open Authorization의 약자로, 제3자 앱에 비밀번호 없이 권한을 위임하는 표준 프로토콜입니다.

왜 필요한가요?

OAuth 없던 시절을 생각해봅시다.

1
2
3
4
[사용자] "저 앱에서 내 카카오 친구 목록 가져오고 싶어"
[앱] "그러면 카카오 ID/PW 알려주세요"
[사용자] "여기요... abc@kakao.com / mypassword123"
[앱] (카카오 로그인해서 친구 목록 가져옴)

문제점이 보이죠?

  • 앱이 내 카카오 비밀번호를 알게 됨
  • 앱이 카카오에서 뭘 해도 모름 (메일 읽기, 삭제 등)
  • 권한 취소하려면 비밀번호를 바꿔야 함

OAuth 방식은 이렇습니다:

1
2
3
4
5
6
[사용자] "저 앱에서 내 카카오 친구 목록 가져오고 싶어"
[앱] "카카오한테 허락받아오세요"
[사용자] → [카카오] "앱이 친구 목록 요청하는데 허락할까요?"
[사용자] "허락!"
[카카오] → [앱] "여기 토큰. 친구 목록만 볼 수 있어요"
[앱] (토큰으로 친구 목록만 조회)

장점:

  • 앱은 비밀번호 모름
  • 친구 목록만 허용, 다른 건 못함
  • 카카오에서 언제든 권한 취소 가능

OAuth 2.0 용어 정리

용어설명예시
Resource Owner리소스 주인 (사용자)카카오 회원인 나
Client리소스 접근하려는 앱우리 서비스
Authorization Server인증/토큰 발급 서버카카오 인증 서버
Resource Server실제 리소스 보유 서버카카오 API 서버

Grant Types (인증 방식)

OAuth 2.0에는 4가지 표준 방식이 있어요.

Grant Type사용 케이스보안 수준
Authorization Code웹 서버 앱 (가장 많이 사용)높음
PKCE모바일/SPA (Authorization Code 확장)높음
Client Credentials서버 간 통신 (사용자 없음)중간
ImplicitSPA용 (현재 비권장)낮음

Authorization Code Grant (가장 중요!)

카카오 로그인, 네이버 로그인이 이 방식입니다. 가장 많이 쓰이는 플로우예요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[1] 사용자가 "카카오 로그인" 클릭

[2] 카카오 인증 페이지로 리다이렉트
    https://kauth.kakao.com/oauth/authorize
    ?client_id=xxx
    &redirect_uri=https://myservice.com/callback
    &response_type=code

[3] 사용자가 카카오에서 로그인 + 권한 동의

[4] Authorization Code와 함께 우리 서비스로 리다이렉트
    https://myservice.com/callback?code=AUTH_CODE_HERE

[5] 서버에서 code + client_secret으로 토큰 요청
    POST /oauth/token
    { code, client_id, client_secret, redirect_uri }

[6] Access Token + Refresh Token 발급
    { access_token, refresh_token, expires_in }

[7] 토큰으로 사용자 정보 요청
    GET /v2/user/me
    Authorization: Bearer {access_token}

왜 Authorization Code를 거칠까요?

“그냥 바로 Access Token 주면 안 되나요?” 라고 생각할 수 있는데요.

브라우저 리다이렉트로 토큰 전달하면 URL에 노출됩니다. 브라우저 히스토리나 로그에 토큰이 남게 돼요. 탈취 위험이 있죠.

그래서 Authorization Code를 먼저 받고, 서버 간 통신으로 토큰을 교환하는 방식입니다. Code가 노출돼도 client_secret 없이는 토큰 교환이 불가능하거든요.

PKCE (모바일/SPA용)

모바일 앱이나 SPA는 client_secret을 안전하게 보관할 수 없습니다.

  • 모바일 앱 → APK 디컴파일하면 노출
  • SPA → 브라우저 소스에서 노출

PKCE는 이 문제를 해결해요:

1
2
3
4
5
6
7
8
9
10
11
12
[1] 클라이언트가 랜덤 값 생성
    code_verifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"

[2] 해시해서 code_challenge 생성
    code_challenge = BASE64URL(SHA256(code_verifier))

[3] 인증 요청 시 code_challenge 전송

[4] 토큰 요청 시 code_verifier 전송

[5] 서버가 검증
    SHA256(code_verifier) == code_challenge? → OK!

핵심은 code_verifier를 알아야 토큰 교환이 가능하다는 점. Authorization Code가 탈취돼도 소용없어요.

Client Credentials Grant

사용자 없이 서버 간 통신할 때 사용하는 방식입니다.

1
2
[우리 서버] → [외부 API]
"나 OOO 서비스야, 데이터 줘"

사용자 개입 없이 Client ID + Client Secret으로 바로 토큰을 받습니다. 배치 작업이나 서버 간 API 연동에 많이 쓰여요.


Basic Authentication

가장 단순한 HTTP 표준 인증 방식. 결제 API에서 많이 씁니다.

동작 원리

1
2
3
4
5
6
7
8
9
10
11
12
13
[1] 인증 정보 준비
    ID: live_sk_xxx
    Password: (보통 비어있거나 동일)

[2] Base64 인코딩
    "live_sk_xxx:" → "bGl2ZV9za194eHg6"

[3] HTTP 요청
    GET /v1/payments
    Authorization: Basic bGl2ZV9za194eHg6

[4] 서버에서 검증
    Base64 디코딩 → ID:Password 추출 → 유효성 검증

예시 코드

1
2
3
4
5
6
String secretKey = "live_sk_xxxxxxx";
String encodedKey = Base64.getEncoder()
                          .encodeToString((secretKey + ":").getBytes());

HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "Basic " + encodedKey);

###️ 주의사항

주의사항이유
Base64는 암호화가 아님누구나 디코딩 가능
HTTPS 필수평문 전송과 동일
매 요청마다 인증 정보 전송노출 기회 많음

Basic Auth는 단순하지만 HTTPS 없이 쓰면 위험합니다. 꼭 HTTPS와 함께 사용하세요.


API Key 인증

가장 간단한 방식. 발급받은 키를 요청에 포함해서 보내면 끝입니다.

전달 방식

방식예시보안성
HeaderX-API-Key: abc123권장
Query Param/api?apiKey=abc123URL에 노출
Body{ "apiKey": "abc123" }보통

예시 코드

1
2
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("X-API-Key", apiKey);

API Key vs OAuth 2.0

항목API KeyOAuth 2.0
복잡도단순복잡
권한 범위전체 또는 없음Scope로 세분화 가능
만료보통 없음Access Token 자동 만료
사용 케이스서버 간 통신, 내부 API사용자 권한 위임

간단한 서버 간 통신에는 API Key, 사용자 권한 위임이 필요하면 OAuth 2.0이 적합해요.


HMAC (Hash-based Message Authentication Code)

비밀키를 네트워크로 전송하지 않는 방식입니다. 채팅 서비스나 웹훅에서 많이 써요.

동작 원리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[클라이언트]
메시지: "userId=12345"
비밀키: "secret_key_abc"
         ↓
HMAC-SHA256(메시지, 비밀키)
         ↓
해시값: "a1b2c3d4e5f6..."

→ 서버로 전송: 메시지 + 해시값 (비밀키는 안 보냄!)

[서버]
받은 메시지로 같은 방식으로 해시 생성
         ↓
받은 해시값 == 계산한 해시값?
         ↓
일치하면 인증 성공!

예시 코드

1
2
3
4
5
6
7
8
9
10
11
public static String generateHmac(String message, String secretKey) {
    Mac sha256Hmac = Mac.getInstance("HmacSHA256");
    SecretKeySpec keySpec = new SecretKeySpec(
        secretKey.getBytes(StandardCharsets.UTF_8), 
        "HmacSHA256"
    );
    sha256Hmac.init(keySpec);
    
    byte[] hash = sha256Hmac.doFinal(message.getBytes(StandardCharsets.UTF_8));
    return Hex.encodeHexString(hash);
}

HMAC의 장점

장점설명
비밀키 미전송네트워크에서 탈취 불가
무결성 검증메시지 변조 감지 가능
재사용 공격 방지timestamp 포함 시

Basic Auth보다 안전해요. 비밀키가 네트워크에 노출되지 않으니까요.


SSO (Single Sign-On)

한 번 로그인으로 여러 시스템에 접근하는 방식. 회사 내부 시스템에서 많이 쓰입니다.

SSO 없을 때 vs 있을 때

1
2
3
4
5
6
7
8
9
10
11
12
[SSO 없을 때]
시스템 A 로그인 → ID/PW 입력
시스템 B 로그인 → ID/PW 또 입력
시스템 C 로그인 → ID/PW 또또 입력
→ 귀찮음, 비밀번호 관리 복잡

[SSO 있을 때]
SSO 서버 로그인 → ID/PW 한 번만 입력
시스템 A 접근 → 자동 인증
시스템 B 접근 → 자동 인증
시스템 C 접근 → 자동 인증
→ 편리함, 중앙 집중 관리

동작 플로우

1
2
3
4
5
6
7
[사용자] → [우리 서비스] → [SSO 서버]
                              ↓
                         통합 계정으로 로그인
                              ↓
                    인증 토큰 + 사용자 정보 반환
                              ↓
[우리 서비스] ← 토큰 검증 후 세션 생성

회사 내부 시스템이나 그룹사 서비스 통합에 많이 사용돼요.


인증 방식 비교 총정리

방식복잡도보안사용 케이스
Basic Auth⭐⭐결제 API
API Key⭐⭐간단한 외부 연동
HMAC⭐⭐⭐⭐⭐무결성 중요한 경우
OAuth 2.0⭐⭐⭐⭐⭐⭐⭐SNS 로그인, 권한 위임
JWT⭐⭐⭐⭐⭐Stateless 인증
SSO⭐⭐⭐⭐⭐⭐⭐사내 시스템 통합

실무에서 선택 기준

어떤 인증 방식을 써야 할지 고민될 때 참고하세요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
사용자 권한 위임이 필요해?
→ OAuth 2.0

서버 간 통신이야?
→ API Key 또는 Client Credentials

메시지 무결성이 중요해?
→ HMAC

레거시 시스템이랑 연동해야 해?
→ Basic Auth (HTTPS 필수!)

사내 여러 시스템 통합 로그인?
→ SSO

Stateless + 확장성이 필요해?
→ JWT

한 프로젝트에서 여러 방식을 혼용하는 경우도 많아요. 결제 API는 Basic Auth, SNS 로그인은 OAuth 2.0, 내부 통신은 API Key 이런 식으로요. 상황에 맞게 선택하면 됩니다.


정리

  • OAuth 2.0: 제3자에게 비밀번호 없이 권한 위임. SNS 로그인의 표준
  • Basic Auth: ID:Password를 Base64 인코딩. 단순하지만 HTTPS 필수
  • API Key: 가장 단순한 방식. 서버 간 통신에 적합
  • HMAC: 비밀키 미전송. 무결성 검증 가능
  • SSO: 한 번 로그인으로 여러 시스템 접근

다음 편에서는 실제로 인증을 적용해보면서 정리하겠습니다.


이 글은 인증 시리즈 2편입니다.

  • 1편: 세션 vs 토큰, 알고 사용하기
  • 2편: OAuth 2.0부터 HMAC까지 실무 인증 패턴 정리 (현재 글)
  • 3편: [try] 인증 실제로 적용해보기
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.