Integrate Starchild OAuth login into any web application — React, Vue, or plain HTML. The SDK handles the full OAuth popup flow, token management, automatic refresh, and session restoration.
⚠️ Keep your Client ID safe. Never commit it directly in source code — use environment variables.
Each user can create up to 10 OAuth apps.
⚠️
Do NOT use with a plain
tag — that file is an ES Module and will fail silently. Use
for
tags, or use
with the ESM build (see examples below).
💡
CDN 加载失败? 如果两个 CDN 都无法访问(如在受限网络环境中),可以用
下载到本地后通过相对路径引用:
bash
curl -sL "https://unpkg.com/starchild-auth-sdk/dist/starchild-auth.umd.cjs" -o starchild-auth.umd.cjs
然后
<script src="starchild-auth.umd.cjs"></script>
When loaded via UMD CDN, the class is available directly as
(it's the constructor itself, not a namespace object).
typescript
import { StarchildAuth } from 'starchild-auth-sdk'
const auth = new StarchildAuth({
clientId: 'your-client-id',
// Called after successful login (popup or auto-login session restore)
onLogin: ({ accessToken, refreshToken, expiresIn, userInfo }) => {
console.log('Logged in:', userInfo.agentName)
console.log('Avatar:', userInfo.agentAvatar)
},
// Called after logout
onLogout: () => {
console.log('Logged out')
},
// Token auto-refreshes every 12 minutes
onTokenRefresh: (newAccessToken) => {
console.log('Token refreshed')
},
// Called when refresh fails (session expired)
onTokenRefreshFailed: () => {
console.log('Session expired, please log in again')
},
})
Auto-login: By default (
), the SDK checks localStorage for a stored refresh token on initialization and automatically restores the session. This means
may fire immediately after construction without calling
.
typescript
// Trigger login (opens Starchild OAuth popup)
const { accessToken, refreshToken, expiresIn, userInfo } = await auth.login()
// Logout (clears tokens, revokes refresh token via API)
await auth.logout()
// Check login status
const isLoggedIn: boolean = auth.isLoggedIn()
// Get current access token (null if not logged in)
const token: string | null = auth.getToken()
// Get current user info (null if not logged in)
const user: UserInfo | null = auth.getUserInfo()
// user = { userInfoId: string, agentName: string, agentAvatar: string }
// Manually trigger token refresh (normally automatic every 12 min)
const newToken: string = await auth.refreshToken()
// Destroy instance (remove listeners, clear timers, clear tokens)
auth.destroy()
tsx
// src/hooks/useStarchildAuth.ts
import { useState, useEffect, useRef, useCallback } from 'react'
import { StarchildAuth } from 'starchild-auth-sdk'
import type { UserInfo, LoginResult } from 'starchild-auth-sdk'
export function useStarchildAuth() {
const [user, setUser] = useState<UserInfo | null>(null)
const [token, setToken] = useState<string | null>(null)
const [loading, setLoading] = useState(true)
const authRef = useRef<StarchildAuth | null>(null)
useEffect(() => {
const auth = new StarchildAuth({
clientId: import.meta.env.VITE_STARCHILD_CLIENT_ID,
onLogin: ({ accessToken, userInfo }: LoginResult) => {
setUser(userInfo)
setToken(accessToken)
setLoading(false)
},
onLogout: () => {
setUser(null)
setToken(null)
},
onTokenRefresh: (newToken: string) => {
setToken(newToken)
},
onTokenRefreshFailed: () => {
setUser(null)
setToken(null)
},
// autoLogin: true (default) — will restore session from localStorage
})
authRef.current = auth
// If auto-login doesn't fire onLogin (no stored session), stop loading
const timeout = setTimeout(() => setLoading(false), 1500)
return () => {
clearTimeout(timeout)
auth.destroy()
}
}, [])
const login = useCallback(async () => {
if (!authRef.current) return
return await authRef.current.login()
}, [])
const logout = useCallback(async () => {
if (!authRef.current) return
await authRef.current.logout()
}, [])
return { user, token, loading, login, logout, isLoggedIn: !!user }
}
tsx
// src/App.tsx
import { useStarchildAuth } from './hooks/useStarchildAuth'
function App() {
const { user, loading, login, logout, isLoggedIn } = useStarchildAuth()
if (loading) return <div>Loading...</div>
return (
<div>
{isLoggedIn ? (
<div>
<p>Welcome, {user?.agentName}</p>
<img src={user?.agentAvatar} alt="avatar" width={40} />
<button onClick={logout}>Logout</button>
</div>
) : (
<button onClick={login}>Login with Starchild</button>
)}
</div>
)
}
export default App
typescript
// src/composables/useStarchildAuth.ts
import { ref, onMounted, onUnmounted } from 'vue'
import { StarchildAuth } from 'starchild-auth-sdk'
import type { UserInfo, LoginResult } from 'starchild-auth-sdk'
export function useStarchildAuth() {
const user = ref<UserInfo | null>(null)
const token = ref<string | null>(null)
const loading = ref(true)
let authInstance: StarchildAuth | null = null
onMounted(() => {
authInstance = new StarchildAuth({
clientId: import.meta.env.VITE_STARCHILD_CLIENT_ID,
onLogin: ({ accessToken, userInfo }: LoginResult) => {
user.value = userInfo
token.value = accessToken
loading.value = false
},
onLogout: () => {
user.value = null
token.value = null
},
onTokenRefresh: (newToken: string) => {
token.value = newToken
},
onTokenRefreshFailed: () => {
user.value = null
token.value = null
},
})
// If no stored session, stop loading after timeout
setTimeout(() => { loading.value = false }, 1500)
})
onUnmounted(() => {
authInstance?.destroy()
})
const login = async () => {
if (!authInstance) return
return await authInstance.login()
}
const logout = async () => {
if (!authInstance) return
await authInstance.logout()
}
const isLoggedIn = () => !!user.value
return { user, token, loading, login, logout, isLoggedIn }
}
💡 如果 CDN 加载失败,参考上方 Step 2 中的 CDN 备选源和本地下载方案。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Starchild Auth Demo</title>
<!-- UMD build: works with plain <script> tags -->
<!-- If CDN is blocked, download the file locally and use a relative path instead -->
<script src="https://unpkg.com/starchild-auth-sdk/dist/starchild-auth.umd.cjs"></script>
</head>
<body>
<div id="app">
<div id="logged-out">
<button id="login-btn">Login with Starchild</button>
</div>
<div id="logged-in" style="display: none">
<p>Welcome, <span id="user-name"></span></p>
<img id="user-avatar" width="40" />
<button id="logout-btn">Logout</button>
</div>
</div>
<script>
// UMD exposes window.StarchildAuth as the constructor directly
if (typeof window.StarchildAuth !== 'function') {
document.getElementById('logged-out').innerHTML =
'<p style="color:red">SDK failed to load. Check if the CDN script loaded correctly.</p>'
throw new Error('StarchildAuth SDK not loaded')
}
var auth = new StarchildAuth({
clientId: 'your-client-id',
onLogin: function (result) {
showLoggedIn(result.userInfo)
},
onLogout: function () {
showLoggedOut()
},
onTokenRefresh: function (newToken) {
console.log('Token refreshed')
},
onTokenRefreshFailed: function () {
showLoggedOut()
},
// autoLogin: true (default) — restores session automatically
})
document.getElementById('login-btn').addEventListener('click', async function () {
try {
await auth.login()
} catch (err) {
console.error('Login failed:', err.message)
}
})
document.getElementById('logout-btn').addEventListener('click', async function () {
await auth.logout()
})
function showLoggedIn(user) {
document.getElementById('logged-out').style.display = 'none'
document.getElementById('logged-in').style.display = 'block'
document.getElementById('user-name').textContent = user.agentName
if (user.agentAvatar) {
document.getElementById('user-avatar').src = user.agentAvatar
}
}
function showLoggedOut() {
document.getElementById('logged-out').style.display = 'block'
document.getElementById('logged-in').style.display = 'none'
}
</script>
</body>
</html>
If you prefer ES Module syntax, use
:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Starchild Auth Demo (ESM)</title>
</head>
<body>
<button id="login-btn">Login with Starchild</button>
<div id="logged-in" style="display: none">
<p>Welcome, <span id="user-name"></span></p>
<button id="logout-btn">Logout</button>
</div>
<script type="module">
import { StarchildAuth } from 'https://unpkg.com/starchild-auth-sdk/dist/starchild-auth.js'
const auth = new StarchildAuth({
clientId: 'your-client-id',
onLogin: ({ userInfo }) => {
document.getElementById('login-btn').style.display = 'none'
document.getElementById('logged-in').style.display = 'block'
document.getElementById('user-name').textContent = userInfo.agentName
},
onLogout: () => {
document.getElementById('login-btn').style.display = 'block'
document.getElementById('logged-in').style.display = 'none'
},
})
document.getElementById('login-btn').addEventListener('click', () => auth.login())
document.getElementById('logout-btn').addEventListener('click', () => auth.logout())
</script>
</body>
</html>
For React / Vue, use the
from the hook/composable:
Common mistake: Using
with a plain
tag. This will fail silently because the ESM file uses
syntax which is invalid in non-module scripts. Always use the
build for plain
tags.
The SDK stores the refresh token in
under the key
. This enables:
To fully clear a user's session, call
which removes the stored token and revokes it server-side.