🔐 OAuth ドライバー
OAuth ドライバーは、Passport.js を使用してサードパーティ OAuth プロバイダーを統合するための一貫したレイヤーを提供します。プロバイダー戦略のセットアップをカプセル化し、ルートおよび機能へ合成する Promise ベースの request と callback ヘルパーを公開します。
🎯 概要
NodeBlocks の OAuth ドライバーは、Google、Twitter、LINE 用 Passport.js 戦略の薄いラッパーです。各ファクトリーは同期的であり、await は不要です。
import { drivers } from '@nodeblocks/backend-sdk';
const {
createGoogleOAuthDriver,
createTwitterOAuthDriver,
createLineOAuthDriver,
verifyGoogleCallback,
verifyTwitterCallback,
verifyLineCallback,
PROVIDER_GOOGLE,
PROVIDER_TWITTER,
PROVIDER_LINE,
TWITTER_CALLBACK_STATE_SESSION_KEY,
} = drivers;
各ファクトリーは 3 つのメソッドを持つドライバーオブジェクトを返します。
| メソッド | 目的 |
|---|---|
initialize(app) | Express アプリに Passport と必要なミドルウェアを登録します。 |
request(req, res, state) | OAuth 認可フローを開始します。 |
callback(req, res) | OAuth コールバックを処理し、正規化済みプロファイルを返します。 |
ドライバー定数:
| エクスポート | 値 | ソースファイル |
|---|---|---|
PROVIDER_GOOGLE | 'google' | src/drivers/oauth/google.ts |
PROVIDER_TWITTER | 'twitter' | src/drivers/oauth/twitter/index.ts |
PROVIDER_LINE | 'line' | src/drivers/oauth/line/index.ts |
TWITTER_CALLBACK_STATE_SESSION_KEY | 'twitter-callback-state' | src/drivers/oauth/twitter/index.ts |
グローバル副作用: 各ファクトリーは共有 Passport シングルトンに対して
passport.use(new ...Strategy(...))を呼び出します。複数のファクトリー関数を呼び出すと、プロセス内の同じ Passport インスタンスに戦略が登録されます。
型 — ドライバーインターフェースおよびプロファイル型は types 名前空間にあります(SDK ソース: src/types/oauth.ts)。
import { types } from '@nodeblocks/backend-sdk';
type GoogleOAuthDriver = types.GoogleOAuthDriver;
type GoogleProfile = types.GoogleProfile;
type TwitterOAuthDriver = types.TwitterOAuthDriver;
type TwitterProfile = types.TwitterProfile;
type TwitterCallbackState = types.TwitterCallbackState;
type TwitterRequest = types.TwitterRequest;
type LineOAuthDriver = types.LineOAuthDriver;
type LineProfile = types.LineProfile;
// OAUTH_LOGIN, OAUTH_SIGNUP, OAuthLoginState, ...
コールバック URL: OAuth プロバイダーのコンソールで同じリダイレクト URI を登録し、ドライバーファクトリーに渡してください。SDK の OAuth ルートは
/auth/oauth/{provider}/callback(例:/auth/oauth/google/callback)を使用します。callbackURLはプロバイダー登録と、認証サービスでマウントするルートパスの両方に一致する必要があります。
📋 利用可能な OAuth ドライバー
Google OAuth ドライバー
Passport.js の Google OAuth 2.0 戦略(passport-google-oauth20)を統合します。
createGoogleOAuthDriver
| パラメーター | 型 | デフォルト | 説明 |
|---|---|---|---|
clientID | string | — | Google OAuth クライアント ID |
clientSecret | string | — | Google OAuth クライアントシークレット |
callbackURL | string | — | OAuth 完了後のリダイレクト URL |
scope | string[] | ['email', 'profile'] | OAuth スコープ |
verify | typeof verifyGoogleCallback | verifyGoogleCallback | 任意の検証関数 |
戻り値: GoogleOAuthDriver
const googleDriver = createGoogleOAuthDriver(
process.env.GOOGLE_CLIENT_ID!,
process.env.GOOGLE_CLIENT_SECRET!,
'https://app.com/auth/oauth/google/callback'
);
googleDriver.initialize(app);
Google ドライバーメソッド
戦略は passReqToCallback: true を使用します。カスタム検証関数は第 1 引数として req を受け取ります(デフォルトの verifyGoogleCallback はこれを無視します)。
| メソッド | シグネチャ | 戻り値 |
|---|---|---|
initialize | (app: Express) => void | passport.initialize() を登録します。 |
request | (req, res, state: string) => Promise<void> | { prompt: 'consent', state } で OAuth を開始します。 |
callback | (req, res) => Promise<GoogleProfile> | session: false を指定した { displayName, email, id }。 |
Twitter OAuth ドライバー
レガシーの passport-twitter パッケージではなく、PKCE を備えたカスタム OAuth 2.0 戦略です。
createTwitterOAuthDriver
| パラメーター | 型 | デフォルト | 説明 |
|---|---|---|---|
clientID | string | — | Twitter アプリケーションの App ID |
clientSecret | string | — | Twitter アプリケーションの App Secret |
callbackURL | string | — | Twitter OAuth 用コールバック URL |
sessionSecret | string | — | express-session 用シークレット |
verify | VerifyFunctionWithRequest | verifyTwitterCallback | 任意の検証関数 |
戻り値: TwitterOAuthDriver
セッションミドルウェア(initialize が ['/auth/oauth/twitter', '/auth/oauth/twitter/callback'] に登録):
| 設定 | 値 |
|---|---|
resave | false |
saveUninitialized | false |
| Cookie | httpOnly、sameSite: 'lax'、secure: 'auto'、maxAge: 10 minutes |
戦略のデフォルト(TwitterStrategy に組み込み。ファクトリーからは設定不可):
| 設定 | 値 |
|---|---|
| スコープ | ['users.read', 'tweet.read'] |
| PKCE | true |
| 認可 URL | https://twitter.com/i/oauth2/authorize |
| トークン URL | https://api.twitter.com/2/oauth2/token |
| プロファイル URL | https://api.twitter.com/2/users/me |
const twitterDriver = createTwitterOAuthDriver(
process.env.TWITTER_CLIENT_ID!,
process.env.TWITTER_CLIENT_SECRET!,
'https://app.com/auth/oauth/twitter/callback',
process.env.SESSION_SECRET!
);
twitterDriver.initialize(app);
Twitter ドライバーメソッド
| メソッド | シグネチャ | 戻り値 |
|---|---|---|
initialize | (app: Express) => void | Twitter ルートにセッションミドルウェアを設定してから passport.initialize() を登録します。 |
request | (req: TwitterRequest, res, state: TwitterCallbackState) => Promise<void> | state を req.session[TWITTER_CALLBACK_STATE_SESSION_KEY] に保存し、OAuth を開始します。 |
callback | (req: TwitterRequest, res) => Promise<{ state: TwitterCallbackState; user: TwitterProfile }> | セッション状態とユーザープロファイル。 |
TwitterCallbackState の形状: { typeId, redirectUrl, purpose }。purpose の値は types.OAUTH_LOGIN / types.OAUTH_SIGNUP と対応します。
コールバックエラー:
| 条件 | エラー |
|---|---|
| Passport がユーザーを返さない | Passport の status/info を持つ AuthenticationOAuthError |
| セッション状態がない | AuthenticationOAuthError: 'Twitter OAuth authentication failed. Session state required for executing callback not found.' |
成功時、callback は常に { state, user } を返します。state は実行時に必須です(TypeScript の戻り値型では任意ですが、実装は存在しない場合に拒否します)。
LINE OAuth ドライバー
LINE Login 用のカスタム OAuth 2.0 戦略です。
createLineOAuthDriver
| パラメーター | 型 | デフォルト | 説明 |
|---|---|---|---|
clientID | string | — | LINE チャネル ID |
clientSecret | string | — | LINE チャネルシークレット |
callbackURL | string | — | OAuth 完了後のリダイレクト URL |
scope | string[] | ['profile', 'openid', 'email'] | OAuth スコープ(戦略のデフォルトを上書き) |
verify | VerifyFunctionWithRequest | verifyLineCallback | 任意の検証関数 |
戻り値: LineOAuthDriver
戦略のデフォルト(LineStrategy に組み込み):
| 設定 | 値 |
|---|---|
| 認可 URL | https://access.line.me/oauth2/v2.1/authorize |
| トークン URL | https://api.line.me/oauth2/v2.1/token |
| プロファイル URL | https://api.line.me/oauth2/v2.1/userinfo |
| 組み込みスコープ(ファクトリー上書き前) | ['openid'] |
ファクトリーの scope パラメーターは組み込みデフォルトを上書きします。
const lineDriver = createLineOAuthDriver(
process.env.LINE_CHANNEL_ID!,
process.env.LINE_CHANNEL_SECRET!,
'https://app.com/auth/oauth/line/callback'
);
lineDriver.initialize(app);
LINE ドライバーメソッド
| メソッド | シグネチャ | 戻り値 |
|---|---|---|
initialize | (app: Express) => void | passport.initialize() を登録します。 |
request | (req, res, state: string) => Promise<void> | { session: false, state } で OAuth を開始します。 |
callback | (req, res) => Promise<LineProfile> | session: false を指定した { name, sub }。 |
型と実装:
src/types/oauth.tsのLineOAuthDriver.requestは任意のscopeパラメーターを含むLineRequestAuthentication型ですが、ドライバー実装が受け取るのは(req, res, state)のみです。
コールバックエラー: Passport がユーザーを返さない場合、callback は Passport の status/info を含む AuthenticationOAuthError で拒否します。検証失敗も、返される Promise を拒否します。
カスタム検証関数
各ファクトリーは任意の verify パラメーターを受け取ります(デフォルト値は上記のファクトリー表を参照)。デフォルト検証関数は drivers 名前空間からエクスポートされます。
const { verifyGoogleCallback, verifyTwitterCallback, verifyLineCallback } = drivers;
verifyGoogleCallback
profile.emails[0].value と profile.id を検証してから、{ displayName, email, id } を Passport に渡します。Google が省略する場合、実行時の displayName は undefined になる可能性があります。検証されるのは email と id のみです。必須データがない場合、メッセージ 'Google oauth payload error' の AuthenticationBadRequestError が発生します。
verifyTwitterCallback
profile、profile.id、profile.username を検証してから、{ displayName: profile.name, id, username } を Passport に渡します。Twitter が name を省略する場合、実行時の displayName は undefined になる可能性があります。データがない場合は AuthenticationOAuthError が発生します。
verifyLineCallback
profile.sub を検証してから、{ name: profile?.name, sub } を Passport に渡します。LINE が省略する場合、name は実行時に undefined になる可能性があります。カスタム検証関数は内部戦略(src/drivers/oauth/line/strategy.ts)からの LineUserInfoPayload を受け取ります。これは drivers からエクスポートされません。sub がない場合、メッセージ 'Cannot get sub from line oauth payload' の AuthenticationOAuthError が発生します。
検証失敗時は Passport の done(error) が呼ばれ、ドライバー callback の Promise は拒否します。
🔧 OAuth ドライバーの使用
サービスとともに使用する
ドライバーを作成し、それぞれで initialize(app) を呼び出してから、authService の第 3 引数オプションで注入します。
第 2 引数の設定にある oauth.allowedRedirectOrigins に、OAuth の戻り先として許可するフロントエンドのオリジンを空でないリストで指定します。例えば https://client.app.com/oauth/complete には https://client.app.com が必要です。各ドライバーのバックエンド側の callbackURL とは別の設定です。OAuth リダイレクト先オリジンを参照してください。
SDK の開始ルートは、プロバイダー state の準備や driver.request の呼び出し前に、リクエストの redirectUrl を検証します。不正または許可されていない宛先は 400 を返し、プロバイダーの認可フローは開始しません。オリジンが未設定または空の場合は AuthenticationUnexpectedError が発生し、開始ルートが 500 に対応付けます。
SDK のコールバックルートは、プロバイダーのコールバック処理と state の処理後に、アイデンティティの検査、トークンの生成・保存、リダイレクトより先に validateURL を実行します。state のリダイレクト URL が不正または許可されていない場合は 400、oauth.allowedRedirectOrigins が未設定または空の場合は 500 を返します。この検証はサービスのコールバックルートの処理であり、ドライバーファクトリーとその callback メソッドの既存の仕様は変わりません。
import { services, drivers } from '@nodeblocks/backend-sdk';
const { authService } = services;
const {
createGoogleOAuthDriver,
createTwitterOAuthDriver,
createLineOAuthDriver,
} = drivers;
const googleOAuthDriver = createGoogleOAuthDriver(
process.env.GOOGLE_CLIENT_ID!,
process.env.GOOGLE_CLIENT_SECRET!,
'https://app.com/auth/oauth/google/callback'
);
const twitterOAuthDriver = createTwitterOAuthDriver(
process.env.TWITTER_CLIENT_ID!,
process.env.TWITTER_CLIENT_SECRET!,
'https://app.com/auth/oauth/twitter/callback',
process.env.SESSION_SECRET!
);
const lineOAuthDriver = createLineOAuthDriver(
process.env.LINE_CHANNEL_ID!,
process.env.LINE_CHANNEL_SECRET!,
'https://app.com/auth/oauth/line/callback'
);
googleOAuthDriver.initialize(app);
twitterOAuthDriver.initialize(app);
lineOAuthDriver.initialize(app);
authService(
dataStores,
{
oauth: {allowedRedirectOrigins: ['https://client.app.com', 'http://localhost:3000']},
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET!,
authSignSecret: process.env.AUTH_SIGN_SECRET!,
},
},
{ googleOAuthDriver, twitterOAuthDriver, lineOAuthDriver }
);
完全な Express 接続、データストア、セッション/Cookie セットアップ、OAuth 環境変数、その他の第 3 引数オプション(mailService など)については、認証サービスを参照してください。
🔗 関連ドキュメント
- ドライバー概要 — ドライバーの完全なエクスポート一覧
- OAuth ブロック — OAuth フローのビジネスロジック
- OAuth ルート — OAuth 用 HTTP ルート合成
- 認証サービス — OAuth ドライバー向けサービス接続