メインコンテンツまでスキップ
バージョン: 0.15.0 (最新)

🔐 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​

パラメーター型デフォルト説明
clientIDstring—Google OAuth クライアント ID
clientSecretstring—Google OAuth クライアントシークレット
callbackURLstring—OAuth 完了後のリダイレクト URL
scopestring[]['email', 'profile']OAuth スコープ
verifytypeof verifyGoogleCallbackverifyGoogleCallback任意の検証関数

戻り値: 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) => voidpassport.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​

パラメーター型デフォルト説明
clientIDstring—Twitter アプリケーションの App ID
clientSecretstring—Twitter アプリケーションの App Secret
callbackURLstring—Twitter OAuth 用コールバック URL
sessionSecretstring—express-session 用シークレット
verifyVerifyFunctionWithRequestverifyTwitterCallback任意の検証関数

戻り値: TwitterOAuthDriver

セッションミドルウェア(initialize が ['/auth/oauth/twitter', '/auth/oauth/twitter/callback'] に登録):

設定値
resavefalse
saveUninitializedfalse
CookiehttpOnly、sameSite: 'lax'、secure: 'auto'、maxAge: 10 minutes

戦略のデフォルト(TwitterStrategy に組み込み。ファクトリーからは設定不可):

設定値
スコープ['users.read', 'tweet.read']
PKCEtrue
認可 URLhttps://twitter.com/i/oauth2/authorize
トークン URLhttps://api.twitter.com/2/oauth2/token
プロファイル URLhttps://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) => voidTwitter ルートにセッションミドルウェアを設定してから 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​

パラメーター型デフォルト説明
clientIDstring—LINE チャネル ID
clientSecretstring—LINE チャネルシークレット
callbackURLstring—OAuth 完了後のリダイレクト URL
scopestring[]['profile', 'openid', 'email']OAuth スコープ(戦略のデフォルトを上書き)
verifyVerifyFunctionWithRequestverifyLineCallback任意の検証関数

戻り値: LineOAuthDriver

戦略のデフォルト(LineStrategy に組み込み):

設定値
認可 URLhttps://access.line.me/oauth2/v2.1/authorize
トークン URLhttps://api.line.me/oauth2/v2.1/token
プロファイル URLhttps://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) => voidpassport.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 など)については、認証サービスを参照してください。


🔗 関連ドキュメント​