GitHubStrategy

一個用於 GitHub 應用程式和 OAuth 應用程式的 Remix Auth 策略

支援的執行環境

執行環境 支援
Node.js
Cloudflare

如何使用

安裝

npm add remix-auth remix-auth-github

建立 OAuth 應用程式

按照 GitHub 文件上的步驟建立一個新的應用程式並取得客戶端 ID 和密碼。

用法

您可以將此策略添加到您的驗證器實例並設定正確的端點來使用它。

export let authenticator = new Authenticator<User>();

authenticator.use(
  new GitHubStrategy(
    {
      clientId: CLIENT_ID,
      clientSecret: CLIENT_SECRET,
      redirectURI: "https://example.app/auth/callback",
      scopes: ["user:email"], // optional
    },
    async ({ tokens, request }) => {
      // here you can use the params above to get the user and return it
      // what you do inside this and how you find the user is up to you
      return await getUser(tokens, request);
    }
  ),
  // this is optional, but if you setup more than one GitHub instance you will
  // need to set a custom name to each one, by default is "github"
  "provider-name"
);

然後您需要設定您的路由,對於 OAuth2 流程,您需要調用 `authenticate` 方法兩次。

首先,您將使用您在驗證器中設定的提供者名稱調用 `authenticate` 方法。

export async function action({ request }: Route.ActionArgs) {
  await authenticator.authenticate("provider-name", request);
}

[!NOTE] 此路由可以是 `action` 或 `loader`,這取決於您是觸發 POST 還是 GET 請求來啟動流程。

這將啟動 OAuth2 流程並將用戶重定向到提供者的登入頁面。一旦用戶登入並授權您的應用程式,提供者會將用戶重定向回您的應用程式重定向 URI。

現在您需要在該 URI 上設定一個路由來處理來自提供者的回呼。

export async function loader({ request }: Route.LoaderArgs) {
  let user = await authenticator.authenticate("provider-name", request);
  // now you have the user object with the data you returned in the verify function
}

[!NOTE] 此路由必須是 `loader`,因為重定向將觸發 `GET` 請求。

一旦您從策略驗證函數返回 `user` 物件,您可以對該資訊執行任何您想做的事情。這可以是將用戶儲存在會話中、在資料庫中建立新用戶、將帳戶連結到您資料庫中的現有用戶等等。

使用重新整理令牌

該策略公開一個公有的 `refreshToken` 方法,您可以使用它來重新整理存取令牌。

let strategy = new GitHubStrategy<User>(options, verify);
let tokens = await strategy.refreshToken(refreshToken);

重新整理令牌是驗證函數接收的 `tokens` 物件的一部分。您如何儲存它以調用 `strategy.refreshToken` 以及您在它之後對 `tokens` 物件執行什麼操作取決於您。

最常見的方法是將重新整理令牌儲存在使用者資料中,然後在重新整理令牌後更新會話。

authenticator.use(
  new GitHubStrategy<User>(
    options,
    async ({ tokens, request }) => {
      let user = await getUser(tokens, request);
      return {
        ...user,
        accessToken: tokens.accessToken()
        refreshToken: tokens.hasRefreshToken() ? tokens.refreshToken() : null,
      }
    }
  )
);

// later in your code you can use it to get new tokens object
let tokens = await strategy.refreshToken(user.refreshToken);

取得使用者個人資料

一旦您擁有 OAuth2 令牌物件,您可以使用存取令牌從 GitHub 的 API 取得使用者個人資料

let response = await fetch("https://api.github.com/user", {
  headers: {
    Accept: "application/vnd.github+json",
    Authorization: `Bearer ${tokens.accessToken()}`,
    "X-GitHub-Api-Version": "2022-11-28",
  },
});

let user = await response.json();

// Somehow parse the user object to ensure it has the correct shape

取得使用者電子郵件

同樣地,您可以使用存取令牌從 GitHub 的 API 取得使用者的電子郵件

[!IMPORTANT] 您需要在驗證使用者時請求 `user:email` 範圍。

let response = await fetch("https://api.github.com/user/emails", {
  headers: {
    Accept: "application/vnd.github+json",
    Authorization: `Bearer ${tokens.accessToken()}`,
    "X-GitHub-Api-Version": "2022-11-28",
  },
});

let emails = await response.json();

// Somehow parse the emails object to ensure it has the correct shape