This is an example of language detection by priority. Fill in the service language coverage (`langCoverage`) according to each service.```javascript
// 1) URL 패스의 언어
const getLangByPath = () => {
const langCoverage = []; // 서비스 언어 커버리지
const lang = window.location.pathname.split('/')[1];
if (!lang) return null;
const lowerCaseLang = lang.toLowerCase();
return langCoverage.some((c) => c === lang) ? lowerCaseLang : null;
};
// 2) LOCALE cookie language (when there is no language in the URL path)
const getLangByCookie = () => {
const GNBLanguageCoverage = ; // GNB service language coverage
const lang = Cookies.get('LOCALE'); // Use external library for cookie lookup
if (!lang) return null;
const lowerCaseLang = lang.toLowerCase();
return GNBLanguageCoverage.includes(lowerCaseLang) ? lowerCaseLang : null;
};
// 3) Browser language (when not in cookies either)
const getNavigatorLang = () => {
const lang = window.navigator.language;
return lang.startsWith('zh') ? lang : lang.replace(/-\S+/g, '');
};
</div>
</details>
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:16px;font-weight:400;line-height:26px;letter-spacing:-0.48px;"><code>customChangeLanguage</code>를 <code>true</code>로 두면 언어 변경 시 쿠키를 바꾼 뒤 <code>change-language</code> 이벤트를 전달해요. <code>false</code>(기본)면 쿠키를 바꾼 뒤 <code>useLanguageCodeFromPath</code>가 <code>true</code>면 URL 언어 패스를 바꿔 이동하고, 아니면 페이지를 새로고침해요. 이벤트 처리 예시는 아래 [샘플 코드]의 이벤트 수신 탭을 참고해요.</p>
<div style="font-size:1.0em;font-weight:bold;margin:24px 0 12px;">옵션</div>
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:16px;font-weight:400;line-height:26px;letter-spacing:-0.48px;"><code>mount()</code>에 전달하는 옵션이에요. 서비스에 필요한 옵션만 선택해 지정해요.</p>
<table style="width:100%;table-layout:fixed;border-collapse:collapse;border-top:1px solid rgba(0,0,0,0.08);border-bottom:1px solid rgba(0,0,0,0.08);">
<thead>
<tr>
<th style="padding:12px;text-align:left;font-weight:normal;color:#314158;border-bottom:1px solid rgba(0,0,0,0.08);background-color:#F8FAFC;width:26%;">옵션</th>
<th style="padding:12px;text-align:left;font-weight:normal;color:#314158;border-bottom:1px solid rgba(0,0,0,0.08);background-color:#F8FAFC;width:10%;">필수</th>
<th style="padding:12px;text-align:left;font-weight:normal;color:#314158;border-bottom:1px solid rgba(0,0,0,0.08);background-color:#F8FAFC;width:16%;">기본값</th>
<th style="padding:12px;text-align:left;font-weight:normal;color:#314158;border-bottom:1px solid rgba(0,0,0,0.08);background-color:#F8FAFC;">설명</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>logArea</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">필수</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">""</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">로그 수집용 로그 영역. 서비스 메인 주소를 기입 (예: <code>https://store.onstove.com</code>)</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>useLanguageCodeFromPath</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">선택</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">false</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;"><code>true</code> 시 URL Path의 언어코드를 감지해 언어 설정</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>serviceTitle.pc / .mobile</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">선택</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">""</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">스토브 로고 우측 서비스 타이틀 (HTML string). PC·모바일 개별 지정</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>widget.notification</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">선택</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">true</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">알림 노출 여부</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>widget.stoveDownload</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">선택</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">false</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">스토브 설치 버튼 노출 여부</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>widget.languageSelect</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">선택</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">true</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">언어 선택 노출 여부</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>widget.themeSelect</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">선택</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">true</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">테마 선택 노출 여부</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>widget.stoveMenu.active / .mobile</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">선택</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">false / true</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">기본 메뉴 노출 여부. <code>mobile</code>은 <code>active=true</code>일 때만 적용</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>global.languageCoverages</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Select</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">['en','zh-cn','zh-tw','ja','ko']</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">List of languages to display as language buttons. If the default language (en) is missing, it will be added automatically.</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>global.defaultSelectedLanguage</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Select</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">'en'</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">The default language selected when no other language is available according to language policy.</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>global.customChangeLanguage</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Select</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">false</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;"><code>true</code> Send custom event after changing language</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>loginMethod.redirectCurrentPage</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Select</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">true</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Redirect location after login. <code>true</code> is the current page, <code>false</code> is the account domain default page</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>mode.theme.support / .default</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Select</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">["light"] / "light"</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">List of supported themes and the default theme. Specify a combination of <code>light</code>·<code>dark</code></td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>mode.mini</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Select</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">false</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Whether to use the mini version (reduced vertical width, 48px height)</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>mode.layout</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Select</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">"wide"</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Layout mode. <code>wide</code> / <code>fix</code></td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>mode.fixed</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Select</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">true</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Whether to fix the top. If fixed, the GNB remains at the top during scrolling.</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;color:#314158;font-size:14px;font-weight:500;"><code>userMenu.coupon</code></td>
<td style="padding:12px;vertical-align:top;color:#314158;font-size:14px;font-weight:400;">Select</td>
<td style="padding:12px;vertical-align:top;color:#314158;font-size:14px;font-weight:400;">true</td>
<td style="padding:12px;vertical-align:top;color:#314158;font-size:14px;font-weight:400;">Whether to display the coupon box in the user info menu</td>
</tr>
</tbody>
</table>
<div style="font-size:1.0em;font-weight:bold;margin:24px 0 12px;">Option Preview</div>
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:16px;font-weight:400;line-height:26px;letter-spacing:-0.48px;">These are actual display examples of major options.</p>
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:14px;font-weight:500;margin-bottom:4px;"><code>serviceTitle</code> — Service title to the right of the Stove logo (PC / Mobile)</p>
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_pc_title.png" width="600">
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_mobile_title.png" width="450">
<div style="margin-top:12px;"></div>
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:14px;font-weight:500;margin-bottom:4px;"><code>widget</code> — Notifications / Install Stove / Language Selection / Theme Selection</p>
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_alert_menu.png" width="75">
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_stove_download.png" width="150">
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_lang_menu_btn.png" height="375">
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_theme_menu_btn.png" height="375">
<div style="margin-top:12px;"></div>
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:14px;font-weight:500;margin-bottom:4px;"><code>widget.stoveMenu</code> — Basic menu (PC / Mobile)</p>
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_stove_menu.png" width="1000">
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_stove_menu_mobile.png" height="500">
<div style="margin-top:12px;"></div>
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:14px;font-weight:500;margin-bottom:4px;"><code>global.languageCoverages</code> / <code>mode.theme</code> — Language List / Theme Settings Popup</p>
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_lang_select_menu.png" height="225">
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_theme_popup.png" height="225">
<div style="margin-top:12px;"></div>
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:14px;font-weight:500;margin-bottom:4px;"><code>mode.layout</code> / <code>userMenu.coupon</code> — Layout / My Info Coupon Box</p>
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_layout.png" height="375">
<img src="https://d2x8kymwjom7h7.cloudfront.net/live/application_no/STATIC/developer-center/WEB/ko_web_gnb_img_userMenu.png" height="375">
<div style="font-size:1.0em;font-weight:bold;margin:24px 0 12px;">Theme Option Details</div>
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:16px;font-weight:400;line-height:26px;letter-spacing:-0.48px;">Set the list of themes supported by the service and the default theme using <code>mode.theme</code>. Configure it as shown below according to the supported combinations.</p>
```javascript
// 다크·라이트 모두 지원
mode: {
theme: {
support: ["dark", "light"],
default: "dark" // default는 서비스 기획에 따라 설정
}
}
// 다크만 지원
mode: { theme: { support: ["dark"], default: "dark" } }
// 라이트만 지원
mode: { theme: { support: ["light"], default: "light" } }
This is the theme application flow based on the presence of theme cookies and the support list (support).



Custom Areas and Runtime Changes
The GNB menu area can only be extended within the designated custom area (customMenuArea). Disable the default menu (widget.stoveMenu.active=false) and receive the mount event delivered by the GNB to render the service menu directly. Customization is not supported outside of the custom area.
mount() You can change options during runtime using updateOptions() of the GNB instance provided as the return value of . Runtime changes only apply to serviceTitle and widget.stoveMenu, and other options are ignored.
!infoIdentify the custom timing with mount events
ㆍ mounted: Delivered when the GNB 1depth container is mounted. You can customize customMenuArea.
ㆍ menu-mounted: Delivered when the skeleton of the GNB 1depth menu area is turned off and exposed.
This is an example of loading the GNB module, mounting it with options, and receiving mount, language, and theme events. Please apply the module host address according to your environment.
=== "Option Integration"
<div id="stove-gnb-wrapper"></div>
<script defer>
(function () {
const script = document.createElement('script');
script.src = 'https://js-cdn.onstove.com/libs/common-gnb/latest/stove-gnb.js'; // 환경별 적용 필요
script.onload = () => {
if (window.StoveGnb) {
window.StoveGnb.mount('#stove-gnb-wrapper', {
logArea: 'https://도메인주소를입력해주세요',
useLanguageCodeFromPath: true, // URL 언어 패스 미사용 시 false
serviceTitle: {
pc: '',
mobile: '서비스 타이틀(모바일)'
},
widget: {
stoveMenu: {
active: true, // 기본 메뉴 비활성화 시 false
mobile: true
}
}
});
}
};
document.body.appendChild(script);
})();
</script>
=== "Event Reception"
<div id="stove-gnb-wrapper"></div>
<script defer>
(function () {
const script = document.createElement('script');
script.src = 'https://js-cdn.onstove.com/libs/common-gnb/latest/stove-gnb.js'; // 환경별 적용 필요
script.onload = () => {
if (window.StoveGnb) {
const gnbEventHandler = (event) => {
if (event.detail.type === 'mounted') {
// 마운트 이벤트 수신: customMenuArea 커스텀
const area = document.getElementById('customMenuArea');
}
if (event.detail.type === 'change-language') {
// 언어 변경 이벤트 수신
}
if (event.detail.type === 'change-theme-mode') {
// 테마 변경 이벤트 수신
}
};
window.removeEventListener('GNB', gnbEventHandler);
window.addEventListener('GNB', gnbEventHandler);
window.StoveGnb.mount('#stove-gnb-wrapper', {
logArea: 'https://도메인주소를입력해주세요'
// 언어·테마 변경 옵션이 활성화되어 있어야 이벤트가 전달돼요
});
}
};
document.body.appendChild(script);
})();
</script>
=== "Runtime Option Changes"
// mount()의 반환 인스턴스로 런타임 중 옵션 변경
const mountedInstance = window.StoveGnb.mount('#stove-gnb-wrapper', { /* GNB 옵션 */ });
// serviceTitle, widget.stoveMenu만 런타임 적용
mountedInstance.gnb.updateOptions({
serviceTitle: {
pc: '',
mobile: ''
},
widget: {
stoveMenu: {
active: true,
mobile: true
}
}
});
### Login URL Method
This method involves integrating the Stove login page directly without using the GNB. The web service generates and calls the login page URL, and handles account login using cookies (token, country, language information, etc.) issued after login is complete.
- The web service (official website) domain must be in the form of
xxx.game.onstove.com to use Stove authentication. - If you are configuring external infrastructure separately, you must issue and set up an SSL certificate. (Issued by Technical PM)
- You must obtain
inflow_path and game_no for identifying the entry path through the Technical PM. - You must have an account with Stove registration completed on the web for integration testing.
Generate and call the Stove login page URL including parameters, and once login is complete, redirect to redirect_url. The web service checks for tokens such as SUAT in the response cookies to process the login status.
game_no·inflow_path·redirect_url are specified as query parameters to generate the Stove login page URL. redirect_url must be URL-encoded. 2. Call the generated login page URL. 3. The user completes the login on the Stove login page. 4. After the login is complete, the user is redirected to the redirect_url and an authentication cookie is set. 5. The web service checks the SUAT(Web Access Token) in the cookie to process the login status. ```mermaid
sequenceDiagram
autonumber
participant U as 사용자
participant W as Web Service
participant L as 스토브 로그인 페이지
W->>W: 로그인 URL 생성 (game_no, inflow_path, redirect_url)
W->>L: 로그인 페이지 URL 호출
U->>L: 스토브 계정 로그인
L-->>W: redirect_url 이동 + 인증 쿠키(SUAT 등) 설정
W->>W: 쿠키에서 SUAT 확인 후 로그인 상태 처리
<div style="font-size:1.0em;font-weight:bold;margin:24px 0 12px;">Request Parameters</div>
<table style="width:100%;table-layout:fixed;border-collapse:collapse;border-top:1px solid rgba(0,0,0,0.08);border-bottom:1px solid rgba(0,0,0,0.08);">
<thead>
<tr>
<th style="padding:12px;text-align:left;font-weight:normal;color:#314158;border-bottom:1px solid rgba(0,0,0,0.08);background-color:#F8FAFC;width:20%;">Parameter</th>
<th style="padding:12px;text-align:left;font-weight:normal;color:#314158;border-bottom:1px solid rgba(0,0,0,0.08);background-color:#F8FAFC;width:12%;">Required</th>
<th style="padding:12px;text-align:left;font-weight:normal;color:#314158;border-bottom:1px solid rgba(0,0,0,0.08);background-color:#F8FAFC;width:26%;">Example</th>
<th style="padding:12px;text-align:left;font-weight:normal;color:#314158;border-bottom:1px solid rgba(0,0,0,0.08);background-color:#F8FAFC;">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>game_no</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Required</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">45</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Game number issued upon entry</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>inflow_path</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">Required</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">STOVE_GAMEID (Uppercase)</td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">User inflow path identifier. Issued via technical PM when entering Stove</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;color:#314158;font-size:14px;font-weight:500;"><code>redirect_url</code></td>
<td style="padding:12px;vertical-align:top;color:#314158;font-size:14px;font-weight:400;">Required</td>
<td style="padding:12px;vertical-align:top;color:#314158;font-size:14px;font-weight:400;">https://test.game.onstove.com/</td>
<td style="padding:12px;vertical-align:top;color:#314158;font-size:14px;font-weight:400;">URL to redirect to after login (URL-encoded). <code>xxxx.onstove.com</code> domain only allowed</td>
</tr>
</tbody>
</table>
<br />
**Request Format Example**
https://accounts.onstove.com/login
?inflow_path={INFLOW_PATH}
&game_no={GAME_NO}
&redirect_url={REDIRECT_URL}
<div style="font-size:1.0em;font-weight:bold;margin:24px 0 12px;">Issued Cookies</div>
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:16px;font-weight:400;line-height:26px;letter-spacing:-0.48px;">Once login is complete, an authentication cookie is set. The web service identifies the login status using <code>SUAT</code>. In addition to SUAT, various cookies are delivered depending on whether the user is logged in or not.</p>
<table style="width:100%;table-layout:fixed;border-collapse:collapse;border-top:1px solid rgba(0,0,0,0.08);border-bottom:1px solid rgba(0,0,0,0.08);">
<thead>
<tr>
<th style="padding:12px;text-align:left;font-weight:normal;color:#314158;border-bottom:1px solid rgba(0,0,0,0.08);background-color:#F8FAFC;width:26%;">Cookie</th>
<th style="padding:12px;text-align:left;font-weight:normal;color:#314158;border-bottom:1px solid rgba(0,0,0,0.08);background-color:#F8FAFC;">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:500;"><code>SUAT</code></td>
<td style="padding:12px;vertical-align:top;border-bottom:1px solid rgba(0,0,0,0.08);color:#314158;font-size:14px;font-weight:400;">STOVE User Access Token. Access Token that identifies an authenticated user</td>
</tr>
<tr>
<td style="padding:12px;vertical-align:top;color:#314158;font-size:14px;font-weight:500;">Additional cookies before/after login</td>
<td style="padding:12px;vertical-align:top;color:#314158;font-size:14px;font-weight:400;">Additional information cookies such as language, country, regulation, and timezone are also issued. Refer to the table below</td>
</tr>
</tbody>
</table>
<br />
<details style="margin:12px 0 0;border:1px solid #e3e6ea;border-radius:8px;overflow:hidden;" markdown="1">
<summary style="cursor:pointer;list-style:none;padding:14px 18px;background-color:#FAFAFA;font-size:16px;font-weight:600;color:#16181d;">Cookie information before login<span style="font-size:13px;font-weight:500;color:#8a9099;margin-left:8px;">COVERAGES · LOCALE · NNTO, etc.</span></summary>
<div style="padding:16px 18px 4px;" markdown="1">
| Cookie | Example | Description |
|---|---|---|
| **COVERAGES** | `de, en, es, fr, id, ja, ko, pt, th, vi, zh, zh-tw` (URL Encoding) | GDS Coverages information. Used to display the list of languages that can be changed in the GNB (`vi`, `zh`, `id` are not supported by Onstove, Header-only cookies) |
| **LOCALE** | `KO` | Language code set on the Onstove webpage. If it is the first visit or no previous setting exists, it is set to the browser language code |
| **NNTO** | `KR` | Stores the access country code before login, and the registration country code after login |
| **PRM** | `KO` | Stores the language code set in the browser |
| **REGULATION** | `KOREA` | Stores GDS country-specific regulation information |
| **TZ** | `Asia/Seoul` | Stores GDS Timezone information |
| **TZ_OFFSET** | `540` | Stores GDS UTC Offset information |
| **dvc** | `pc`, `m` | Access device information (`pc`: PC, `m`: Mobile) |
</div>
</details>
<details style="margin:12px 0 0;border:1px solid #e3e6ea;border-radius:8px;overflow:hidden;" markdown="1">
<summary style="cursor:pointer;list-style:none;padding:14px 18px;background-color:#FAFAFA;font-size:16px;font-weight:600;color:#16181d;">Cookie information after login<span style="font-size:13px;font-weight:500;color:#8a9099;margin-left:8px;">SUAT · HD · PLD · SIGN · RFT, etc.</span></summary>
<div style="padding:16px 18px 4px;" markdown="1">
| Cookie | Example | Description |
|---|---|---|
| **SUAT** | `Access Token` | STOVE User Access Token. Access Token that identifies an authenticated user |
| **HD** | `eyJhbGciOiJIUzI1NiJ9` | Header area of the JWT Access Token (`.` first string separated by) |
| **PLD** | `eyJhcHBsaWNhdGlvbl9ubyI6...` | Payload area of the JWT Access Token (`.` second string separated by) |
| **SIGN** | `cbzoplX31qyd9iyCDEd0...` | Signature area of the JWT Access Token (`.` third string separated by) |
| **RFT** | `eyJhbGciOiJIUzI1NiJ9...` | JWT Refresh Token |
| **FOREVER** | `Y`, `N` | Keep me logged in (`Y`: Keep, `N`: Do not keep) |
| **LTC** | `0` | Login error code (loginErrorCode) |
| **LTN** | `0` | Whether a login error occurred (isUsed) |
| **LTU** | `""` | Number of login attempts (loginTryNum). CAPTCHA after 5 failures, blocked after 10 failures |
| **n_uid** | `2744ffd704f574a0...` | Cookie for managing Third-party Access Token or State information |
| **page_uid** | `6da4bd9920526f15...` | Cookie for anti-macro during STOVE login |
</div>
</details>
#### Troubleshooting
| Situation | Cause | Action |
|---|---|---|
| Login page does not open | Missing required parameters (<code>game_no</code>·<code>inflow_path</code>·<code>redirect_url</code>) | Include all three parameters and URL-encode the <code>redirect_url</code>. |
| Redirect failed after login | <code>redirect_url</code> is not an allowed domain | Specify the address within the <code>xxxx.onstove.com</code> domain scope. |
| Authentication cookie not found | Domain mismatch or SSL not configured | Check the service domain/SSL configuration and contact the technical PM. |
| Inflow path not aggregated | <code>inflow_path</code> not issued or entered incorrectly | Provide the value issued by the technical PM in uppercase exactly. |
#### Sample Code
<p style="color:#314158;font-family:'Spoqa Han Sans Neo';font-size:16px;font-weight:400;line-height:26px;letter-spacing:-0.48px;">This is an example of generating and calling a STOVE login page URL by specifying parameters. Please apply the domain according to your environment.</p>
::dc-tabs
:::dc-tab-item{label="JavaScript"}
```javascript
// 스토브 로그인 페이지 URL 생성 및 호출
function openStoveLogin({ gameNo, inflowPath, redirectUrl }) {
const base = "https://accounts.onstove.com/login"; // 환경별 적용 필요
const url = new URL(base);
url.searchParams.set("inflow_path", inflowPath); // 대문자
url.searchParams.set("game_no", gameNo);
url.searchParams.set("redirect_url", redirectUrl); // URLSearchParams가 인코딩 처리
window.location.href = url.toString();
}
openStoveLogin({
gameNo: "45",
inflowPath: "STOVE_GAMEID",
redirectUrl: "https://test.game.onstove.com/"
});
:::
::
Q. Should I choose the GNB method or the login URL method?
A. We recommend the GNB method if you want to provide common UI elements such as sign-up, language, theme, and game navigation in addition to login. If you only want to integrate the login flow without common UI elements, you can use the login URL method to call the STOVE login page directly.
Q. What domain should I use to use STOVE authentication?
A. The web service being integrated must use an onstove.com series domain (e.g., xxx.game.onstove.com). If you are configuring it with external infrastructure, an SSL certificate is required, and domain connection/issuance is handled through the publishing technical representative (Technical PM).
Q. How is the GNB display language determined?
A. It is determined in the following order: URL path language → LOCALE cookie → browser language → service default language. If a valid language is not found in the previous step, it moves to the next step, and the final fallback for the entire web service is English. The GNB operates on the premise of a page refresh when the language is changed.
Q. Can I customize the GNB menu to fit my service?
A. You can only expand it within the designated custom area (customMenuArea). You can disable the default menu (widget.stoveMenu.active=false) and receive the mounted / menu-mounted events sent by the GNB to render the service menu directly. Customization is not supported outside of the custom area.
Q. What GNB options can be changed at runtime?
A. You can only change serviceTitle and widget.stoveMenu at runtime using updateOptions() of the instance returned by mount(). Other options are ignored, so they must be specified at the initial mount() point.
Q. How do I check the login result in the login URL method?
A. When the login is complete, it redirects to the redirect_url and an authentication cookie is set. The web service checks the login status using the SUAT (Web Access Token) in the response cookie. In addition to the SUAT, additional cookies such as language, country, and regulations are also delivered.
Q. Are there any restrictions on the redirect_url?
A. The redirect_url must be xxxx.onstove.comIt is limited to pages that can be used as domains. The target page must be verified by the publishing technical manager before integration, and firewall settings for communication between the game server and the STOVE API server must be completed in advance.
Q. How do I verify the SUAT issued after login?
A. The issued SUAT must be verified on the server side. For cache optimization to reduce repeated verification calls, please refer to the [웹 서비스 세션 최적화](/docs/stove/guide/session) guide.