雖然 DID 錢包是主要且最安全的驗證方法,但 @arcblock/did-connect-react 仍為多種替代登入方法提供了強大的支援,以提供靈活性並滿足不同使用者的偏好。本節詳細介紹如何將 OAuth (社群登入)、Passkeys (無密碼驗證) 和统一登录站点群登入整合到您的應用程式中。
這些方法透過特定的 React Context Providers 啟用,並透過相應的 hooks 存取,這些 hooks 應巢狀嵌套在主 SessionProvider 中。
OAuth (社群登入)
整合 Google、GitHub 或 Apple 等熱門社群登入供應商,讓使用者能用現有帳號登入。此功能由 OAuthProvider 和 useOAuth hook 管理。
1. 使用 OAuthProvider 設定
若要啟用 OAuth 功能,請用 OAuthProvider 包裹您的元件樹。通常會將其放置在 SessionProvider 內部。
OAuthProvider Setup
import { SessionProvider } from '@arcblock/did-connect-react';
import { OAuthProvider } from '@arcblock/did-connect-react/lib/OAuth';
function App() {
return (
<SessionProvider>
<OAuthProvider
onBindOAuth={(provider) => console.log(`${provider.provider} 已綁定!`)}
onUnbindOAuth={(account) => console.log(`${account.provider} 已解除綁定!`)}>
{/* 您的應用程式元件 */}
</OAuthProvider>
</SessionProvider>
);
}OAuthProvider 的 Props
- children
ReactNode(required) — 將有權存取 OAuth context 的子元件。 - locale
string(default:en) — 用於 UI 訊息和提示的語言。 - onBindOAuth
function— 使用者成功綁定 OAuth 帳號後觸發的回呼函式。 - onUnbindOAuth
function— 使用者成功解除綁定 OAuth 帳號後觸發的回呼函式。 - onSwitchPassport
function— 使用者切換 passport 後觸發的回呼函式。 - session
object— 目前的使用者 session 物件,passport 切換 UI 需要。
2. 使用 useOAuth Hook
useOAuth hook 提供了與 OAuth 驗證流程互動的函式。
useOAuth Hook
import { useOAuth } from '@arcblock/did-connect-react/lib/OAuth';
function SocialLoginButtons() {
const { loginOAuth, getOAuthConfigList, bindAuthLoading } = useOAuth();
const [providers, setProviders] = React.useState([]);
React.useEffect(() => {
getOAuthConfigList().then(setProviders);
}, [getOAuthConfigList]);
const handleLogin = async (provider) => {
try {
const result = await loginOAuth({ provider: provider.provider });
console.log('登入成功:', result);
// 處理登入結果,例如更新 session
} catch (error) {
console.error('登入失敗:', error.message);
}
};
if (providers.length === 0) {
return <p>未設定第三方登入方式。</p>;
}
return (
<div>
{providers.map((p) => (
<button key={p.provider} onClick={() => handleLogin(p)} disabled={bindAuthLoading}>
使用 {p.provider} 登入
</button>
))}
</div>
);
}核心函式
loginOAuth({ provider }, { action, ... }): 為特定供應商啟動登入流程。將會開啟一個彈出視窗供使用者驗證。bindOAuth({ session, oauthItem }): 將一個新的社群帳號綁定到目前登入的使用者。unbindOAuth({ session, connectedAccount }): 從目前使用者解除綁定一個社群帳號。getOAuthConfigList(): 非同步地取得在 Blocklet 設定中設定的已啟用 OAuth 供應商列表。switchOAuthPassport(user): 開啟一個對話方塊,用於在與同一 OAuth 身分相關聯的不同使用者帳號 (passports) 之間切換。
Passkeys (無密碼)
使用基於 WebAuthn 標準的 Passkeys,啟用現代、安全且無密碼的驗證。這讓使用者可以使用生物辨識 (指紋、臉部 ID)、裝置 PIN 碼或安全金鑰登入。
1. 使用 PasskeyProvider 設定
使用 PasskeyProvider 包裹您的應用程式以啟用 Passkey 功能。
PasskeyProvider Setup
import { SessionProvider } from '@arcblock/did-connect-react';
import { PasskeyProvider } from '@arcblock/did-connect-react/lib/Passkey';
function App() {
return (
<SessionProvider>
<PasskeyProvider
onAddPasskey={(result) => console.log('Passkey 已新增!', result)}
onRemovePasskey={(result) => console.log('Passkey 已移除!', result)}>
{/* 您的應用程式元件 */}
</PasskeyProvider>
</SessionProvider>
);
}PasskeyProvider 的 Props
- children
ReactNode(required) — 將有權存取 Passkey context 的子元件。 - locale
string(default:en) — 用於 UI 訊息和提示的語言。 - onAddPasskey
function— 使用者成功新增 Passkey 後觸發的回呼函式。 - onRemovePasskey
function— 使用者成功移除 Passkey 後觸發的回呼函式。 - onSwitchPassport
function— 使用者切換 passport 後觸發的回呼函式。 - session
object— 目前的使用者 session 物件,passport 切換 UI 需要。
2. 使用 usePasskey Hook
usePasskey hook 提供了 Passkey 註冊和驗證所需的所有函式。
usePasskey Hook
import { usePasskey } from '@arcblock/did-connect-react/lib/Passkey';
import { useSession } from '@arcblock/did-connect-react';
function PasskeyAuth() {
const { loginPasskey, connectPasskey, connecting } = usePasskey();
const { session } = useSession();
const handleLogin = async () => {
try {
const result = await loginPasskey();
console.log('Passkey 登入成功:', result);
// 處理登入結果
} catch (error) {
console.error('Passkey 登入失敗:', error.message);
}
};
const handleConnect = async () => {
// 這應該在使用者已經登入時呼叫
// 並且想要在他們的個人資料設定中新增一個 passkey。
if (!session.user) {
alert('您必須登入才能新增 passkey。');
return;
}
try {
await connectPasskey();
} catch (error) {
console.error('連接 passkey 失敗:', error.message);
}
};
return (
<div>
<button onClick={handleLogin}>使用 Passkey 登入</button>
{session.user && (
<button onClick={handleConnect} disabled={connecting}>
{connecting ? '連接中...' : '新增 Passkey'}
</button>
)}
</div>
);
}核心函式
loginPasskey({ action, ... }): 啟動 Passkey 驗證流程 (也稱為 assertion)。這用於登入現有使用者。connectPasskey(extraParams): 一個高階函式,用於建立一個新的 Passkey 並將其綁定到目前使用者的帳號。它處理完整的註冊儀式。disconnectPasskey({ session, connectedAccount }): 在成功驗證後,從目前使用者的帳號中移除一個 Passkey。createPasskey(params): 啟動 WebAuthn 註冊過程的較低階函式。connectPasskey在內部使用此函式。verifyPasskey(params): 啟動 WebAuthn 驗證過程的較低階函式。loginPasskey和disconnectPasskey在內部使用此函式。switchPassport(user): 開啟一個對話方塊,用於在可能共享 Passkeys 的不同使用者帳號 (passports) 之間切換。
统一登录站点群登入
统一登录站点群登入允許一組關聯的 Blocklet 應用程式 (一個「统一登录站点群」) 共享單一登入 session。當使用者登入指定的「主」站點時,他們可以在任何「成員」站點上自動進行驗證,無需再次登入。
1. 概念與設定
此功能依賴於您 Blocklet 設定中的主從站點設定。需要 FederatedProvider 元件來處理此功能在現代瀏覽器中運作所需的跨網域通訊,特別是用於管理第三方 cookie 的存取。
與其他 provider 一樣,FederatedProvider 應包含在您的元件樹中,通常位於 SessionProvider 內部。
FederatedProvider Setup
import { SessionProvider } from '@arcblock/did-connect-react';
import { FederatedProvider } from '@arcblock/did-connect-react/lib/Federated';
function App() {
return (
<SessionProvider>
<FederatedProvider>
{/* 您的應用程式元件 */}
</FederatedProvider>
</SessionProvider>
);
}2. 使用方法
统一登录站点群登入邏輯直接整合到 session 管理中。您可以使用 useSession 回傳的 session 物件上的 loginFederated 函式來觸發它。
loginFederated 支援兩種模式:
auto: 如果使用者在主站點上有活動的 session,則嘗試靜默登入使用者。這非常適合在頁面載入時進行檢查。manual: 啟動標準的 DID Connect 登入流程。成功登入後,它也會與主站點建立统一登录站点群 session。
Federated Login Example
import { useSession } from '@arcblock/did-connect-react';
import React from 'react';
function FederatedLogin() {
const { session } = useSession();
const { federatedEnabled, loginFederated } = session;
// 在元件掛載時嘗試自動登入
React.useEffect(() => {
if (federatedEnabled) {
loginFederated((err) => {
if (err) {
console.warn('自動统一登录站点群登入失敗:', err);
} else {
console.log('自動统一登录站点群登入成功!');
}
}, { mode: 'auto' });
}
}, [federatedEnabled, loginFederated]);
const handleManualLogin = () => {
loginFederated((err) => {
if (err) console.error('手動统一登录站点群登入失敗:', err);
}, { mode: 'manual' });
};
if (!federatedEnabled) {
return <p>未啟用统一登录站点群登入。</p>;
}
return (
<button onClick={handleManualLogin}>
使用主站點帳號登入
</button>
);
}