— BROWSER (JS) + UNITY (WebGL / STANDALONE) CLIENT SDK —
A client-side SDK guide for integrating the AltsCodex OAuth login flow. The JavaScript SDK covers browser environments; the Unity SDK targets WebGL and Standalone (Windows / macOS / Linux) game clients. Both never see the client_secret — they only return a short-lived JWT that your game backend exchanges via the server SDKs.
AltsCodex OAuth 로그인 흐름을 클라이언트 측에서 연동하는 가이드입니다. JavaScript SDK 는 브라우저 환경, Unity SDK 는 WebGL 및 Standalone(Windows / macOS / Linux) 게임 클라이언트를 다룹니다. 두 SDK 모두 client_secret 을 보지 않고, 짧은 수명의 JWT 만 반환합니다 — 이를 게임 백엔드로 보내 서버 SDK 로 교환합니다.
Integrate the AltsCodex frontend SDK in 4 steps. 4단계로 AltsCodex 프론트엔드 SDK를 연동하세요.
Install the SDK using npm. npm을 사용하여 SDK를 설치합니다.
npm install @altscodex/sdk
Choose your import method: Import 방법을 선택하세요:
import AltsCodex from '@altscodex/sdk';
const AltsCodex = require('@altscodex/sdk');
Create a AltsCodex instance using the client credentials issued from the developer center. AltsCodex 인스턴스를 생성합니다. 개발자 센터에서 발급받은 클라이언트 정보를 사용하세요.
| Parameter | Type | Required | Description |
|---|---|---|---|
| altscodexUrl | string | Required | AltsCodex server base URL AltsCodex 서버 base URL |
| clientId | string | Required | Client ID issued from the developer center 개발자센터에서 발급받은 클라이언트 ID |
| redirectUri | string | Required | URI to redirect to after OAuth authorization OAuth 인가 후 리다이렉트될 URI |
| responseType | string | Optional | OAuth response type (default: 'code') OAuth response type (default: 'code') |
| popupWidth | number | Optional | Popup width (default: 600) 팝업 너비 (default: 600) |
| popupHeight | number | Optional | Popup height (default: 500) 팝업 높이 (default: 500) |
const sdk = new AltsCodex({
altscodexUrl: 'https://your-altscodex.com',
clientId: 'your-client-id',
redirectUri: 'https://your-app.com/callback',
});
sdk.login(options?) —
Opens an OAuth popup and returns the login result as a Promise.
OAuth 팝업을 열고 로그인 결과를 Promise로 반환합니다.
{ from: "altscodex", type: "success"|"fail", data: JWT|ERROR_MSG } is sent to the parent window. The SDK handles this automatically.
팝업 창에서 로그인이 완료되면 { from: "altscodex", type: "success"|"fail", data: JWT|ERROR_MSG } 형식의 postMessage를 부모 창으로 전송합니다. SDK가 이를 자동으로 처리합니다.
| Parameter | Type | Required | Description |
|---|---|---|---|
| state | string | Optional | CSRF state value (auto-generated if omitted) CSRF 방지용 state 값 (미입력 시 자동 생성) |
| timeout | number | Optional | Login timeout in ms (default: 120000) 로그인 타임아웃 ms (default: 120000) |
try {
const { jwt } = await sdk.login({ state: String(Date.now()) });
console.log('JWT:', jwt);
// JWT를 게임 백엔드로 전달
await fetch('/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jwt }),
});
} catch (err) {
console.error('Login failed:', err.message);
}
Manage tokens and handle logout after login. 로그인 후 토큰을 관리하고 로그아웃을 처리합니다.
| Method | Returns | Description |
|---|---|---|
| sdk.logout(options?) | Promise<void> | Deactivates De-OAuth server JWT + clears localStorage De-OAuth 서버 JWT 비활성화 + localStorage 정리 |
| sdk.getToken() | string | null | Returns stored access_token 저장된 access_token 반환 |
| sdk.getRefreshToken() | string | null | Returns stored refresh_token 저장된 refresh_token 반환 |
| sdk.getCode() | string | null | Returns stored OAuth code 저장된 OAuth code 반환 |
| sdk.isLoggedIn() | boolean | Whether access_token exists access_token 존재 여부 |
| sdk.refresh(options) | Promise<{...}> | Refresh token (clientSecret required) 토큰 갱신 (clientSecret 필수) |
// 로그아웃
await sdk.logout();
// 토큰 확인
if (sdk.isLoggedIn()) {
const token = sdk.getToken();
console.log('Token:', token);
}
clientSecret
is exposed in the browser when used on the frontend. For security-sensitive operations, use it only on the backend. Calling refresh() on the frontend includes clientSecret in the JavaScript bundle, visible to anyone.
은 프론트엔드에서 사용 시 브라우저에 노출됩니다. 보안이 필요한 경우 백엔드에서만 사용하세요. 프론트엔드에서 refresh()를 호출하면 clientSecret이 JavaScript 번들에 포함되어 누구나 확인할 수 있습니다.
// ⚠️ 프론트엔드에서 refresh() 사용 시 clientSecret 노출 주의
const result = await sdk.refresh({
clientSecret: 'your-client-secret', // 브라우저에 노출됨!
});
console.log('New token:', result.accessToken);
Error messages and their causes from the SDK. SDK에서 발생할 수 있는 에러 메시지와 원인입니다.
| Error Message | Cause |
|---|---|
| Popup blocked | Browser popup blocked 브라우저 팝업 차단 설정 |
| User closed the login window | User closed the popup window 사용자가 팝업 창을 닫음 |
| Login failed: {reason} | Error during login processing 로그인 처리 중 오류 발생 |
| Login timeout | No response within timeout (default 120s) timeout 시간 내 응답 없음 (default 120초) |
try {
const { jwt } = await sdk.login();
} catch (err) {
if (err.message.includes('Popup blocked')) {
alert('팝업을 허용해주세요.');
} else if (err.message.includes('User closed')) {
console.log('사용자가 로그인을 취소했습니다.');
} else if (err.message.includes('timeout')) {
console.error('로그인 시간이 초과되었습니다.');
} else {
console.error('로그인 오류:', err.message);
}
}
The SDK does not read process.env or import.meta.env itself — it accepts plain options. Inject them from your build environment so secrets stay out of source code.
SDK 자체는 process.env / import.meta.env 를 읽지 않습니다. 옵션으로 직접 전달받습니다. 빌드 환경에서 .env 로 주입해 시크릿이 소스코드에 남지 않도록 하세요.
# .env.production
VITE_ALTSCODEX_URL=https://altscodex.com
VITE_CLIENT_ID=your-registered-client-id
VITE_REDIRECT_URI=https://yourapp.com/callback
// AuthContext.tsx
import AltsCodex from '@altscodex/sdk';
const sdk = new AltsCodex({
altscodexUrl: import.meta.env.VITE_ALTSCODEX_URL,
clientId: import.meta.env.VITE_CLIENT_ID,
redirectUri: import.meta.env.VITE_REDIRECT_URI,
});
# .env.local (server side)
ALTSCODEX_AUTH_SERVER_URL=https://api.altscodex.com
ALTSCODEX_CLIENT_ID=your-registered-client-id
ALTSCODEX_CLIENT_SECRET=your-client-secret # NEVER expose to the browser
ALTSCODEX_REDIRECT_URI=https://yourapp.com/getinfo
Use a separate .env.<mode> file per environment (local / staging / production). Vite picks the file by --mode; Next.js picks by NODE_ENV.
환경별로 .env.<mode> 파일을 분리하세요. Vite 는 --mode 로, Next.js 는 NODE_ENV 로 파일을 선택합니다.
| Purpose | Production | Local development |
|---|---|---|
| Frontend | https://altscodex.com (or www.) |
http://localhost:3000 |
| Backend / API | https://api.altscodex.com |
http://localhost:3000 |
| Developer Center | https://developers.altscodex.com |
— |
Do NOT invent subdomains like login.altscodex.com, oauth.altscodex.com, auth.altscodex.com. They resolve to NXDOMAIN and the popup silently fails with User closed the login window after a long timeout.
login.altscodex.com, oauth.altscodex.com, auth.altscodex.com 같은 미등록 서브도메인을 임의로 사용하지 마세요. NXDOMAIN 이 떨어지고 팝업이 한참 후 User closed the login window 로 조용히 실패합니다.
clientId and redirectUri first
2. clientId / redirectUri 사전 등록 필수
Register your application here at the Developer Center to obtain a clientId and clientSecret. Hard-coding values that are not registered (or a redirectUri that does not exactly match the registered value — including trailing slash) results in invalid_client / redirect_uri mismatch 401 errors.
개발자 센터에서 애플리케이션을 등록해 clientId / clientSecret 을 발급받으세요. 미등록 값을 박거나 redirectUri 가 등록된 값과 정확히 일치하지 않으면 (트레일링 슬래시 포함) invalid_client / redirect_uri mismatch 401 오류가 발생합니다.
@webxcom/sdk v1.x
3. @webxcom/sdk v1.x 에서 마이그레이션
Old (@webxcom/sdk v1.x) |
New (@altscodex/sdk v2.x) |
|---|---|
import WebXCOM from '@webxcom/sdk' |
import AltsCodex from '@altscodex/sdk' |
new WebXCOM({ webxcomUrl: ... }) |
new AltsCodex({ altscodexUrl: ... }) |
WebXCOMBackend |
AltsCodexBackend |
webxcom_* localStorage keys |
altscodex_* localStorage keys |
Coexistence: the platform server emits postMessage in dual-broadcast mode — one with from: "altscodex" (consumed by v2.x SDK) and a second with from: "webxcom" (consumed by v1.x SDK). Existing v1.x apps continue to work unchanged during gradual migration.
양립 호환: 플랫폼 서버는 dual-broadcast 로 동작합니다. from: "altscodex" (v2.x SDK 수신) 과 from: "webxcom" (v1.x SDK 수신) 두 메시지를 동시에 발송합니다. 옛 v1.x 앱은 코드 변경 없이 동작합니다.
If your hosting page sets Cross-Origin-Opener-Policy: same-origin, the browser may block the SDK's popup.closed poll. The SDK degrades gracefully (stops polling and relies on postMessage + timeout), but a user closing the popup with the X button may not be detected. Recommended COOP for OAuth opener pages: same-origin-allow-popups or unsafe-none.
호스팅 페이지가 Cross-Origin-Opener-Policy: same-origin 을 보내면 SDK 의 popup.closed 폴링이 차단될 수 있습니다. SDK 는 graceful 하게 폴링을 중단하고 postMessage + timeout 으로 종료를 결정하지만, 사용자가 X 로 닫는 케이스는 감지 못할 수 있습니다. OAuth 팝업을 여는 페이지의 권장 COOP 정책: same-origin-allow-popups 또는 unsafe-none.
If your client is a Unity game, use the Unity SDK instead of the browser JavaScript SDK. It mirrors the same login flow (popup + JWT) but exposes a single async C# API: await AltsCodexLogin.LoginAsync(config).
클라이언트가 Unity 게임이라면 브라우저 JavaScript SDK 대신 Unity SDK 를 사용하세요. 동일한 로그인 흐름(popup + JWT)을 그대로 재현하되 비동기 C# API 하나로 노출합니다: await AltsCodexLogin.LoginAsync(config).
| Target | Status (0.1.x) | Mechanism |
|---|---|---|
WebGL |
✅ Supported | window.open popup + postMessage (JS SDK 와 동일 프로토콜) |
Standalone (Win / macOS / Linux) |
✅ Supported | Application.OpenURL + loopback HttpListener (RFC 8252) |
| Unity Editor (Play mode) | ✅ Supported | Standalone 경로 재사용 |
| iOS / Android / 기타 | ❌ Out of scope | OS 네이티브 플러그인 필요 — 0.2.x 로 연기 |
Open Window → Package Manager → + → Add package from git URL... and paste: Window → Package Manager → + → Add package from git URL... 에서 다음을 입력하세요:
https://github.com/alts-codex/unity-sdk.git#v0.1.0
Or edit Packages/manifest.json directly:
또는 Packages/manifest.json 을 직접 편집:
{
"dependencies": {
"com.alts-codex.auth-sdk": "https://github.com/alts-codex/unity-sdk.git#v0.1.0"
}
}
using System.Threading;
using UnityEngine;
using AltsCodex;
public class LoginButton : MonoBehaviour
{
public async void OnClick()
{
var config = new LoginConfig
{
ClientId = "YOUR_CLIENT_ID", // Developer Center 발급
RedirectUri = "https://yourgame.example.com/callback",
// AltsCodexUrl 기본값: https://altscodex.com
};
var result = await AltsCodexLogin.LoginAsync(config);
if (!result.Success)
{
Debug.LogWarning("login failed: " + result.ErrorMessage);
return;
}
// result.Jwt 를 게임 백엔드로 전송 → 백엔드가 Node/Python/Go SDK 로 슬롯 정보 조회
Debug.Log("JWT received, length=" + result.Jwt.Length);
}
}
LoginAsync calls into a bundled .jslib, which opens window.open(loginUrl) against altscodex.com. The popup posts back via postMessage and the bridge forwards the payload to C# through unityInstance.SendMessage(...). Your WebGL template must expose the instance: window.unityInstance = unityInstance; after createUnityInstance(...).
C# LoginAsync 가 번들된 .jslib 를 호출해 altscodex.com 으로 window.open(loginUrl). popup 이 postMessage 로 응답하면 브릿지가 unityInstance.SendMessage(...) 로 C# 에 전달합니다. WebGL 템플릿에서 반드시 인스턴스를 노출해야 합니다: createUnityInstance(...) 호출 후 window.unityInstance = unityInstance;.
http://127.0.0.1:<port>/callback via System.Net.HttpListener (ephemeral port by default, or pin via LoopbackPort), opens the OS default browser with Application.OpenURL, then waits for the platform server to redirect back with jwt + state query parameters. The Developer Center must whitelist this loopback URI (fixed port like http://127.0.0.1:17070/callback, or wildcard http://127.0.0.1:*/callback if supported).
SDK 가 System.Net.HttpListener 로 http://127.0.0.1:<port>/callback 바인딩(기본 ephemeral, LoopbackPort 로 고정 가능), Application.OpenURL 로 OS 기본 브라우저 열기, 플랫폼 서버가 jwt + state 쿼리 파라미터로 리다이렉트 대기. Developer Center 에 이 loopback URI 를 등록해야 합니다(http://127.0.0.1:17070/callback 고정 포트, 또는 지원 시 http://127.0.0.1:*/callback 와일드카드).
il2cpp_dumper / dnSpy. The Unity SDK intentionally does not accept clientSecret — only clientId + redirectUri. Send the resulting JWT to your game backend; the backend uses the Node / Python / Go server SDK with clientSecret to call get_slot_info(jwt).
Unity 빌드는 il2cpp_dumper / dnSpy 로 1분이면 디컴파일됩니다. Unity SDK 는 의도적으로 clientSecret 을 받지 않습니다 — clientId + redirectUri 만 받습니다. 받은 JWT 를 게임 백엔드로 전송하고, 백엔드가 clientSecret 을 가진 Node / Python / Go 서버 SDK 로 get_slot_info(jwt) 를 호출하세요.
alts-codex/unity-sdk —
source, full README, issues
소스, 전체 README, 이슈