Skip to content
스토브
마지막 업데이트

실제 이용 흐름이 궁금하신가요?

이용 시나리오 / 웹 서비스 이용하기

웹 서비스 SSO 연동

이해하기


SSO 연동은 게임이 고객센터·약관·이벤트·상점 같은 웹 서비스를 재로그인 없이 여는 기능이에요. 게임 로그인으로 확보한 게임 AccessToken을 기반으로 일회성 state를 발급받고, SSO Callback을 호출해 인증 쿠키를 웹 서비스에 전달하는 구조예요.

연동 방식은 두 가지예요. Mobile·PC SDK를 사용하는 게임은 SDK가 state 발급과 Callback 호출을 처리하는 SDK 방식(기본)을 사용하고, SDK를 사용하지 않는 일부 게임은 API를 직접 호출하는 API 직접 방식(예외)을 사용해요.

연동 방식

방식 이런 경우에 사용 특징
SDK 방식
(기본)
Mobile SDK 또는 PC SDK를 이미 사용 중인 게임 SDK가 토큰 확인·state 발급·웹뷰 실행을 표준 동선으로 제공.
구현이 간단하고 권장되는 방식
API 직접 방식
(예외)
SDK를 사용하지 않고 게임이 직접 SSO API를 호출하는 일부 게임 게임이 state 발급·Callback 호출·토큰 갱신을 직접 구현.
자유도가 높은 대신 구현·유지보수 책임이 큼

적용 환경

SSO는 웹 서비스를 어디에 표시하느냐에 따라 웹뷰 동선과 외부 브라우저 동선으로 나뉘어요. 플랫폼이 달라도 Callback 구조는 동일하며, 실행 방법과 발급 쿠키만 달라요.

구분 웹뷰 동선 외부 브라우저 동선
실행 위치 게임 화면 안 내장 웹뷰 (Android WebView·iOS WKWebView·CEF·WebView2) 이용자 기본 브라우저
토큰 유형(mode) game_token web_token
발급 쿠키 접근 토큰(SUAT) 접근 토큰(SUAT) + 갱신 토큰(SURT)

구성 요소

구성 요소 역할
Game Client (SDK/직접) 게임 AccessToken 확인, state 발급, SSO Callback URL 생성, 웹뷰·외부 브라우저 실행
Sim API (SSO Gateway) state 발급·검증, redirect_url 도메인 검증, 인증 쿠키(SUAT·SURT) 발급, 최종 서비스로 302 리다이렉트
Auth Server web_token 모드에서 게임 토큰을 웹 전용 토큰으로 변환
Web Service 발급된 인증 쿠키를 기반으로 재로그인 없이 서비스 제공
Redis state와 게임 AccessToken의 매핑을 일정 시간(10분) 임시 저장

동작 원리

게임 AccessToken을 URL에 직접 담지 않고, 일회성 state 키를 발급받아 Callback URL에 전달해요. SSO Gateway가 state로 실제 토큰을 조회해 인증 쿠키를 발급하므로 민감한 토큰이 URL에 노출되지 않아요.

웹뷰 동선은 game_token 모드로 게임 토큰을 그대로 웹 인증에 사용하며 접근 토큰(SUAT) 쿠키만 발급해요. 외부 브라우저 동선은 web_token 모드로 Auth Server가 게임 토큰을 웹 토큰으로 변환하고 접근 토큰(SUAT)과 갱신 토큰(SURT)을 함께 발급해요.

연동 가이드


사전 준비

SDK 방식·API 직접 방식에 공통으로 필요한 준비 사항이에요. 방식별 세부 준비는 각 [개발하기] 트랙에서 안내해요.

항목 내용 비고
유효한 게임 AccessToken 게임 로그인이 완료되어 유효한 게임 AccessToken을 보유.
없거나 만료 시 로그인·갱신 선행
필수
state 발급 API 접근 환경별 도메인의 POST /sim/auth/sso/key 호출 경로 확보 필수
WebView 쿠키·리다이렉트 웹뷰·브라우저가 SUAT·SURT 쿠키를 저장하고 302 리다이렉트를 따라가도록 설정 필수
redirect_url 도메인 확인 최종 이동 주소가 허용 도메인 범위인지 확인 (아래 허용 도메인 참고) 필수

API 접근 권한은 퍼블리싱 기술 담당자와 협의해요
환경별 도메인과 접근 권한은 담당자를 통해 확인해 주세요. 문의: sgp_publishtech_d@smilegate.com

전체 SSO 흐름

게임이 state를 발급받아 Callback을 호출하면, SSO Gateway가 도메인을 검증하고 게임 토큰을 조회해 mode에 따라 인증 쿠키를 발급한 뒤 최종 서비스로 이동시켜요. SDK 방식·API 직접 방식 모두 아래 순서를 따라요.

Callback URL 파라미터

발급받은 state와 최종 서비스 주소로 Callback URL을 구성해요. 쿼리 파라미터 값은 모두 URL 인코딩해야 해요.

파라미터 필수 기본값 설명
state 필수 - 게임 AccessToken 기준으로 발급된 일회성 SSO 키
redirect_url 필수 store.onstove.com 인증 완료 후 이동할 웹 서비스 주소.
미지정 시 기본 주소로 이동
mode 선택 web_token game_token: 게임 토큰 그대로 사용, SUAT만 발급(웹뷰)
web_token: 웹 토큰 변환, SUAT·SURT 발급(외부 브라우저)
theme 선택 light 오류 화면에 적용할 UI 테마. light / dark
game_id 선택 빈 문자열 호출한 게임을 식별하는 게임 ID
lang 선택 ko 오류 페이지 다국어 처리에 사용할 언어값

요청 형식 예시

text
https://api.onstove.com/sim/auth/session/callback
    ?state={STATE}
    &redirect_url={REDIRECT_URL}
    &mode={MODE}
    &theme={THEME}
    &game_id={GAME_ID}
    &lang={LANG}

상세 응답 코드 명세는 별도 메뉴에서 제공돼요
엔드포인트별 응답 코드(예: 91030 Wrong Request 등) 등 상세 명세는 API & SDK 레퍼런스 메뉴로 이관될 예정이에요.

redirect_url 허용 도메인

SSO Gateway는 Open Redirect 공격을 막기 위해 redirect_url의 도메인을 검증해요. 단순 문자열 포함 검사는 우회될 수 있으므로, Hostname을 파싱해 정확한 도메인 또는 하위 도메인 관계를 검증해야 해요.

  • 허용 도메인: onstove.com, onstove.vn, gate8.vn, gate8.com, ppool.us, gameclub.ph
  • 하위 도메인 허용 여부는 Gateway 정책에 맞게 적용

문자열 포함 방식으로 검증하지 마세요
https://onstove.com.attacker.com이나 https://attacker.com/?url=onstove.com 같은 우회 주소가 통과될 수 있어요.
반드시 Hostname을 파싱해 정확한 도메인·하위 도메인 관계를 검증해 주세요.

환경 구분 안내

환경별 도메인을 사용해요. 연동 테스트는 Sandbox에서 먼저 진행한 뒤 Live에 적용해요.

환경 Domain Address
dev https://api-dev.onstove.com/sim
qa https://api-qa.onstove.com/sim
qa2 https://api-qa2.onstove.com/sim
sandbox https://api.gate8.com/sim
live https://api.onstove.com/sim

개발하기


SDK 연동

Mobile·PC SDK를 사용하는 기본 경로예요. SDK가 게임 AccessToken 확인·state 발급·Callback 호출을 처리하고, 게임은 실행 시점과 mode만 지정하면 돼요.

사전 준비

  • 로그인이 완료되어 유효한 게임 AccessToken을 보유하고 있어야 해요. 없거나 만료 시 로그인·토큰 갱신을 먼저 진행해요.
  • 웹뷰가 인증 쿠키(SUAT·SURT)를 저장·유지하고 302 리다이렉트를 따라가도록 설정해요.
  • 외부 브라우저 동선에서는 mode=web_token을 사용해 SUAT·SURT를 함께 발급받아요.

개발 흐름

모바일 SDK와 PC SDK 모두 아래 순서가 동일하며, 웹 서비스를 실행하는 방법만 플랫폼에 따라 달라요.

  1. SDK 로그인 모듈로 현재 이용자의 게임 AccessToken을 확인해요.
  2. 게임 AccessToken을 POST /sim/auth/sso/key에 전달해 일회성 state를 발급받아요. (유효 시간 10분)
  3. state·redirect_url로 SSO Callback URL을 생성해요. 동선에 맞게 mode를 지정해요.
    • 웹뷰 실행: mode=game_token
    • 외부 브라우저 실행: mode=web_token
  4. 생성한 Callback URL을 웹뷰 또는 기본 브라우저의 최초 진입 주소로 사용해요.
  5. SSO Gateway가 인증 쿠키를 발급하고 302로 최종 서비스로 이동시켜요.
  6. 게임 AccessToken 만료 전에 새 state를 발급받아 같은 절차를 다시 수행하면 인증 쿠키가 자동 갱신돼요.

인증 토큰을 URL에 직접 담지 마세요
게임 AccessToken을 Callback URL에 그대로 포함하면 토큰이 노출돼요. 반드시 state 키만 URL에 전달하고, 갱신 시에도 기존 state를 재사용하지 마세요.

트러블슈팅

상황원인조치
Callback 후 인증 상태가 유지되지 않음웹뷰 쿠키 저장 비활성 또는 302 리다이렉트 미허용웹뷰 쿠키 저장·리다이렉트 설정을 확인하세요.
외부 브라우저에서 로그인이 풀림web_token 미사용으로 SURT(갱신 토큰) 미발급외부 브라우저 동선은 mode=web_token으로 지정하세요.
state 오류로 에러 페이지 이동state 미전달·10분 초과·이미 사용된 state실행 직전에 state를 발급하고, 갱신 시 새 state를 사용하세요.
게임 AccessToken 조회 실패미로그인 또는 토큰 만료로그인·토큰 갱신 후 state부터 다시 발급하세요.
스팀으로 실행하면 Base_OpenExternalUrl()이 동작하지 않음스팀 런처로 실행한 경우는 아직 지원하지 않음PCSDK 3.5.1에서 지원 예정.
Base_OpenExternalUrl() 콜백이 오지 않음게임 루프에서 Base_RunCallback()을 호출하지 않음게임 루프에서 매 프레임 Base_RunCallback()을 호출하세요.
브라우저는 열리는데 로그인이 안 된 상태로 표시됨스토브 관련 도메인이 아니어서 SSO 처리가 적용되지 않음허용 도메인 범위의 주소인지 확인하세요.

샘플 코드

Mobile SDK 외부 브라우저 연동

인증 세션을 유지한 상태로 외부 브라우저에서 ONSTOVE 페이지를 열어요.

게스트 계정은 본 기능을 사용할 수 없어요. (게스트 사용자는 지원 대상에서 제외돼요.)

스토브와 다른 인증서(서명키)로 로그인한 계정은 SSO 외부 브라우저 호출을 지원하지 않아요. 반드시 ‘스토브 계정 전환’을 완료한 후 해당 기능을 호출해 주세요.

호출 예시
cpp
/**
  * url : "외부브라우저를 연동할 url : 쿠폰 or 커뮤니티 등";
  **/

public void OpenExternalUrl()
{

   AccessToken accessToken = Auth.AccessToken;
   if (accessToken == null)
   {
     return;
   }

  string url = "외부브라우저를 연동할 url : 쿠폰 or 커뮤니티 등";

  ViewUI.OpenExternalUrl(url, (Result result) =>
  {
    if (result.IsSuccessful)
    {
        // 설정된 url 로 외부브라우저 연동 성공            
    }
    else
    {
        // 외부브라우저 호출 실패
        OperationUI.HandleResult(result, (Result operationResult) =>
        {
        });
    }
  });
}
PC SDK 외부 브라우저 연동

PC SDK를 사용하면서 웹 서비스를 외부 브라우저로 여는 경우에 한해, 위 1~5단계를 직접 구현하지 않아도 돼요. Base_OpenExternalUrl() 한 번을 호출하면 SDK가 게임 AccessToken 확인·state 발급·SSO Callback 호출·외부 브라우저 실행까지 대신 처리해요. 이용자는 재로그인 없이 스토브 커뮤니티·고객센터 같은 웹 서비스를 기본 브라우저에서 이용할 수 있어요.

게임 화면 안 웹뷰로 여는 동선(mode=game_token)은 이 API의 대상이 아니에요. 웹뷰 동선과 PC SDK를 사용하지 않는 게임은 위 1~5단계를 그대로 구현해야 해요.

항목 내용
제공 모듈 BaseSDK. 팝업(ViewSDK) 모듈과 무관하며 ViewSDK 초기화 없이 호출 가능
적용 동선 외부 브라우저 동선. 이용자 기본 브라우저 실행
state·mode 지정 SDK가 내부에서 처리. 게임은 열려는 URL만 전달
SSO 적용 범위 스토브 관련 도메인을 열 때만 SSO 처리 적용. 그 밖의 주소는 인증 없이 브라우저로만 실행
호출 조건 Base_Initialize() 완료 이후 호출
결과 수신 비동기 API. 결과는 Base_RunCallback()을 호출한 스레드에서 콜백으로 전달

스팀 런처로 실행한 경우에는 사용할 수 없어요
PCSDK 3.5.1에서는 사용할 수 있게 기능을 제공할 예정이에요.

함수 원형
cpp
void Base_OpenExternalUrl(const wchar_t* url, OnOpenExternalUrlFinished onFinished);

// 콜백
typedef void(__cdecl* OnOpenExternalUrlFinished)(CallbackResult callbackResult);
파라미터 필수 설명
url 필수 열고자 하는 웹 서비스 주소. 스토브 관련 도메인이면 SSO 처리 적용
onFinished 선택 실행 결과를 받을 콜백. 결과 확인이 필요 없으면 생략 가능
호출 예시
cpp
#include "BaseSDK.h"

using namespace Stove::PCSDK::Base;

// Base_Initialize() 성공 이후에 호출해요.
void OpenStoveCommunity()
{
    Base_OpenExternalUrl(L"https://www.onstove.com", [](CallbackResult callbackResult)
    {
        if (callbackResult.GetResult().IsSuccessful())
        {
            // 브라우저 실행 성공 시 로직을 구현해 주세요.
        }
        else
        {
            // 실패 시 로직을 구현해 주세요.
        }
    });
}

// 게임 루프에서 매 프레임 호출해야 콜백이 전달돼요.
void GameLoop()
{
    Base_RunCallback();
}

콜백 성공은 브라우저 실행까지를 의미해요
콜백의 성공 여부는 외부 브라우저가 열렸는지까지를 알려줘요. 브라우저가 열린 뒤 웹 서비스에서 일어나는 인증 결과는 콜백으로 전달되지 않아요.


API 직접 연동

SDK를 사용하지 않는 게임이 SSO API를 직접 호출하는 예외 경로예요. State 발급·저장, 토큰 조회·쿠키 셋팅, 토큰 갱신을 게임이 직접 구현해요.

사전 준비

  • Game Client가 유효한 게임 AccessToken을 보유하고, 만료 시간을 추적·관리해야 해요.
  • SSO Gateway가 state 기반 토큰 저장·조회를 위해 Redis와 연동되어 있어야 해요.
  • SSO Gateway가 redirect_url 허용 도메인 검증 정책을 구성하고 있어야 해요.
  • web_token 사용 시 Auth Server가 게임 토큰을 웹 토큰으로 변환하는 API를 제공해야 해요.
  • Web Service가 SUAT·SURT 쿠키 기반 인증을 지원해야 해요.
  • Game Client가 게임 토큰 만료 전 자동 갱신 기능을 구현해야 해요.

개발 흐름

State 키 발급 및 토큰 값 저장

Game Client가 게임 AccessToken으로 state를 발급받아요. Sim API는 난수 state를 생성해 Redis에 게임 AccessToken과 매핑 저장하고 state를 반환해요.

  • 요청: POST /sim/auth/sso/key (헤더 access_token: {게임 AccessToken}, Content-Type: application/json)
  • 응답 성공: { "code": 0, "message": "ok", "value": "{state}" }
  • state 유효 시간은 10분, 일회성
토큰 조회 및 쿠키 셋팅 (+ redirect)

발급받은 state로 Callback을 호출하면, Sim API가 redirect_url 도메인을 검증하고 Redis에서 게임 AccessToken을 조회해요. mode에 따라 인증 쿠키를 발급한 뒤 최종 서비스로 302 리다이렉트해요.

Sim API의 처리 순서예요.

  1. state 존재 여부 확인
  2. redirect_url 형식·허용 도메인 검증
  3. Redis에서 state에 연결된 게임 AccessToken 조회
  4. 사용된 state 삭제(재사용 불가 처리)
  5. mode에 따라 인증 토큰 결정
  6. 인증 쿠키를 HTTP 응답에 설정
  7. 검증된 redirect_url로 302 Redirect
토큰 갱신 및 쿠키 셋팅 (+ redirect)

인증 토큰 갱신 주체는 게임이나 앱(Game Client)이에요. 게임 AccessToken 만료 전에 새 state를 발급받아 같은 절차를 다시 수행하면 인증 쿠키가 자동으로 갱신돼요.

항목
갱신 주체 인증 토큰을 관리하는 게임 또는 앱(SDK)
만료 시간 6시간
갱신 시점 만료 10~30분 전
갱신 후 액션 state 키를 재발급받은 후 SSO 프로세스를 다시 진행

갱신 시 기존 state를 재사용하지 마세요
갱신할 때도 반드시 새 state를 발급해야 해요. 만료·사용된 state로는 인증이 실패해요.

자동 갱신을 지원하지 않는 환경에서는 다음과 같이 처리하세요.

토큰이 만료된 상태에서 WebView 내 콘텐츠에서 사용자 액션이 발생하면, 토큰 만료 안내를 표시하고 WebView를 종료하거나 재인증을 진행하도록 처리해 주세요.

토큰 만료 시 처리 방식은 서비스별 요구사항에 따라 달라질 수 있어요. 서비스 개발자와 사전에 협의한 후 구현해 주세요.

트러블슈팅

오류 상황별 처리

SSO 처리 중 오류가 발생하면 공통 에러 페이지로 이동해요. 주요 오류 상황과 처리 방안이에요.

오류 상황Gateway 처리처리 방안
state 누락 / 만료 / 재사용요청 거부 / 인증 실패새 state를 발급받아 재시도하세요.
redirect_url 누락 / 허용되지 않은 도메인요청 거부허용 도메인 범위로 주소를 수정하세요.
mode 오류요청 거부 또는 기본값 적용game_token / web_token 중 동선에 맞게 지정하세요.
게임 토큰 조회 실패인증 실패로그인·토큰 갱신 후 state부터 다시 발급하세요.
웹 토큰 변환 실패일시적 오류재시도 후 지속되면 담당자에게 문의하세요.
Cookie 발급 실패 / 302 Redirect 실패인증 실패 / 오류 페이지웹뷰·브라우저의 쿠키 저장·리다이렉트 설정을 확인하세요.
mode별 에러 처리

에러는 웹뷰 밖에서 처리되므로 에러 페이지 이동 시 mode에 따라 파라미터 구성이 달라져요.

샘플 코드

PC Client (게임/앱)

표준화 개발된 Callback URL 빌더와 실행 코드예요. Native App (이하 App)의 실제 웹뷰 및 외부 브라우저 실행 메서드명은 App 명세에 맞게 적용해 주세요.

Callback URL 빌더
cpp
   // SsoUrl.h
   #pragma once
   #include <string>
   #include <sstream>
   #include <stdexcept>

   namespace sso {

   // RFC 3986 unreserved 외 문자를 %XX로 인코딩
   inline std::string UrlEncode(const std::string& value) {
       static const char hex[] = "0123456789ABCDEF";
       std::string out; out.reserve(value.size() * 3);
       for (unsigned char c : value) {
           if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
               (c >= '0' && c <= '9') ||
               c == '-' || c == '_' || c == '.' || c == '~') {
               out.push_back(static_cast<char>(c));
           } else {
               out.push_back('%');
               out.push_back(hex[c >> 4]);
               out.push_back(hex[c & 0x0F]);
           }
       }
       return out;
   }

   struct SsoParams {
       std::string state;                 // 필수
       std::string redirectUrl;           // 필수
       std::string mode  = "game_token";  // game_token | web_token
       std::string theme = "light";       // light | dark
       std::string gameId;
       std::string lang  = "ko";
   };

   inline std::string BuildSsoCallbackUrl(const SsoParams& p) {
       static const char* kBaseUrl =
           "https://api.onstove.com/sim/auth/session/callback";
       if (p.state.empty())       throw std::invalid_argument("state is required.");
       if (p.redirectUrl.empty()) throw std::invalid_argument("redirect_url is required.");
       std::ostringstream url;
       url << kBaseUrl
           << "?state="        << UrlEncode(p.state)
           << "&redirect_url=" << UrlEncode(p.redirectUrl)
           << "&mode="         << UrlEncode(p.mode.empty()  ? "game_token" : p.mode)
           << "&theme="        << UrlEncode(p.theme.empty() ? "light"      : p.theme)
           << "&lang="         << UrlEncode(p.lang.empty()  ? "ko"         : p.lang);
       if (!p.gameId.empty()) url << "&game_id=" << UrlEncode(p.gameId);
       return url.str();
   }

 } // namespace sso
웹뷰 실행 (mode=game_token)
cpp
#include "include/cef_browser.h"
#include "include/cef_frame.h"
#include "SsoUrl.h"

void NavigateSso(CefRefPtr<CefBrowser> browser, const sso::SsoParams& baseParams) {
    if (!browser) return;
    sso::SsoParams params = baseParams;
    params.mode = "game_token";  // 웹뷰는 game_token
    const std::string url = sso::BuildSsoCallbackUrl(params);
    browser->GetMainFrame()->LoadURL(CefString(url));  // CefString은 UTF-8 처리
}
외부 브라우저 실행 (mode=web_token)
csharp
using UnityEngine;

public static class SsoUnityBrowser
{
    // 외부 브라우저는 web_token (SUAT + SURT)
    public static void OpenExternal(
        string state, string redirectUrl, string gameId, string theme = "light")
    {
        string url = SsoUrlBuilder.Build(
            state, redirectUrl, "web_token", theme, gameId, "ko");
        Application.OpenURL(url);
    }
}

Mobile Client (게임/앱)

표준화된 Callback URL 빌더와 실행 코드입니다. Mobile 게임/앱의 실제 WebView 및 외부 브라우저 실행 메서드는 각 App의 명세에 맞게 적용해 주세요.

Callback URL 빌더
cpp
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public static class SsoUtil
{
   private const string CALLBACK_URL =
       "https://api.onstove.com/sim/auth/session/callback";

   public static string CreateMobileSsoUrl(
       string state,
       string redirectUrl,
       string mode = "game_token",
       string theme = "light",
       string gameId = "",
       string lang = "ko")
   {
       if (string.IsNullOrWhiteSpace(state))
       {
           throw new ArgumentException("state is required.", nameof(state));
       }

       if (string.IsNullOrWhiteSpace(redirectUrl))
       {
           throw new ArgumentException(
               "redirectUrl is required.",
               nameof(redirectUrl)
           );
       }

       var queryParams = new List<string>
       {
           $"state={UnityWebRequest.EscapeURL(state)}",
           $"redirect_url={UnityWebRequest.EscapeURL(redirectUrl)}",
           $"mode={UnityWebRequest.EscapeURL(mode)}",
           $"theme={UnityWebRequest.EscapeURL(theme)}",
           $"lang={UnityWebRequest.EscapeURL(lang)}"
       };

       if (!string.IsNullOrWhiteSpace(gameId))
       {
           queryParams.Add(
               $"game_id={UnityWebRequest.EscapeURL(gameId)}"
           );
       }

       return $"{CALLBACK_URL}?{string.Join("&", queryParams)}";
   }
}

// URL 생성 예제
string ssoUrl = SsoUtil.CreateMobileSsoUrl(
   state: state,
   redirectUrl: "https://service.onstove.com/main",
   gameId: "STOVE_LORD"
);
웹뷰 실행 (mode=game_token)
kotlin
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class SsoWebView {

   public static void openWebView(
           WebView webView,
           String ssoCallbackUrl
   ) {
       if (webView == null) {
           throw new IllegalArgumentException("webView is required.");
       }

       if (ssoCallbackUrl == null || ssoCallbackUrl.isEmpty()) {
           throw new IllegalArgumentException("ssoCallbackUrl is required.");
       }

       WebSettings settings = webView.getSettings();
       settings.setJavaScriptEnabled(true);
       settings.setDomStorageEnabled(true);

       webView.setWebViewClient(new WebViewClient());

       // SSO Callback URL을 최초 진입 주소로 사용
       webView.loadUrl(ssoCallbackUrl);
   }
}

// 사용 예제
String ssoUrl = SsoUtil.createMobileSsoUrl(
state,
"https://service.onstove.com/main",
"game_token",
   "light",
   "STOVE_LORD",
   "ko"
);

SsoWebView.openWebView(webView, ssoUrl);
외부 브라우저 실행 (mode=web_token)
kotlin
import android.content.Context
import android.content.Intent
import android.net.Uri

object SsoBrowser {

  fun openExternalBrowser(
    context: Context,
    ssoCallbackUrl: String
  ) {
      require(ssoCallbackUrl.isNotBlank()) {
          "ssoCallbackUrl is required."
      }

      val intent = Intent(
          Intent.ACTION_VIEW,
          Uri.parse(ssoCallbackUrl)
      ).apply {
          addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
      }

      context.startActivity(intent)
  }
}

// 사용 예제
val ssoUrl = SsoUtil.createMobileSsoUrl(
  state = state,
  redirectUrl = "https://service.onstove.com/main",
  mode = "web_token",      // 외부 브라우저는 web_token 권장
  gameId = "STOVE_LORD"
)

SsoBrowser.openExternalBrowser(
  context = this,
  ssoCallbackUrl = ssoUrl
)

Web Client (웹 서비스/WIC)

WebView에서 웹 콘텐츠의 링크를 선택했을 때, 지정한 Target 값에 따라 내부에서 실행하거나 외부 브라우저로 이동하는 JavaScript 예제예요.

window.open Target 옵션
설명
INTERNAL_BROWSER내부(현재 WebView) 브라우저에서 실행
EXTERNAL_BROWSER운영체제의 기본 외부 브라우저에서 실행

Target 옵션값은 SDK 또는 Game Client에서 별도로 구현해야 해요.
INTERNAL_BROWSEREXTERNAL_BROWSER는 SDK에서 정의한 커스텀 Target 값이에요. 따라서 해당 값을 인식하여 내부 실행 또는 외부 브라우저 실행으로 연결하도록 SDK 또는 Game Client에서 미리 연동되어 있어야 정상적으로 동작해요.

웹뷰 (game_token)

window.open() 메서드를 사용하여 새로운 WebView를 실행하는 예제예요.

target 값으로 INTERNAL_BROWSER를 지정하면 게임 내 새로운 WebView를 생성해요.

새로 생성된 WebView는 부모 WebView의 인증 쿠키를 공유하므로, 별도의 SSO 인증 과정을 다시 수행하지 않고 로그인 상태를 유지한 채 웹 서비스를 이용할 수 있어요.

외부 브라우저 (web_token)

window.open() 메서드를 사용하여 SSO Callback URL을 운영체제의 기본 외부 브라우저에서 실행하는 예제예요.

target 값으로 EXTERNAL_BROWSER를 지정하면 SDK 또는 Game Client가 운영체제의 기본 웹 브라우저를 실행하여 SSO Callback URL을 호출해요.

SSO Gateway는 전달받은 State를 검증하고 웹 인증 쿠키를 발급한 후, redirect_url로 이동시켜 로그인된 상태로 웹 서비스를 이용할 수 있도록 해줘요.

js
function openExternalBrowser({
    state, redirectUrl,
    mode = "web_token", theme = "light", game_id = "", lang = "ko"
}) {
    const url = new URL("/sim/auth/session/callback", window.location.origin);
    url.searchParams.set("state", state);
    url.searchParams.set("redirect_url", redirectUrl);
    url.searchParams.set("mode", mode);
    url.searchParams.set("theme", theme);
    url.searchParams.set("lang", lang);

    if (game_id) {
        url.searchParams.set("game_id", game_id);
    }

    window.open(url.toString(), "EXTERNAL_BROWSER", "noopener,noreferrer");  // 새 창
}

openExternalBrowser({
    state: "issued-state",
    redirectUrl: "https://service.onstove.com/main"
});

자주 묻는 질문



Q. SDK 방식과 API 직접 방식 중 무엇을 선택해야 하나요?
A. Mobile·PC SDK를 사용 중이라면 SDK 방식을 권장해요. API 직접 방식은 SDK를 사용하지 않는 일부 게임을 위한 예외 경로로, state 발급·Callback 호출·토큰 갱신을 게임이 직접 구현해야 해요.
Q. 웹뷰와 외부 브라우저 중 어느 mode를 선택해야 하나요?
A. 게임 화면 안에서 웹 서비스를 여는 웹뷰 동선은 game_token을 사용해요. 이용자 기본 브라우저로 여는 외부 브라우저 동선은 web_token을 사용해요.
game_token은 접근 토큰(SUAT)만, web_token은 접근·갱신 토큰(SUAT·SURT)을 함께 발급해요.
Q. PC SDK를 사용하면 state 발급·Callback 호출을 직접 구현하지 않아도 되나요?
A. 외부 브라우저로 여는 경우에 한해서예요. Base_OpenExternalUrl()을 호출하면 SDK가 게임 AccessToken 확인·state 발급·SSO Callback 호출·브라우저 실행을 대신 처리해요.
게임 화면 안 웹뷰로 여는 동선(mode=game_token)은 이 API의 대상이 아니므로, 개발 흐름 1~5단계를 그대로 구현해야 해요.
Q. 스팀으로 게임을 실행해도 SSO 연동이 되나요?
A. 스팀 런처로 실행한 경우에는 PC SDK의 Base_OpenExternalUrl()을 사용할 수 없어요. PCSDK 3.5.1에서는 사용할 수 있게 기능을 제공할 예정이에요.
Q. state는 재사용할 수 있나요?
A. 아니요, state는 일회성이에요. 유효 시간은 10분이며 한 번 사용하면 삭제돼요. 토큰 갱신 등으로 SSO를 다시 진행할 때도 반드시 새 state를 발급받아 주세요.
Q. 게임 AccessToken을 Callback URL에 직접 포함하면 안 되나요?
A. 안 돼요. 토큰이 URL에 노출되면 유출 위험이 있어요. 게임 AccessToken은 state 발급 API로 임시 저장하고, URL에는 발급받은 state만 전달해야 해요.
Q. redirect_url은 아무 주소나 지정해도 되나요?
A. 아니요, 허용 도메인(onstove.com, onstove.vn, gate8.vn, gate8.com, ppool.us, gameclub.ph) 범위여야 해요. Open Redirect 공격을 막기 위해 Gateway가 Hostname을 파싱해 검증하므로, 문자열 포함 방식의 우회 주소는 거부돼요.
Q. 인증 쿠키는 얼마나 유지되고 언제 갱신하나요?
A. 게임 AccessToken 만료 시간은 6시간이에요. 만료 10~30분 전에 새 state를 발급받아 SSO 절차를 다시 진행하면 인증 쿠키가 자동으로 갱신돼요. 갱신 주체는 토큰을 관리하는 게임 또는 앱이에요.
Q. SSO 처리 중 오류가 나면 이용자에게 무엇이 보이나요?
A. 공통 에러 페이지로 이동해요. 이때 theme·lang 파라미터가 반영되며, web_token 동선에서는 전달된 redirect_url이 있으면 해당 주소로, 없으면 기본 스토어 주소로 이동해요.