品牌与识别套件
用于将 UniAuth 登录集成进您应用程序的官方素材。盾牌标志、预制按钮、徽章与可嵌入小工具,全部集中在一处。
盾牌标志
UniAuth 盾牌是主要的品牌标志。请在登录按钮、应用程序列表与文档中将其作为易于辨识的图标使用。
<img src="https://uniauth.id/brand/oauth/mark.svg" alt="UniAuth" width="24" height="24" />登录按钮
交互式试用区——选择主题、尺寸、形状与文本,即可在真实的鼠标停留状态下即时预览按钮。拷贝产生的 HTML 即可嵌入您的应用程序。
实时示范 — 滑入并点击
SVG 资产
信任徽章
交互式试用区——选择主题与文本样式,即可在鼠标停留效果下即时预览徽章。拷贝 HTML 即可嵌入您的页脚、侧边栏或结帐页面。
扁平胶囊徽章
适用于 README 文件、文档与仪表板的 shields.io 风格扁平徽章。选择一种样式并拷贝 Markdown 或 HTML。
信任印记
适用于结帐页面、侧边栏与安全页面的醒目信任印记。切换主题与样式进行预览,然后拷贝 HTML。
浮动徽章与信任列
即时示范——切换以显示屏幕角落的浮动徽章或页脚的信任列。将鼠标停留在浮动徽章上即可看到浮起效果。
小工具——随插即用的 JavaScript
添加 UniAuth 登录最快的方式。一个 script 标签即可呈现品牌按钮,并自动处理完整的 PKCE OAuth 流程。
弹出窗口模式(建议用于桌面)
用户停留在您的页面上,验证在弹出窗口中进行,权杖通过回呼传递。
<script src="https://uniauth.id/brand/oauth/uniauth-widget.js"></script>
<div id="uniauth-signin"></div>
<script>
UniAuth.renderButton('#uniauth-signin', {
clientId: 'your-client-id',
redirectUri: 'https://yourapp.com/callback',
mode: 'popup', // opens auth in a centered popup
theme: 'dark',
onSuccess: function(result) {
console.log('Logged in!', result.accessToken);
},
onError: function(err) {
console.error('Auth failed:', err.error);
}
});
</script>重新导向模式
将整个页面导向 UniAuth,再带着授权码重新导向返回。在任何环境都能运作。
<script src="https://uniauth.id/brand/oauth/uniauth-widget.js"></script>
<div id="uniauth-signin"></div>
<script>
UniAuth.renderButton('#uniauth-signin', {
clientId: 'your-client-id',
redirectUri: 'https://yourapp.com/callback',
mode: 'redirect', // full-page navigation
theme: 'dark'
});
</script>
<!-- On your /callback page: -->
<script>
UniAuth.handleCallback({
clientId: 'your-client-id',
redirectUri: 'https://yourapp.com/callback'
}).then(function(result) {
if (result.success) {
console.log('Access token:', result.accessToken);
}
});
</script>自动侦测(缺省)
mode 省略时会自动侦测:桌面使用弹出窗口,行动设备使用重新导向。
UniAuth.renderButton('#uniauth-signin', {
clientId: 'your-client-id',
redirectUri: 'https://yourapp.com/callback',
// mode omitted — auto-detects popup (desktop) or redirect (mobile)
});所有选项
| 选项 | 类型 | 缺省 | 说明 |
|---|---|---|---|
| clientId | string | — | 您的 OAuth 用户端 ID(必填) |
| redirectUri | string | origin/callback | 验证后重新导向的目标地址 |
| mode | string | auto | "popup" | "redirect" — 省略时自动侦测 |
| scope | string | "openid profile email" | 要求的 OAuth 范围 |
| theme | string | "dark" | "dark" | "light" | "outline" | "neutral" |
| size | string | "standard" | "small" | "standard" | "large" |
| text | string | "signin" | "signin" | "continue" |
| shape | string | "rectangular" | "rectangular" | "pill" |
| width | number | auto | 固定宽度(像素) |
| locale | string | "en" | 按钮文本的语言 |
| onSuccess | function | — | 弹出窗口验证完成后接收权杖的回呼 |
| onError | function | — | 验证发生错误或弹出窗口关闭时的回呼 |
| onSignIn | function | — | 自订的点击处理常式(略过 OAuth 流程) |
| popupWidth | number | 480 | 弹出窗口的宽度(像素) |
| popupHeight | number | 640 | 弹出窗口的高度(像素) |
| loginHint | string | — | 在 UniAuth 登录画面预先填入电子邮件 |
| prompt | string | — | "login" | "consent" | "none" |
| nonce | string | — | 用于防止重放攻击的 ID 权杖 nonce |
呈现徽章
<div id="uniauth-badge"></div>
<script>
UniAuth.renderBadge('#uniauth-badge', {
theme: 'light', // 'light' | 'dark'
text: 'secured' // 'powered' | 'secured' | 'identity'
});
</script>CSS 类别——HTML 集成
若需完整控制,请使用具备语意化类别名称的独立 CSS 文件。无需 JavaScript——只要 HTML 与 CSS。
引入样式表
<link rel="stylesheet"
href="https://uniauth.id/brand/oauth/uniauth-buttons.css" />深色按钮
<a href="https://uniauth.id/api/oauth/authorize?client_id=YOUR_ID&..."
class="uniauth-btn uniauth-btn-dark">
<span class="uniauth-btn-icon"></span>
Sign in with UniAuth
</a>浅色按钮
<a href="..." class="uniauth-btn uniauth-btn-light">
<span class="uniauth-btn-icon"></span>
Sign in with UniAuth
</a>外框按钮
<a href="..." class="uniauth-btn uniauth-btn-outline">
<span class="uniauth-btn-icon"></span>
Continue with UniAuth
</a>修饰类别
<!-- Small -->
<a class="uniauth-btn uniauth-btn-dark uniauth-btn-sm">...</a>
<!-- Large -->
<a class="uniauth-btn uniauth-btn-light uniauth-btn-lg">...</a>
<!-- Pill shape -->
<a class="uniauth-btn uniauth-btn-dark uniauth-btn-pill">...</a>
<!-- Full width -->
<a class="uniauth-btn uniauth-btn-dark uniauth-btn-block">...</a>
<!-- Icon only -->
<a class="uniauth-btn uniauth-btn-dark uniauth-btn-icon-only">
<span class="uniauth-btn-icon"></span>
</a>
<!-- Disabled -->
<a class="uniauth-btn uniauth-btn-dark" disabled>...</a>
<!-- Loading -->
<a class="uniauth-btn uniauth-btn-dark uniauth-btn-loading">
<span class="uniauth-btn-icon"></span>
Signing in...
</a>徽章类别
<a href="https://uniauth.id" class="uniauth-badge uniauth-badge-light">
<span class="uniauth-badge-icon"></span>
<span>Powered by <strong>UniAuth</strong></span>
</a>
<a href="https://uniauth.id" class="uniauth-badge uniauth-badge-dark">
<span class="uniauth-badge-icon"></span>
<span>Secured by <strong>UniAuth</strong></span>
</a>React 组件
适用于 Next.js、Vite 或任何 React 应用程序的随插即用 React 组件。可使用官方 @uniauth/react SDK,也可独立使用。
搭配 @uniauth/react SDK
import { UniAuthProvider, LoginButton } from '@uniauth/react';
function App() {
return (
<UniAuthProvider
issuer="https://uniauth.id"
clientId="your-client-id"
redirectUri="https://yourapp.com/callback"
>
<LoginButton theme="dark" />
</UniAuthProvider>
);
}独立组件
interface UniAuthButtonProps {
clientId: string;
redirectUri: string;
scope?: string;
theme?: 'dark' | 'light' | 'outline' | 'neutral';
size?: 'small' | 'standard' | 'large';
text?: 'signin' | 'continue';
className?: string;
}
const SHIELD_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"
viewBox="0 0 24 24" fill="none">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"
stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round"/>
</svg>`;
export function UniAuthButton({
clientId,
redirectUri,
scope = 'openid profile email',
theme = 'dark',
size = 'standard',
text = 'signin',
className = '',
}: UniAuthButtonProps) {
const label = text === 'continue'
? 'Continue with UniAuth'
: 'Sign in with UniAuth';
const heights = { small: 'h-9', standard: 'h-11', large: 'h-[52px]' };
const iconSizes = { small: 'w-[34px]', standard: 'w-[42px]', large: 'w-[50px]' };
const fonts = { small: 'text-[13px]', standard: 'text-sm', large: 'text-base' };
const themes = {
dark: 'bg-[#0a0a0a] border-[#0a0a0a] text-[#fafafa] hover:bg-[#262626]',
light: 'bg-white border-[#d4d4d4] text-[#0a0a0a] hover:bg-[#f5f5f5]',
outline: 'bg-transparent border-[#a3a3a3] text-[#262626] hover:bg-black/[0.04]',
neutral: 'bg-[#f5f5f5] border-[#e5e5e5] text-[#171717] hover:bg-[#e5e5e5]',
};
async function handleClick() {
const array = new Uint8Array(32);
crypto.getRandomValues(array);
const verifier = btoa(String.fromCharCode(...array))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const digest = await crypto.subtle.digest(
'SHA-256', new TextEncoder().encode(verifier)
);
const challenge = btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const stateArr = new Uint8Array(16);
crypto.getRandomValues(stateArr);
const state = btoa(String.fromCharCode(...stateArr))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
sessionStorage.setItem('uniauth_code_verifier', verifier);
sessionStorage.setItem('uniauth_state', state);
const params = new URLSearchParams({
response_type: 'code',
client_id: clientId,
redirect_uri: redirectUri,
scope,
state,
code_challenge: challenge,
code_challenge_method: 'S256',
});
window.location.href =
`https://uniauth.id/api/oauth/authorize?${params}`;
}
return (
<button
type="button"
onClick={handleClick}
aria-label={label}
className={`inline-flex items-center gap-0 border rounded-md
font-medium transition-colors cursor-pointer select-none
${heights[size]} ${fonts[size]} ${themes[theme]} ${className}`}
style={{ paddingRight: size === 'large' ? 20 : 16 }}
>
<span
className={`flex items-center justify-center
${iconSizes[size]} ${heights[size]}
border-r border-current/15`}
dangerouslySetInnerHTML={{ __html: SHIELD_SVG }}
/>
<span className="flex-1 text-center">{label}</span>
</button>
);
}SVG 按钮嵌入
预先绘制的按钮 SVG——最简单的集成方式。只要嵌入为 <img> 或 <object> 即可,无需 CSS 或 JS。
<!-- Dark "Sign in" button -->
<a href="https://uniauth.id/api/oauth/authorize?client_id=YOUR_ID&...">
<img src="https://uniauth.id/brand/oauth/btn-signin-dark.svg"
alt="Sign in with UniAuth" height="44" />
</a>
<!-- Light "Sign in" button -->
<img src="https://uniauth.id/brand/oauth/btn-signin-light.svg"
alt="Sign in with UniAuth" height="44" />
<!-- Outline "Sign in" button -->
<img src="https://uniauth.id/brand/oauth/btn-signin-outline.svg"
alt="Sign in with UniAuth" height="44" />
<!-- Dark "Continue with" button -->
<img src="https://uniauth.id/brand/oauth/btn-continue-dark.svg"
alt="Continue with UniAuth" height="44" />
<!-- Icon-only buttons -->
<img src="https://uniauth.id/brand/oauth/btn-icon-dark.svg"
alt="UniAuth" width="44" height="44" />
<img src="https://uniauth.id/brand/oauth/btn-icon-light.svg"
alt="UniAuth" width="44" height="44" />可用的 SVG 文件
| 文件 | 尺寸 | 说明 |
|---|---|---|
| btn-signin-dark.svg | 240 x 44 | 深色「Sign in with UniAuth」 |
| btn-signin-light.svg | 240 x 44 | 浅色「Sign in with UniAuth」 |
| btn-signin-outline.svg | 240 x 44 | 外框「Sign in with UniAuth」 |
| btn-continue-dark.svg | 260 x 44 | 深色「Continue with UniAuth」 |
| btn-continue-light.svg | 260 x 44 | 浅色「Continue with UniAuth」 |
| btn-icon-dark.svg | 44 x 44 | 深色纯图标按钮 |
| btn-icon-light.svg | 44 x 44 | 浅色纯图标按钮 |
| btn-icon-outline.svg | 44 x 44 | 外框纯图标按钮 |
品牌使用准则
请遵循这些准则,以确保在您的应用程序中一致地呈现 UniAuth 品牌。
建议
- 依原样使用官方的按钮 SVG 或 CSS 类别
- 在按钮周围保留至少 8px 的留白
- 在浅色背景使用深色版本,在深色背景使用浅色版本
- 将按钮设置为与您接口中其他社群登录按钮相近的尺寸
- 使用「Sign in with UniAuth」或「Continue with UniAuth」作为按钮文本
- 纳入盾牌图标——这是主要的辨识标志
避免
- 更改盾牌图标的形状、比例或线条粗细
- 为盾牌加上色彩填满——它一律是纯线条标志
- 在没有合作关系的情况下使用 UniAuth 标志来暗示背书
- 将按钮呈现得低于 36px 高,或更改其文本
- 将按钮放在会降低对比度的杂乱背景上
- 旋转、倾斜或对标志套用效果(阴影、光晕)
色彩配置
UniAuth 采用单色调配置。所有品牌元素都使用中性灰阶——没有任何强调色。
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif。按钮文本使用字重 500(中等),「UniAuth」文本标志使用 700(粗体)。所有下载
识别套件中的所有素材,依类型整理。
按钮 SVG
信任徽章
扁平胶囊徽章
信任印记
完整标志套件
多种尺寸的 PNG/SVG 图标与完整标志也可在 /brand/ 目录中取得。