외부 SaaS와 우리 서비스를 연동하는 개발을 하면서 가장 많이 마주친 개념은 인증과 인가였다. 이번 글에서는 SSO, JWT, 그리고 인증/인가가 실제 요청 흐름에서 어떻게 연결되는지 정리해보려고 한다.
1.인증 (Authentication) 이란
“너 누구야?” 라고 사용자가 누군지 확인하는 단계이다. 즉, 요청을 보낸 주체가 누구인지 식별하고, 그 신원이 유효한지 검증하는 단계다.
- 아이디 / 패스워드로 로그인
- Google, Kakao 등을 통한 소셜 로그인
- 회사 SSO 를 통한 로그인
인증이 끝나면 서버는 “이 사용자가 누구인지”는 알 수 있다. 하지만 그 사용자가 어떤 기능까지 수행할 수 있는지는 아직 알 수 없다.
2.인가 (Authorization)
인가 라는 것은 “너 이거 해도 돼?” 를 확인하는 과정이다. 인증이 사용자의 신원을 확인하는 단계라면, 인가는 그 사용자가 특정 자원이나 기능에 접근할 권한이 있는지 판단하는 단계다. 예를 들어 이런 것들이 인가의 문제다.
- 로그인 후 사용자가 관리자 페이지에 들어갈 수 있는가
- 사용자 A 가 사용자 B, C, D의 주문 정보를 조회할 수 있는가
- 이 문서를 읽는 것이 가능한가 수정이 가능한가
인가의 기준은 단순한 역할(Role)만으로 결정되지 않는다.
실제 서비스에서는 권한(Permission), 소유권(Ownership), 조직 범위(Tenant), 정책(Policy) 등 다양한 기준이 함께 사용된다.
3. 인증과 인가를 분리해야 하는 이유
인증과 인가는 함께 등장하지만, 서로 다른 문제를 해결한다. 특히 외부 SaaS를 우리 서비스와 연동할 때 이 차이가 더 분명해진다.
예를 들어, 커머스 서비스에서 고객 상담용 SaaS인 Zendesk를 연동한다고 가정해보자.
먼저 Zendesk는 현재 접속한 사용자가 누구인지 확인해야 한다. 즉, 이 사용자가 실제로 우리 커머스 서비스의 유효한 사용자인지 검증하는 인증(Authentication) 이 필요하다.
하지만 인증만으로는 충분하지 않다. 어떤 사용자인지 확인되었다고 해서, 그 사용자가 모든 상담 내용에 접근할 수 있어서는 안 되기 때문이다. 예를 들어 사용자 A가 로그인했다고 해서 사용자 B나 C의 문의 내역, 주문 관련 상담 내용, 개인정보가 포함된 상담 기록까지 조회할 수 있다면 큰 보안 문제가 된다. 그래서 인가가 필요하다. 인가는 사용자에게 허용된 범위를 제한하는 단계이다.
인증과 인가를 분리하지 않으면, 로그인만 하면 다른 사용자들의 모든 상담내역을 볼 수 있는 위험한 구조가 된다.
4. JWT는 무엇일까
사용자가 로그인 페이지에서 아이디와 비밀번호를 입력하면, 인증 시스템은 해당 사용자의 정보를 검증한다. 검증이 성공하면 Access Token 을 발급하는데, 이 토큰 형식으로 자주 사용되는 것이 JWT (JSON Web Token) 이다.
JWT는 사용자와 토큰에 대한 정보를 담아 전달하는 형식이다. 클라이언트는 로그인 성공 이후 API를 호출할 때 이 JWT를 Authorization 헤더에 담아 보낸다. JWT는 보통 다음과 같은 정보를 담을 수 있다.
- 사용자 식별자
- 만료 시간
- 역할(Role) 또는 권한 관련 정보
- 토큰 발급자 정보
Authorization: Bearer <access-token>
JWT 는 점으로 구분된 세 부분으로 구성된다.
header.payload.signature
각 부분의 의미는 다음과 같다.
- header: 서명에 사용한 알고리즘 정보
- payload: sub, role, exp 같은 클레임(Claim)
- signature: 토큰 위변조를 방지하기 위한 서명
JWT 예시
{
"sub": "123", // 사용자 식별자
"preferred_username": "minjiwoo",
"role": "ADMIN", // 권한
"exp": 300 // 만료 시각
}
JWT는 정보를 담는 형식일 뿐이다. 이 토큰이 신뢰할 수 있는지, 그리고 이 사용자가 실제로 무엇을 할 수 있는지는 서버가 별도로 판단해야 한다.
5. SSO 는 무엇일까
SSO(Single Sign-On)는 한 번 로그인하면 여러 시스템을 다시 로그인하지 않고 사용할 수 있게 해주는 방식이다.
예를 들어 회사에서 Okta 같은 중앙 인증 시스템에 한 번 로그인하면, 이후 AWS나 GitHub 같은 다른 서비스에도 다시 로그인하지 않고 접근할 수 있는 경우가 있다.
즉, 서비스마다 아이디와 비밀번호를 반복해서 입력하는 대신, 한 번 중앙 인증 시스템에 로그인하면 그 결과를 여러 서비스가 함께 신뢰하는 구조가 바로 SSO다. 즉, SSO의 핵심은 여러 시스템이 동일한 사용자 신원 체계를 공유하도록 만드는 것이다.
6. 그렇다면 Keycloak 은 무슨 역할을 할까

여기서 등장하는 것이 Keycloak 이다. Keycloak은 SSO, 인증, 인가를 중앙에서 관리할 수 있게 해주는 오픈소스 IAM(Identity and Access Management) 솔루션이다.
쉽게 말하면, 각 서비스가 로그인 기능을 제각각 구현하지 않고, 로그인과 사용자 신원 검증을 Keycloak에 맡기는 구조를 만들 수 있다.
Keycloak 의 주요 기능은 다음과 같다.
1) 인증의 중앙화
사용자의 로그인 처리를 한 곳에서 담당한다.서비스마다 로그인 로직을 따로 만들지 않아도 되기 때문에 인증 방식이 일관되어진다.
2) SSO 제공
한 번 로그인한 사용자가 여러 시스템을 다시 로그인하지 않고 이용할 수 있게 한다.즉, Keycloak이 여러 애플리케이션 사이의 로그인 세션을 연결해주는 중심 역할을 한다.
3) 토큰 발급
인증이 끝난 뒤 Access Token, Refresh Token, ID Token 같은 토큰을 발급한다.애플리케이션은 이 토큰을 바탕으로 사용자를 식별하고 요청을 처리한다.
4) 사용자 및 권한 관리
사용자, 그룹, 역할(Role) 등을 중앙에서 관리할 수 있다. 즉, “누구인지”뿐 아니라 “어떤 권한을 가질 수 있는지”를 함께 다룰 수 있다.
5) 외부 인증 시스템 연동
Google 같은 소셜 로그인이나 다른 인증 시스템과도 연동할 수 있다.즉, Keycloak은 직접 사용자를 관리할 수도 있고, 다른 인증 시스템을 중간에서 연결하는 허브 역할도 할 수 있다.
7. Keycloak의 Realm은 어떤 단위일까
Keycloak을 처음 보면 가장 먼저 나오는 개념 중 하나가 Realm 이다.
Realm은 쉽게 말해 인증과 인가가 독립적으로 관리되는 하나의 보안 영역이다. 각 Realm은 자기만의 사용자(User), 클라이언트(Client), 역할(Role), 그룹(Group), 로그인 설정을 가진다. 즉, Realm이 다르면 사용자 목록도 다르고, 토큰을 발급하는 기준도 다르고, 권한 체계도 분리된다. 예를 들어서 서비스별로 권한 체계를 나눌 수 있다.
- 고객 전용 서비스 Realm
- 백오피스 전용 Realm
8. Keycloak에서 JWT 를 어떻게 발급 / 관리할 수 있을까
사용자가 Keycloak을 통해 로그인하면, Keycloak은 인증에 성공한 사용자에 대해 토큰을 발급한다.
애플리케이션은 이 토큰을 받아 이후 요청을 처리하게 된다. 또한 토큰의 수명이나 세션 유지 정책은 Keycloak의 realm 또는 client 설정에서 조정할 수 있다.
이 과정을 단순하게 보면 다음과 같다.
- 사용자가 애플리케이션에 접속한다.
- 애플리케이션은 사용자를 Keycloak 로그인 페이지로 보낸다.
- 사용자가 로그인에 성공한다.
- Keycloak은 애플리케이션에 authorization code를 전달한다.
- 애플리케이션은 이 code를 이용해 Keycloak의 토큰 엔드포인트에 요청하고, Access Token, ID Token, 필요하면 Refresh Token을 발급받는다.
- 클라이언트는 이후 API 요청에 Access Token을 담아 보낸다.
- 서버는 토큰을 검증하고, 사용자 정보를 바탕으로 요청을 처리한다.
여기서 Access Token은 주로 API 호출에 사용되고, ID Token은 로그인한 사용자가 누구인지 식별하는 데 사용된다.
그리고 Refresh Token은 Access Token이 만료되었을 때, 사용자가 다시 로그인하지 않아도 새로운 토큰을 발급받을 수 있게 해준다.
Keycloak은 이렇게 토큰을 발급하는 것에서 끝나지 않고, 토큰을 검증하고 갱신할 수 있는 기준도 함께 제공한다.
예를 들어 API 서버는 클라이언트가 보낸 Access Token을 그대로 신뢰하는 것이 아니라, 이 토큰이 정말 Keycloak이 발급한 것인지 검증해야 한다.
이때 Keycloak은 각 realm의 공개키를 JWKS(JSON Web Key Set) 형태로 제공한다.
애플리케이션이나 API 서버는 이 공개키를 사용해 JWT의 서명을 검증하고, 해당 토큰이 위조되지 않았는지 확인할 수 있다.
'Backend' 카테고리의 다른 글
| 멱등성을 보장하는 시스템 개발하기 (6) | 2024.10.13 |
|---|---|
| [sqlalchemy] Entity.metadata.create_all() 자동으로 테이블 생성하기 (0) | 2024.08.08 |
| [GitHub] REMOTE HOST IDENTIFICATION HAS CHANGED 해결방법 (0) | 2023.03.26 |