跳到主要內容

驗證方法

雖然 DID 錢包是主要且最安全的驗證方法,但 @arcblock/did-connect-react 仍為多種替代登入方法提供了強大的支援,以提供靈活性並滿足不同使用者的偏好。本節詳細介紹如何將 OAuth (社群登入)、Passkeys (無密碼驗證) 和统一登录站点群登入整合到您的應用程式中。

這些方法透過特定的 React Context Providers 啟用,並透過相應的 hooks 存取,這些 hooks 應巢狀嵌套在主 SessionProvider 中。

OAuth (社群登入)

整合 Google、GitHub 或 Apple 等熱門社群登入供應商,讓使用者能用現有帳號登入。此功能由 OAuthProvideruseOAuth hook 管理。

1. 使用 OAuthProvider 設定

若要啟用 OAuth 功能,請用 OAuthProvider 包裹您的元件樹。通常會將其放置在 SessionProvider 內部。

OAuthProvider Setup

jsx
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

jsx
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

jsx
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

jsx
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 驗證過程的較低階函式。loginPasskeydisconnectPasskey 在內部使用此函式。
  • switchPassport(user): 開啟一個對話方塊,用於在可能共享 Passkeys 的不同使用者帳號 (passports) 之間切換。

统一登录站点群登入

统一登录站点群登入允許一組關聯的 Blocklet 應用程式 (一個「统一登录站点群」) 共享單一登入 session。當使用者登入指定的「主」站點時,他們可以在任何「成員」站點上自動進行驗證,無需再次登入。

1. 概念與設定

此功能依賴於您 Blocklet 設定中的主從站點設定。需要 FederatedProvider 元件來處理此功能在現代瀏覽器中運作所需的跨網域通訊,特別是用於管理第三方 cookie 的存取。

與其他 provider 一樣,FederatedProvider 應包含在您的元件樹中,通常位於 SessionProvider 內部。

FederatedProvider Setup

jsx
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

jsx
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>
  );
}