WorkOS Connect로 내 앱을 OAuth 제공자로 만들기

앱에 인증을 붙일 때 우리는 보통 한 방향만 생각합니다. 구글이나 회사 SSO 같은 외부 신원 제공자에 “우리 사용자 좀 로그인시켜 주세요” 하고 기대는 쪽이죠. WorkOS로 엔터프라이즈 SSO 붙이기에서 다룬 게 딱 이 방향입니다.
그런데 서비스가 자리를 잡으면 반대 요구가 들어오기 시작해요. “당신 서비스의 계정으로 우리 앱에 로그인하게 해주세요”, “그 사용자의 데이터를 API로 가져가게 해주세요” 하고 이번엔 다른 앱들이 우리에게 기대오는 겁니다. “Google로 로그인”이나 “GitHub로 로그인” 버튼을 우리 서비스 이름으로 제공하는 셈이죠.
WorkOS Connect는 바로 이 뒤집힌 방향, 즉 내 앱이 다른 앱에게 신원과 데이터를 열어주는 OAuth 제공자가 되도록 해주는 기능입니다. 이 글에서는 Connect가 어떤 문제를 풀어주는지, 두 가지 애플리케이션 유형이 어떻게 다른지, 그리고 토큰이 발급되고 검증되는 흐름을 차례로 살펴보겠습니다.
Connect가 여는 세 가지 문
Connect는 “다른 애플리케이션이 우리 사용자의 신원과 자원에 안전하게 접근하도록” 해줍니다. 문서는 크게 세 가지 시나리오를 제시하는데요.
우선 고객 통합입니다. 고객사가 우리 서비스와 연동되는 자체 앱을 만들고, 거기에 우리 브랜드의 로그인 버튼을 붙이는 경우예요. 그다음은 보조 애플리케이션입니다. 포럼이나 고객 지원 도구처럼 우리 서비스를 둘러싼 주변 앱들이 같은 사용자 신원을 그대로 쓰게 하는 거죠. 마지막은 파트너 접근입니다. 신뢰하는 파트너에게 자격 증명을 발급해 API 인증에 쓰도록 하는 경우입니다.
세 시나리오 모두 공통점은, 우리가 신원을 소비하는 쪽이 아니라 제공하는 쪽이 된다는 점입니다. 그래서 Connect는 OAuth 2.0과 OpenID Connect 같은 산업 표준 위에 지어졌어요. 표준을 그대로 따르니 상대 앱은 이미 익숙한 OAuth 라이브러리로 우리 서비스에 붙을 수 있습니다.
소비자에서 제공자로
이 방향 전환을 OAuth 용어로 보면 우리 앱의 역할이 통째로 바뀝니다. 앞서 본 AuthKit 로그인이나 SSO에서 우리 앱은 신뢰 당사자(Relying Party), 즉 외부 인가 서버가 발급한 토큰을 받아 쓰는 쪽이었어요. 반면 Connect를 켜면 우리 앱이 그 인가 서버(Authorization Server) 자리에 올라섭니다. 이제 서드파티 앱이 신뢰 당사자가 되고, 우리는 토큰을 발급하고 서명하며 검증용 키까지 공개하는 주체가 되는 거죠.
같은 WorkOS 대시보드 안에 로그인용 AuthKit과 제공자용 Connect가 나란히 있어 헷갈리기 쉬운데, “누가 누구의 사용자에 기대는가”로 나누면 간단합니다. 우리가 남의 사용자를 빌려 오면 로그인이고, 남이 우리 사용자를 빌려 가면 Connect예요.
두 가지 애플리케이션 유형
Connect에서 애플리케이션을 만들 때는 두 유형 중 하나를 고릅니다. 누가 인증의 주체냐에 따라 갈리는데요.
OAuth 애플리케이션은 개별 사용자가 주체입니다. 사용자가 “내 앱으로 로그인”을 눌러 명시적으로 동의하는 흐름이라, 발급되는 토큰에는 로그인한 사용자의 정보가 담깁니다. 웹이나 모바일 앱처럼 사람이 직접 로그인하는 서드파티 통합에 맞아요.
M2M(Machine-to-Machine, 이하 M2M) 애플리케이션은 사람이 없는 서비스 간 통신이 주체입니다.
백엔드 서비스끼리 주고받는 자동화된 접근이라 로그인 화면이 없고, 토큰에는 사용자 대신 어느 조직에 발급됐는지를 나타내는 org_id 클레임이 담깁니다.
정리하면 사용자가 개입하면 OAuth 애플리케이션(authorization_code 흐름), 서비스끼리면 M2M 애플리케이션(client_credentials 흐름)입니다.
이제 각각을 흐름으로 따라가 볼게요.
OAuth 애플리케이션: 사용자를 대신한 접근
OAuth 애플리케이션은 우리에게 익숙한 인가 코드(Authorization Code) 흐름을 그대로 씁니다. 서드파티 앱이 우리 서비스로 사용자를 보내 로그인시키고, 돌아온 인가 코드를 토큰으로 교환하는 방식이죠.
sequenceDiagram
autonumber
participant U as 사용자
participant T as 서드파티 앱
participant C as 내 앱 (Connect)
U->>T: "내 앱으로 로그인" 클릭
T-->>U: 내 앱의 authorize로 리다이렉트<br/>(client_id, redirect_uri, scope, state)
U->>C: 로그인과 동의
C-->>U: redirect_uri로 authorization code 반환
U->>T: code 전달
T->>C: 토큰 교환 (code + client_secret)
C-->>T: access token 발급 (사용자 정보 포함)
T->>C: access token으로 사용자 데이터 API 호출
C-->>T: 데이터 응답
서드파티 앱은 먼저 우리 Connect 애플리케이션의 인가 엔드포인트로 사용자를 리다이렉트합니다.
GET /oauth2/authorize?
response_type=code
&client_id=client_01ABC...
&redirect_uri=https%3A%2F%2Fthirdparty.app%2Fcallback
&scope=openid%20profile%20email
&state=xyz
&nonce=n-0S6_WzA2Mj
사용자가 로그인하고 동의하면 redirect_uri로 인가 코드가 돌아오고, 서드파티 앱은 이 코드를 client_secret과 함께 토큰 엔드포인트(POST /oauth2/token)에 제출해 액세스 토큰(access token)을 받습니다.
동적 클라이언트 등록(Dynamic Client Registration)으로 만들어진 클라이언트라면 여기에 PKCE가 더해집니다.
인가 요청에 code_challenge를, 토큰 교환에 code_verifier를 함께 실어 코드 가로채기를 막는 방식이에요.
발급된 토큰에는 로그인한 사용자의 정보가 담기고, openid 스코프를 요청하면 id_token이, offline_access 스코프를 요청하면 refresh_token이 함께 나옵니다.
서드파티 앱은 이 토큰으로 우리 API를 호출해 사용자의 자원을 대신 다룰 수 있습니다.
M2M 애플리케이션: 서비스 간 접근
M2M 애플리케이션에는 로그인할 사람이 없습니다.
그래서 사용자를 리다이렉트하는 단계 없이, 서비스가 자기 자격 증명만으로 곧장 토큰을 받아 갑니다.
OAuth의 client_credentials 그랜트를 그대로 쓰는 거죠.
이 그랜트 자체의 동작과 클라이언트 인증 방식은 OAuth Client Credentials로 M2M 인증하기에서 자세히 다뤘습니다.
# 엔드포인트 경로는 /oauth2/token, 호스트는 Connect 환경마다 다릅니다
curl -X POST "https://auth.example.com/oauth2/token" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_id=$CLIENT_ID" \
--data-urlencode "client_secret=$CLIENT_SECRET"
여기서 발급되는 액세스 토큰에는 사용자 정보 대신 org_id 클레임이 담깁니다.
클라이언트가 어느 조직을 대신해 동작하는지를 가리키는 값인데요.
우리 서버는 이 org_id를 보고 “이 요청은 A 파트너사 몫이구나” 하고 조직 단위로 접근 범위를 가를 수 있습니다.
참고로 M2M 애플리케이션은 서드파티용으로만 설정할 수 있다는 제약이 있어요.
발급된 토큰을 검증하기
토큰을 받아 우리 API를 호출하는 쪽이 서드파티 앱이라면, 그 토큰을 검증하는 쪽은 우리 서버입니다. OAuth 용어로는 우리가 자원 서버(Resource Server)가 되고, Connect가 토큰을 발급하는 인가 서버(Authorization Server) 역할을 맡는 구조죠.
검증 방식은 두 가지입니다.
우선 상태 없는(stateless) 검증입니다. Connect가 공개하는 JWKS로 토큰 서명을 직접 검증하는 방식이라, 매 요청마다 WorkOS에 물어볼 필요가 없어 빠릅니다. WorkOS로 MCP 서버에 OAuth 붙이기에서 다룬 액세스 토큰 검증과 완전히 같은 방식이에요. 또 하나는 토큰 인트로스펙션(introspection) API로, 토큰이 지금도 유효한지 인가 서버에 동기적으로 물어보는 방식입니다. 즉시 폐기가 중요한 경우에 쓰지만 매번 네트워크 왕복이 든다는 비용이 있고요.
인가 엔드포인트든 토큰 엔드포인트든 JWKS 주소든, 이 값들은 전부 OAuth 메타데이터 문서로 공개됩니다. 서드파티 앱이 우리 엔드포인트를 하드코딩하지 않아도 되는 이유인데, 이 자동 발견 구조는 OAuth 2.0 메타데이터와 엔드포인트 동적 발견에서 자세히 다뤘습니다.
대시보드에서 준비하기
실제 설정은 WorkOS 대시보드에서 애플리케이션을 만드는 것으로 시작합니다. 용도에 맞춰 OAuth 유형과 M2M 유형 중 하나를 고르면 되고요.
자격 증명 관리에는 알아둘 규칙이 몇 가지 있습니다.
한 애플리케이션은 자격 증명을 최대 5개까지 가질 수 있고, client_secret은 생성 시점에 딱 한 번만 표시되며 이후 다시 볼 수 없습니다.
그러니 만들자마자 안전한 곳에 보관해 둬야 해요.
그리고 이 자격 증명은 만료되지 않으므로, 유출이 의심되면 폐기하고 새로 발급하는 회전(rotation)을 직접 챙겨야 합니다.
마치며
WorkOS Connect는 인증의 방향을 뒤집어, 우리 앱을 다른 앱들이 붙어 오는 OAuth 제공자로 만들어 줍니다.
사용자가 직접 로그인하는 통합이라면 사용자 정보를 담은 토큰을 발급하는 OAuth 애플리케이션을, 서비스끼리의 자동화된 접근이라면 org_id로 조직을 식별하는 M2M 애플리케이션을 쓰면 됩니다.
어느 쪽이든 OAuth 2.0과 OpenID Connect 표준을 그대로 따르기 때문에, 상대 앱은 특별한 준비 없이 익숙한 방식으로 우리 서비스에 연결할 수 있어요.
더 자세한 내용은 WorkOS Connect 공식 문서를 참고하세요.
This work is licensed under CC BY 4.0