OAuth2Strategy
一種用於使用和實作 OAuth2 框架的策略,以與 Google、Facebook、GitHub 等聯合服務進行身份驗證。
[!WARNING] 此策略預期身份提供者嚴格遵循 OAuth2 規範。如果提供者不遵循規範且偏離規範,此策略可能無法如預期般運作。
支援的執行環境
執行環境 | 是否支援 |
---|---|
Node.js | ✅ |
Cloudflare | ✅ |
如何使用
安裝
npm add remix-auth-oauth2
直接安裝
您可以將此策略新增至您的驗證器實例並配置正確的端點來使用它。
import { OAuthStrategy, CodeChallengeMethod } from "remix-auth-oauth2";
export const authenticator = new Authenticator<User>();
authenticator.use(
new OAuth2Strategy(
{
cookie: "oauth2", // Optional, can also be an object with more options
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
authorizationEndpoint: "https://provider.com/oauth2/authorize",
tokenEndpoint: "https://provider.com/oauth2/token",
redirectURI: "https://example.app/auth/callback",
tokenRevocationEndpoint: "https://provider.com/oauth2/revoke", // optional
scopes: ["openid", "email", "profile"], // optional
codeChallengeMethod: CodeChallengeMethod.S256, // 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 OAuth2 instance you will
// need to set a custom name to each one
"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 OAuth2Strategy<User>(options, verify);
let tokens = await strategy.refreshToken(refreshToken);
刷新令牌是驗證函數接收的 tokens
物件的一部分。您如何儲存它以呼叫 strategy.refreshToken
以及之後如何處理 tokens
物件取決於您。
最常見的方法是將刷新令牌儲存在使用者資料中,然後在刷新令牌後更新會話。
authenticator.use(
new OAuth2Strategy<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);
撤銷令牌
您可以撤銷使用者在提供者處擁有的存取令牌。
await strategy.revokeToken(user.accessToken);
探索提供者
如果您想要探索提供者的端點,您可以使用 discover
靜態方法。
export let authenticator = new Authenticator<User>();
authenticator.use(
await OAuth2Strategy.discover<User>(
"https://provider.com",
{
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
redirectURI: "https://example.app/auth/callback",
scopes: ["openid", "email", "profile"], // 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);
}
)
);
這將擷取提供者的設定端點 (/.well-known/openid-configuration
),並從中取得授權、令牌和撤銷端點,它還將擷取支援的程式碼挑戰方法,並嘗試使用 S256(如果支援)。
請記住,這將在建立策略時執行擷取,這將會增加您應用程式啟動的延遲時間。
建議只使用此方法一次,然後將端點複製到您的配置中。
自訂 Cookie
您可以透過將一個物件傳遞給 cookie
選項來自訂 cookie 選項。
authenticator.use(
new OAuth2Strategy<User>(
{
cookie: {
name: "oauth2",
maxAge: 60 * 60 * 24 * 7, // 1 week
path: "/auth",
httpOnly: true,
sameSite: "lax",
secure: process.env.NODE_ENV === "production",
},
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
authorizationEndpoint: "https://provider.com/oauth2/authorize",
tokenEndpoint: "https://provider.com/oauth2/token",
redirectURI: "https://example.app/auth/callback",
},
async ({ tokens, request }) => {
return await getUser(tokens, request);
}
)
);
這將使用名稱 oauth2
設定 cookie,最大期限為 1 週,僅可在 /auth
路徑上存取,僅限 http,同站 lax,並且如果應用程式在生產環境中執行則為安全。