728x90
OAuth (OpenAuthorization)
권한 위임을 위한 표준 프로토콜이다. 사용자가 비밀번호를 제3자 앱에 제공하지 않고 서비스 접근 권한을 위임할 수 있게 한다.
"나의 자격증명은 그대로 두고, 일부 권한만 제3자에게 위임하는 것"
OAuth 2.0 핵심 구조
| 구성 요소 | 설명 | 역할 |
| Resource Owner | 인증받을 사용자 | 리소스의 실제 소유자 (ex: 사용자) |
| Client | OAuth를 사용하는 앱 | 리소스를 사용하려는 앱 (ex: 카카오톡에 연결된 외부 앱) |
| Authorization Server | 로그인 인증 및 토큰 발급 | 사용자 인증 및 토큰 발급 처리 (ex: Google) |
| Resource Server | 보호된 리소스를 제공하는 API 서버 | 실제 API 자원이 있는 곳 (ex: Google Calendar API) |
든든 앱에서 구글 로그인으로 회원가입 및 로그인을 한다면, OAuth에서 Resource Server는 Google의 사용자 정보 API를 가리킨다.
요약 단계
- 사용자가 로그인 요청 → 인증서버로 리디렉션
- 사용자 로그인 & 동의 → Authorization Code 발급
- 클라이언트가 서버로 Code 전달 → Access Token 발급
- Access Token으로 API 요청
흐름 그림
[Client] ──▶ [Authorization Server]
1. Redirect with client_id, redirect_uri, scope
[User] ◀─ 로그인/동의 화면
[Authorization Server] ──▶ [Client]
2. Redirect with code
[Client] ──▶ [Authorization Server]
3. POST /token with code, client_secret
[Authorization Server] ──▶ [Client]
4. Response with access_token
[Client] ──▶ [Resource Server]
5. API call with Authorization: Bearer <access_token>
node.js와 express로 만든 예제코드
// 로그인 요청
import express from 'express';
const router = express.Router();
const clientID = process.env.GOOGLE_CLIENT_ID;
const redirectURI = 'http://localhost:3000/oauth2callback';
const scope = encodeURIComponent('profile email');
router.get('/login', (req, res) => {
const authURL = `https://accounts.google.com/o/oauth2/v2/auth?` +
`client_id=${clientID}&redirect_uri=${redirectURI}&response_type=code&scope=${scope}`;
res.redirect(authURL);
});
export default router;
// 콜백 핸들러
import express from 'express';
import axios from 'axios';
const router = express.Router();
const clientID = process.env.GOOGLE_CLIENT_ID;
const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
const redirectURI = 'http://localhost:3000/oauth2callback';
router.get('/oauth2callback', async (req, res) => {
const code = req.query.code as string;
// Step 3: Access Token 요청
const response = await axios.post(
'https://oauth2.googleapis.com/token',
{
code,
client_id: clientID,
client_secret: clientSecret,
redirect_uri: redirectURI,
grant_type: 'authorization_code',
},
{
headers: {
'Content-Type': 'application/json',
},
}
);
const { access_token, id_token } = response.data;
// Step 4: User Info 요청
const userInfo = await axios.get('https://www.googleapis.com/oauth2/v2/userinfo', {
headers: {
Authorization: `Bearer ${access_token}`,
},
});
res.json(userInfo.data);
});
export default router;
이 외 개념들
Scope
- 사용자가 허용할 권한 범위 (예: email, calendar.readonly)
- 적절한 scope를 지정하면 최소 권한 원칙을 지킬 수 있음
PKCE (Proof Key for Code Exchange)
- 모바일 앱/SPA 같은 public client를 위한 보안 강화 기법
- 코드 탈취 방지
728x90
CI와 DI
본인인증 시스템에 사용되고, 휴대폰 본인인증 과정에서 많이 사용된다.
CI (Connecting Information): 개인 식별
- CI는 개인 식별자로, 다양한 서비스 간 동일인을 식별하기 위한 고유값이다.
- 이름, 주민번호, 휴대폰번호 등으로 인증받은 결과로 1인당 1개씩 고정된 값이 생성된다.
- 서비스 간 연동 시 같은 사람인지를 판별하는 데 사용된다.
특징
- 암호화된 해시값 (개인정보 유출 방지를 위해)
- 동일인이 여러 서비스에 가입했을 때, 서로 CI 값이 같음
- 사용자의 실명/주민번호 없이도 동일성 확인 가능
A 서비스와 B 서비스에 가입한 이용자가 있을 때,
- 두 서비스 모두 같은 휴대폰 인증을 통해 CI 값을 받으면
- 운영자는 두 계정이 동일인이라는 것만 파악 가능 (실명은 모름)
DI (Duplication Information): 중복 방지
- DI는 중복 가입을 방지하기 위한 식별자이다.
- 인증을 요청한 각 서비스마다 고유한 값으로 생성된다.
- 특정 서비스 내에서 1인이 여러 번 가입하는 것을 방지할 수 있도록 설계되었다.
특징
- 동일 사용자가 여러 서비스에 가입해도 DI 값은 서로 다름
- 하지만 한 서비스 안에서 같은 사람이 중복 인증하면 DI는 동일함
- CI가 "사람 중심 식별자"라면, DI는 “서비스 중심 식별자”
예를 들어, 어떤 쇼핑몰에서 휴대폰 본인인증을 두 번 시도해도 다른 서비스에 가입하면 DI는 다르다. → 서비스 간 추적 불가
| 항목 | CI (Connecting Information) | DI (Duplication Information) |
| 용도 | 동일인 여부 확인 | 중복 가입 방지 |
| 값 생성 | 모든 서비스에서 동일 | 서비스마다 다름 |
| 사용자 추적 | 가능 (단, 암호화됨) | 불가 |
| 개인정보 포함 여부 | 아님 (암호화된 값) | 아님 (암호화된 값) |
Auth Bearer (Bearer Token Authentication): 세션 인증
Bearer 토큰 인증은 API 요청 시 Authorization 헤더에 토큰을 포함하여 사용자 인증을 하는 방식이다.
Authorization: Bearer <token>
“이 토큰을 가진 자가 권한이 있다”는 의미이며, 토큰 자체가 신뢰 기반 자격 증명을 의미한다.
예를 들면
- 클라이언트가 OAuth로 로그인 → Access Token 받음
- 이후 모든 API 요청 시 헤더에
Authorization: Bearer eyJhbGciOiJIUzI1NiIsIn... - 서버는 토큰 유효성 검증 후 요청 처리
개발할 때 꼭 필요한 "인증"에 대해서 공부해보았다!
728x90
'TECH' 카테고리의 다른 글
| Reflow와 Repaint 🎨 (2) | 2025.06.26 |
|---|---|
| 딥링크 🔗 (13) | 2025.06.25 |
| 태스크 큐 (Task Queue) / 매크로태스크 큐 (Macrotask Queue) (1) | 2025.06.23 |
| 주소창에 google.com을 입력해서 결과를 보기까지의 과정들 🌐 (1) | 2025.06.22 |
| null, undefined, undeclared, NaN (0) | 2025.06.21 |