Auth.js
Auth.js は、さまざまな JS フレームワークで使用される認証のための有名なライブラリです。Auth.js を使用することで、複雑さを軽減できます。また、GitHub、Google、Facebook など、さまざまな認証プロバイダーにアクセスできます。さらに、Qwik を含む複数のフレームワークに統合できます。
Auth.js は、シンプルさ、生産性、柔軟性、プロバイダーの多様性を強化するいくつかの機能を提供しています。以下は、Auth.js の主な機能です。
- プロバイダー: Auth.js は、複数のプロバイダーをサポートしており、アプリケーションでの認証プロセスを簡素化します(例:Github、Google、Facebook、Twitter)。また、シングルサインオン(SSO)サービスと従来の認証も提供しています。
- 管理: Auth.js は、ビジネスロジックに集中できるよう、大幅に支援してくれます。トークンを管理、保存し、自動的に更新します。
- 設定: Auth.js の設定は簡単です。簡単なインストール、エラー処理、ログインと登録用のカスタムフォーム、プロバイダーとの簡単な統合を提供します。
- 統合: Auth.js は、JS フレームワークとシームレスに統合され、従うべき明確なガイドを提供する包括的なドキュメントによって支援されます。
- セキュリティ: Auth.js は開発者にとって使いやすいものですが、データの高レベルのセキュリティを確保する基盤となる複雑さを認識することが重要です。
Auth.js ライブラリはまだ 1.0 より前の段階であり、バグが発生する可能性があることに注意してください。
インストール
次の Qwik スタータースクリプトを使用すると、Auth.js を簡単に追加できます
npm run qwik add auth
このコマンドは、新しいパッケージを追加します
@auth/qwik
そして、[email protected]
という名前の新しいファイルと、構成例を作成します。
Node を使用した手動デプロイに関する注意
Node.js を使用して、特に Express のようなフレームワークで手動でアプリケーションをデプロイする場合、サーバーまたは Node プロセスは、HTTP または HTTPS のどちらで提供されているかを本質的に認識しません。ORIGIN 構成が自動的に管理される Vercel、Netlify、Cloudflare などのホスティングサービスとは異なり、手動セットアップでは明示的な指定が必要です。Node.js アプリケーションが提供される正しいプロトコルとホストを認識するようにするには、次の環境変数を設定します。
- ORIGIN: これをアプリケーションの URL に設定します。例:ORIGIN=https://your-app-name.example.com
- PROTOCOL_HEADER: これは、クライアントがリクエストした元のプロトコルを示すために使用されます。一般的に、これはプロキシ構成で指定されます。この変数を次のように設定します。PROTOCOL_HEADER=X-Forwarded-Proto
- HOST_HEADER: このヘッダーは、クライアントがリクエストした元のホストを識別するのに役立ちます。特に Node 環境がプロキシまたはロードバランサーの背後にある場合に必要です。この変数を次のように設定します。HOST_HEADER=X-Forwarded-Host
Qwik API
useSession
セッションオブジェクトまたはセッションがない場合は空のオブジェクトを返す routeLoader$。返されるセッションオブジェクトの内容は、セッションコールバックで設定可能です。セッションデータは、session REST API を使用して取得することもできます。
import { component$ } from '@builder.io/qwik';
import { useSession } from '~/routes/plugin@auth';
export default component$(() => {
const session = useSession();
return <p>{session.value?.user?.email}</p>;
});
useSignIn
サインインフローを開始するか、可能なすべてのプロバイダーを一覧表示するサインインページにユーザーを送信するために使用される routeAction$。CSRF トークンは、useSignIn
を使用してサインインするときに内部的に処理されます。
パラメーター
providerId
: プロバイダーの名前を持つオプションの文字列パラメーター。指定すると、ID プロバイダーへの認証リクエストが開始されます。省略すると、組み込み/ブランドなしのサインインページにリダイレクトされます。options
: オプションのオブジェクト。redirectTo
: サインイン後にユーザーがリダイレクトされる URL を指定するオプションの文字列。デフォルトでは、サインインが開始されたページ URL になります。
authorizationParams
: /authorize エンドポイントに送信される追加パラメーターのオプションオブジェクト。アイデアについては、Authorization Request OIDC 仕様を参照してください。
注意: プロバイダー.authorizationParams 構成を通じて
authorizationParams
を設定することもできます
<Form> コンポーネントとオプションの providerId
および options.redirectTo
を使用した useSignIn
の例
import { component$ } from '@builder.io/qwik';
import { Form } from '@builder.io/qwik-city';
import { useSignIn } from '~/routes/plugin@auth';
export default component$(() => {
const signIn = useSignIn();
return (
<Form action={signIn}>
<input type="hidden" name="providerId" value="github" />
<input type="hidden" name="options.redirectTo" value="http://qwik-auth-example.com/dashboard" />
<button>Sign In</button>
</Form>
);
});
オプションのproviderId
とoptions.redirectTo
を指定して、useSignIn
をプログラム的に使用する例
import { component$ } from '@builder.io/qwik';
import { useSignIn } from '~/routes/plugin@auth';
export default component$(() => {
const signIn = useSignIn();
return (
<button onClick$={() => signIn.submit({ providerId: 'github', options: { redirectTo: 'http://qwik-auth-example.com/dashboard' } })}>Sign In</button>
);
});
useSignOut
サインアウトフローを開始するために使用されるrouteAction$。ユーザーセッションは、セッションを保存するために選択したフローに応じて、クッキー/データベースから無効化/削除されます。
パラメータ
redirectTo
: サインアウト後にユーザーがリダイレクトされるURLを指定するオプションの文字列。デフォルトでは、サインインが開始されたページのURLになります。
'redirectTo'は、リダイレクトコールバックハンドラーによって有効とみなされる必要があります。デフォルトでは、URLが同じホスト名で絶対URLであるか、スラッシュで始まる相対URLを提供する必要があります。一致しない場合はホームページにリダイレクトされます。他のURLを許可するように独自のリダイレクトコールバックを定義できます。
<Form>コンポーネントとオプションのredirectTo
を使用して、useSignOut
を使用する例
import { component$ } from '@builder.io/qwik';
import { Form } from '@builder.io/qwik-city';
import { useSignOut } from '~/routes/plugin@auth';
export default component$(() => {
const signOut = useSignOut();
return (
<Form action={signOut}>
<input type="hidden" name="redirectTo" value="/signedout" />
<button>Sign Out</button>
</Form>
);
});
オプションのredirectTo
を指定して、useSignOut
をプログラム的に使用する例
import { component$ } from '@builder.io/qwik';
import { useSignOut } from '~/routes/plugin@auth';
export default component$(() => {
const signOut = useSignOut();
return <button onClick$={() => signOut.submit({ redirectTo: '/signedout' })}>Sign Out</button>;
});
REST API
Auth.jsによって提供されるすべてのREST APIが利用可能です。
signin
GET /api/auth/signin
組み込みの/ブランド化されていないサインインページを表示します。
POST /api/auth/signin/:provider
プロバイダー固有のサインインフローを開始します。OAuthプロバイダーの場合、このエンドポイントを呼び出すと、IDプロバイダーへの認証リクエストが開始されます。このエンドポイントは、内部的にuseSignInアクションによっても使用されます。
callback
GET/POST /api/auth/callback/:provider
signout
GET /api/auth/signout
組み込みの/ブランド化されていないサインアウトページを表示します。
POST /api/auth/signout
ユーザーのサインアウトを処理します。これは、悪意のあるリンクがユーザーの同意なしにサインアウトをトリガーするのを防ぐためのPOST送信です。ユーザーセッションは、セッションを保存するために選択したフローに応じて、クッキー/データベースから無効化/削除されます。このエンドポイントは、内部的にuseSignOutメソッドによっても使用されます。
session
GET /api/auth/session
クライアントセーフなセッションオブジェクト、またはセッションがない場合は空のオブジェクトを返します。返されるセッションオブジェクトの内容は、セッションコールバックで設定可能です。セッションデータは、useSession routerLoaderを使用して取得することもできます。
csrf
GET /api/auth/csrf
CSRFトークンを含むオブジェクトを返します。NextAuth.jsでは、すべての認証ルートにCSRF保護が存在します。「ダブルサブミットクッキー方式」を使用し、署名付きのHttpOnly、ホスト専用のクッキーを使用します。このエンドポイントによって返されるCSRFトークンは、すべてのAPIエンドポイントへのPOST送信でcsrfTokenというフォーム変数として渡される必要があります。
providers
GET /api/auth/providers
構成されたOAuthサービスと、各サービスの詳細(例:サインインとコールバックURL)のリストを返します。カスタムサインアップページを動的に生成したり、構成された各OAuthプロバイダーに構成されているコールバックURLを確認したりするのに役立ちます。
例
GitHub
- GitHub OAuthガイドに従って、
GitHub Client ID
、GitHub Client Secrets
を取得し、openssl rand -base64 32
またはシークレットジェネレーターを使用してAUTH_SECRET
を生成します。 - デフォルトの
[email protected]
はGitHubを例として使用するため、そこで何も変更する必要はありません。ただし、GitHub以外のプロバイダーを使用したり、追加のプロバイダーを追加したりできます。Auth.jsは、このファイルで設定できる追加のオプションも多数サポートしています。
import { QwikAuth$ } from "@auth/qwik";
import GitHub from "@auth/qwik/providers/github";
export const { onRequest, useSession, useSignIn, useSignOut } = QwikAuth$(
() => ({
providers: [GitHub],
}),
);
重要:oAuthフローのリダイレクトを処理するために使用されるため、
onRequest
のエクスポートを必ずそのまま保持してください。ユーザーがoAuthフローを完了すると、GitHub(またはその他のプロバイダー)はユーザーを/api/auth/callback/github
(または/api/auth/callback/[otherProvider]
)にアプリケーションにリダイレクトします。onRequest
ミドルウェア関数は、このエンドポイントへのリクエストを処理し、oAuthフローを完了します。
- プロジェクトのルートにある
.env.local
ファイルを作成または編集して、シークレットを保存します
GITHUB_ID=
GITHUB_SECRET=
AUTH_SECRET=
重要:環境変数を安全に使用していることを確認するために、環境変数に関するQwikドキュメントをお読みください。多くのプロバイダーシークレットは安全に保管し、クライアント/ブラウザに公開しないでください。
- これで、Auth.jsを使用して認証を実装する準備が整いました。
- お楽しみください!
Credentials
警告: この機能はAuth.jsによって推奨されていません。
https://next-auth.js.org/providers/credentials
- 資格情報ベースの認証に提供される機能は、パスワードに関連する固有のセキュリティリスク、およびユーザー名とパスワードのサポートに関連する追加の複雑さのために、パスワードの使用を控えるために意図的に制限されています。
- デフォルトの
[email protected]
はGitHubを例として使用するため、Credentialsに置き換える必要があります。
import { QwikAuth$ } from "@auth/qwik";
import GitHub from "@auth/qwik/providers/github";
export const { onRequest, useSession, useSignIn, useSignOut } = QwikAuth$(
() => ({
providers: [
Credentials({
async authorize(credentials, req) {
// Add logic here to look up the user from the credentials supplied
const user = {
id: 1,
name: "Mike",
email: "[email protected]",
};
return user;
},
}),
],
}),
);
- プロジェクトのルートにある
.env.local
ファイルを作成または編集して、シークレットを保存します
AUTH_SECRET=
重要:環境変数を安全に使用していることを確認するために、環境変数に関するQwikドキュメントをお読みください。多くのプロバイダーシークレットは安全に保管し、クライアント/ブラウザに公開しないでください。
- これで、Auth.jsを使用して認証を実装する準備が整いました。
- お楽しみください!
ルート保護
セッションデータは、ルートevent.sharedMap
を介してアクセスできます。そのため、layout.tsx
またはページのindex.tsx
にあるこのようなものを使用して、ルートを保護し、リダイレクトできます
export const onRequest: RequestHandler = (event) => {
const session: Session | null = event.sharedMap.get('session');
if (!session || new Date(session.expires) < new Date()) {
throw event.redirect(302, `/api/auth/signin?redirectTo=${event.url.pathname}`);
}
};
注: layout.tsxに配置する場合は、リダイレクト先が同じlayout.tsxを共有していないことを確認してください。そうしないと、リダイレクトループが発生する可能性があります。