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

🔐 認証ユーティリティ

Nodeblocks SDK は、トークン管理、検証、セキュリティのための包括的な認証ユーティリティを提供します。これらのユーティリティは、Bearer トークン、Cookie ベース認証、およびさまざまなユースケース向けの各種トークンタイプを処理します。


🎯 概要

認証ユーティリティは、ユーザーおよびアプリケーション認証の両方に対し、安全なトークン生成、検証、管理を提供します。複数のトークンタイプとセキュリティ検証メカニズムをサポートします。

サービスレベルの構成(authModecheckIp、トークン署名オプション)については、Authentication サービスを参照してください。

主な機能

  • 複数のトークンタイプ: ユーザーアクセス、アプリアクセス、リフレッシュ、ワンタイムトークン
  • セキュリティ検証: フィンガープリント、IP、ユーザーエージェントの検証
  • 柔軟な認証: Bearer トークンおよび Cookie ベース認証
  • 二層トークン: 署名済み JWT を囲む AES-256-CBC 暗号化エンベロープ

トークン形式

トークンは二層形式を使用します:

  1. 内側の層: authSignSecret で署名した標準 JWT(jsonwebtoken を使用)
  2. 外側の層: authEncSecret から SHA-256 で導出したキーによる AES-256-CBC 暗号化。iv_hex:ciphertext_hex として保存されます

エンベロープには encryptdecrypt を使用し、復号と検証を一度に行うには decryptAndVerifyJWT を使用します。

デフォルトのトークン有効期間

トークンデフォルトの expiresIn
ユーザーアクセス'15m'
Refresh'2d'
ワンタイム'5m'
アプリアクセスなし(署名オプションにデフォルトの有効期限はありません)

🔑 トークン生成

generateUserAccessToken

セキュリティ検証メタデータを含む暗号化ユーザーアクセストークンを作成します。

import { utils } from '@nodeblocks/backend-sdk';

const { generateUserAccessToken } = utils;

const token = generateUserAccessToken(
authSecrets,
{ expiresIn: '30m' }, // optional; default '15m'
identityId,
{
fingerprint: 'device-fingerprint',
ip: '192.168.1.1',
domain: 'example.com',
userAgent: 'Mozilla/5.0...'
}
);

パラメーター:

  • authSecrets: 暗号化/署名用の認証シークレット
  • jwtSignOptions: jsonwebtoken の必須 SignOptions | undefined パラメーター。デフォルトの expiresIn: '15m' を使用するには undefined を渡します
  • identityId: アイデンティティ識別子
  • tokenVerification: 検証用セキュリティコンテキスト

注記:

  • 生成トークンは常に stateful: false です(この関数では設定不可)

generateAppAccessToken

サービス間通信向けの暗号化アプリアクセストークンを作成します。

import { utils } from '@nodeblocks/backend-sdk';

const { generateAppAccessToken } = utils;

const token = generateAppAccessToken(authSecrets, 'app-service-id');

パラメーター:

  • authSecrets: 認証シークレット
  • appId: アプリケーション識別子

generateRefreshToken

セッション管理用の暗号化リフレッシュトークンを作成します。

import { utils } from '@nodeblocks/backend-sdk';

const { generateRefreshToken } = utils;

const token = generateRefreshToken(
authSecrets,
'jwt-token-id',
identityId,
{
fingerprint: 'device-fingerprint',
ip: '192.168.1.1',
domain: 'example.com',
userAgent: 'Mozilla/5.0...'
},
{ expiresIn: '7d' } // optional; default '2d'
);

パラメーター:

  • authSecrets: 認証シークレット
  • jti: ステートフルリフレッシュトークン追跡用 JWT トークン ID
  • identityId: アイデンティティ識別子
  • tokenVerification: 検証用セキュリティコンテキスト
  • jwtSignOptions: 任意の SignOptions(デフォルト expiresIn: '2d'

注記:

  • 生成トークンは常に stateful: true です(ハードコードされ、この関数では設定不可)

generateOnetimeToken

一時アクセス用のワンタイムトークンを作成します。

import { utils } from '@nodeblocks/backend-sdk';

const { generateOnetimeToken } = utils;

const token = generateOnetimeToken(
authSecrets,
{ identityId: 'id-123', action: 'password-reset' },
{
fingerprint: 'device-fingerprint',
ip: '192.168.1.1',
domain: 'example.com',
userAgent: 'Mozilla/5.0...'
},
{ expiresIn: '1h' } // optional; default '5m'
);

パラメーター:

  • authSecrets: 認証シークレット
  • data: トークンに埋め込むペイロード(Record<string, unknown>
  • tokenVerification: 検証用セキュリティコンテキスト
  • jwtSignOptions: 任意の SignOptions(デフォルト expiresIn: '5m'

注記:

  • 生成トークンは常に stateful: true です(ハードコードされ、この関数では設定不可)

🔍 トークン検証

getBearerTokenInfo

リクエストの Authorization ヘッダーからトークン情報を抽出します。Bearer トークン用のデフォルト認証関数です。

import { utils } from '@nodeblocks/backend-sdk';

const { getBearerTokenInfo } = utils;

const tokenInfo = await getBearerTokenInfo(payload);

処理:

  1. Authorization: Bearer <token> ヘッダーからトークンを抽出します
  2. JWT 署名を復号して検証します
  3. トークンタイプ(ユーザーまたはアプリ)を検証します
  4. ユーザートークンのセキュリティチェックを実行します(アプリトークンはセキュリティチェックを省略します)
  5. トークン情報を返します

IP バインディング: payload.context.configuration.checkIp で制御します。未設定時、IP チェックはデフォルトで有効です(checkIp ?? true)。

エラー: トークンが欠落、不正、アクセストークンでない、またはセキュリティチェックに失敗した場合(ユーザートークン)、NodeblocksError(401) をスローします。アプリアクセストークンはセキュリティチェックを省略し、AppAccessTokenInfo を返します。

getCookieTokenInfo

Cookie からトークン情報を抽出します。authMode'cookie' のときの Cookie ベーストークン用認証関数です。

import { utils } from '@nodeblocks/backend-sdk';

const { getCookieTokenInfo } = utils;

const tokenInfo = await getCookieTokenInfo(payload);

ユースケース:

  • Cookie ベース認証を使用する Web アプリケーション(cookies.accessToken
  • cookie-parser を使用するサーバーサイドセッション管理

注: Cookie モードと Bearer モードの違いはトークン転送のみです。セキュリティチェック(フィンガープリント、IP、ユーザーエージェント)は、configuration.checkIp ?? true を含め、getBearerTokenInfo と同じロジックを使用します。

エラー: cookies.accessToken が欠落、不正、アクセストークンでない、またはセキュリティチェックに失敗した場合(ユーザートークン)、NodeblocksError(401) をスローします。アプリアクセストークンはセキュリティチェックを省略し、AppAccessTokenInfo を返します。

defaultRefreshTokenBodyAuth

リクエスト本文から取得するリフレッシュトークン用のデフォルト認証関数です。常にトークンを抽出し、decryptTokentrue の場合は復号、検証、セキュリティチェックを行います。

import { utils } from '@nodeblocks/backend-sdk';

const { defaultRefreshTokenBodyAuth } = utils;

const { token, tokenInfo } = await defaultRefreshTokenBodyAuth(
authSecrets,
request,
true, // decryptToken
logger
);

パラメーター:

  • authSecrets: トークン復号用の認証シークレット
  • request: リフレッシュトークンを含む HTTP リクエストオブジェクト
  • decryptToken: トークンを復号および検証するか(デフォルト: false)
  • logger: セキュリティチェックログ用の任意ロガー

処理:

  1. request.body.refreshToken からリフレッシュトークンを抽出します
  2. トークン検証コンテキスト(フィンガープリント、IP、ユーザーエージェント)を取得します
  3. トークン形式と存在を検証します
  4. JWT 署名を復号して検証します(decryptToken が true の場合)
  5. トークンタイプがリフレッシュトークンであることを検証します
  6. IP 検証を有効にしてセキュリティチェックを実行します
  7. トークンおよびトークン情報を返します

defaultRefreshTokenCookieAuth

Cookie から取得するリフレッシュトークン用のデフォルト認証関数です。常にトークンを抽出し、decryptTokentrue の場合は復号、検証、セキュリティチェックを行います。そのモードでは tokentokenInfo の両方を返します。

import { utils } from '@nodeblocks/backend-sdk';

const { defaultRefreshTokenCookieAuth } = utils;

const { token, tokenInfo } = await defaultRefreshTokenCookieAuth(
authSecrets,
request,
true, // decryptToken
logger
);

パラメーター:

  • authSecrets: トークン復号用の認証シークレット
  • request: Cookie 内のリフレッシュトークンを含む HTTP リクエストオブジェクト
  • decryptToken: トークンを復号および検証するか(デフォルト: false)
  • logger: セキュリティチェックログ用の任意ロガー

処理:

  1. request.cookies.refreshToken からリフレッシュトークンを抽出します
  2. トークン検証コンテキスト(フィンガープリント、IP、ユーザーエージェント)を取得します
  3. トークン形式と存在を検証します
  4. JWT 署名を復号して検証します(decryptToken が true の場合)
  5. トークンタイプがリフレッシュトークンであることを検証します
  6. IP 検証を有効にしてセキュリティチェックを実行します(checkIp: true
  7. トークンおよびトークン情報を返します(decryptToken が true の場合)

本文認証との主な違い:

  • ソース: リクエスト本文ではなく Cookie から読み取ります

resolveRefreshTokenFromRequest

Cookie および/またはリクエスト本文からリフレッシュトークンを解決します。両方のソースが存在する場合、同じトークンを指す必要があります。

import { utils } from '@nodeblocks/backend-sdk';

const { resolveRefreshTokenFromRequest } = utils;

const result = await resolveRefreshTokenFromRequest(authSecrets, request, logger);

if (result.isOk() && result.value) {
const { token, tokenInfo } = result.value;
}

パラメーター:

  • authSecrets: トークン復号用の認証シークレット
  • request: HTTP リクエストオブジェクト
  • logger: セキュリティチェックログ用の任意ロガー

戻り値:

  • Result<{ token: string; tokenInfo: RefreshTokenInfo } | undefined, NodeblocksError>
  • 有効なリフレッシュトークンが見つからない場合は ok(undefined) を返します
  • Cookie と本文のトークンが一致しない場合は、401 の err(...) を返します

🛡️ セキュリティ関数

tokenPassesSecurityCheck

トークンのセキュリティコンテキストを検証します。

import { utils } from '@nodeblocks/backend-sdk';

const { tokenPassesSecurityCheck } = utils;

const isValid = tokenPassesSecurityCheck(
tokenInfo,
{
fingerprint: 'device-fingerprint',
ip: '192.168.1.1',
userAgent: 'Mozilla/5.0...'
},
logger,
{ checkIp: true }
);

検証ロジック:

  1. フィンガープリントは一致する必要があります。一致しない場合、チェックは直ちに失敗します
  2. checkIp が無効の場合、チェックは成功します(フィンガープリントはすでに一致しています)
  3. checkIp が有効で IP が一致する場合、チェックは成功します
  4. checkIp が有効で IP が一致しない場合、ユーザーエージェントが一致するときにのみチェックは成功します。それ以外は失敗します

パラメーター:

  • tokenInfo: ユーザーアクセスまたはリフレッシュトークン情報
  • tokenVerification: 現在のリクエストコンテキスト(domainfingerprintipuserAgent
  • logger: 任意のロガー
  • options.checkIp: IP バインディングチェックを実行するか(デフォルト: true

decryptAndVerifyJWT

AES エンベロープを復号し、内側の JWT 署名を検証します。

import { utils } from '@nodeblocks/backend-sdk';

const { decryptAndVerifyJWT } = utils;

const tokenInfo = decryptAndVerifyJWT(authSecrets, encryptedToken);

エラー: トークンが空、形式不正、不正、または期限切れの場合、ステータス 401NodeblocksError をスローします。フィンガープリント/IP/ユーザーエージェントチェックは実行しません。呼び出し元(例: 認証関数)は、ユーザートークンに対して別途 tokenPassesSecurityCheck を実行する必要があります。


🔧 ヘルパー関数

getBearerToken

リクエストヘッダーから Bearer トークンを抽出します。

import { utils } from '@nodeblocks/backend-sdk';

const { getBearerToken } = utils;

const token = getBearerToken(request.headers);
// Returns: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

エラー: Authorization ヘッダーがない場合は undefined を返します。ヘッダーが存在するものの文字列でない、または Bearer <token> 形式でない場合は、ステータス 422NodeblocksError をスローします。

getFingerprint

ヘッダーからデバイスフィンガープリントを抽出します。

import { utils } from '@nodeblocks/backend-sdk';

const { getFingerprint } = utils;

const fingerprint = getFingerprint(request.headers, 'x-nb-fingerprint');

エラー: ヘッダーが存在するものの文字列でない場合、ステータス 422NodeblocksError をスローします。

getUserAgent

リクエストヘッダーからユーザーエージェントを抽出します。

import { utils } from '@nodeblocks/backend-sdk';

const { getUserAgent } = utils;

const userAgent = getUserAgent(request.headers);

getRequestInfo

トークン検証用のリクエストメタデータを抽出します。

import { utils } from '@nodeblocks/backend-sdk';

const { getRequestInfo } = utils;

const requestInfo = getRequestInfo(request);
// Returns: { host, ip, method, path, url }

getExpiresIn

トークンの有効期限値を正規化します。さまざまな入力形式を標準化された有効期限形式に変換します。

import { utils } from '@nodeblocks/backend-sdk';

const { getExpiresIn } = utils;

const expiresIn = getExpiresIn('24h'); // Returns: '24h'
const expiresIn2 = getExpiresIn(3600000); // Returns: 3600000
const expiresIn3 = getExpiresIn(); // Returns: '48h' (default)

パラメーター:

  • expirationTime: 文字列または数値として指定する任意の有効期限

戻り値:

  • number | string: 正規化済み有効期限(デフォルト: '48h')

動作:

  • expirationTimenull または undefined の場合: デフォルトの '48h' を返します
  • expirationTime が有効な数値の場合: その数値を返します
  • expirationTime が非数値文字列の場合: 文字列をそのまま返します
  • expirationTime が数値文字列の場合: 数値に変換します

getExpirationDate

期間文字列またはミリ秒に基づいて絶対有効期限日時を計算します。

import { utils } from '@nodeblocks/backend-sdk';

const { getExpirationDate } = utils;

const expirationDate = getExpirationDate('7d'); // Returns: Date object 7 days from now
const expirationDate2 = getExpirationDate(3600000); // Returns: Date object 1 hour from now
const expirationDate3 = getExpirationDate(); // Returns: Date object 2 days from now (default)

パラメーター:

  • expiresIn: 期間文字列(例: '7d'、'24h'、'30m')またはミリ秒(デフォルト: '2d'

戻り値:

  • Date: 絶対有効期限日時

対応する期間形式:

  • '7d' - 7 日
  • '24h' - 24 時間
  • '30m' - 30 分
  • '60s' - 60 秒
  • ミリ秒の数値

deriveCookieMaxAge

トークンの expiresIn 値を Express Cookie の maxAge オプション用のミリ秒に変換します。

import { utils } from '@nodeblocks/backend-sdk';

const { deriveCookieMaxAge } = utils;

const maxAge = deriveCookieMaxAge('15m'); // Returns: 900000 (ms)
const maxAge2 = deriveCookieMaxAge(3600); // Returns: 3600000 (3600 seconds → ms)

パラメーター:

  • expiresIn: 期間文字列(ms() で解析)、または 単位の数値(jsonwebtoken の規約に準拠)

戻り値:

  • number: ミリ秒単位の期間

注: getExpirationDate と異なり、ここでは単独の数値をミリ秒ではなくとして扱います。

isAccessToken

トークンがアクセストークン(ユーザーまたはアプリ)かどうかを確認し、単純な型ガードとして使用できます。

import { utils } from '@nodeblocks/backend-sdk';

const { isAccessToken } = utils;

if (isAccessToken(tokenInfo)) {
// tokenInfo is AccessTokenInfo (accessType: 'user' | 'app')
}

パラメーター:

  • tokenInfo: 確認するトークン情報オブジェクト

戻り値:

  • boolean: トークンがアクセストークンなら true、それ以外は false

isUserAccessToken

トークンがユーザーアクセストークンかどうかを確認します。

import { utils } from '@nodeblocks/backend-sdk';

const { isUserAccessToken } = utils;

if (isUserAccessToken(tokenInfo)) {
// tokenInfo is UserAccessTokenInfo
console.log(tokenInfo.identityId);
}

パラメーター:

  • tokenInfo: 確認するトークン情報オブジェクト

戻り値:

  • boolean: トークンがユーザーアクセストークンなら true、それ以外は false

isAppAccessToken

トークンがアプリアクセストークンかどうかを確認します。

import { utils } from '@nodeblocks/backend-sdk';

const { isAppAccessToken } = utils;

if (isAppAccessToken(tokenInfo)) {
// tokenInfo is AppAccessTokenInfo
console.log(tokenInfo.appId);
}

パラメーター:

  • tokenInfo: 確認するトークン情報オブジェクト

戻り値:

  • boolean: トークンがアプリアクセストークンなら true、それ以外は false

isRefreshToken

トークンがリフレッシュトークンかどうかを確認します。

import { utils } from '@nodeblocks/backend-sdk';

const { isRefreshToken } = utils;

if (isRefreshToken(tokenInfo)) {
// tokenInfo is RefreshTokenInfo
console.log(tokenInfo.jti);
}

パラメーター:

  • tokenInfo: 確認するトークン情報オブジェクト

戻り値:

  • boolean: トークンがリフレッシュトークンなら true、それ以外は false

isOnetimeToken

トークンがワンタイムトークンかどうかを確認します。

import { utils } from '@nodeblocks/backend-sdk';

const { isOnetimeToken } = utils;

if (isOnetimeToken(tokenInfo)) {
// tokenInfo is OnetimeTokenInfo
console.log(tokenInfo.data);
}

パラメーター:

  • tokenInfo: 確認するトークン情報オブジェクト

戻り値:

  • boolean: トークンがワンタイムトークンなら true、それ以外は false

isValidAppAccessToken

アプリアクセストークンに appId が存在することを確認します。

import { utils } from '@nodeblocks/backend-sdk';

const { isValidAppAccessToken } = utils;

if (isValidAppAccessToken(tokenInfo)) {
// tokenInfo is AppAccessTokenInfo with appId present
}

パラメーター:

  • tokenInfo: 確認するトークン情報オブジェクト

戻り値:

  • boolean: appId を持つアプリアクセストークンなら true、それ以外は false

isValidUserAccessToken

ユーザーアクセストークンに identityId が存在することを確認します。

import { utils } from '@nodeblocks/backend-sdk';

const { isValidUserAccessToken } = utils;

if (isValidUserAccessToken(tokenInfo)) {
// tokenInfo is UserAccessTokenInfo with identityId present
}

パラメーター:

  • tokenInfo: 確認するトークン情報オブジェクト

戻り値:

  • boolean: identityId を持つユーザーアクセストークンなら true、それ以外は false

retrieveTokenVerification

Express の Request からトークン検証メタデータを作成します。

import { utils } from '@nodeblocks/backend-sdk';

const { retrieveTokenVerification } = utils;

const verification = retrieveTokenVerification(request);
// { domain, fingerprint, ip, userAgent }

validateAuthSecrets

必須の認証シークレットを検証し、欠落または短すぎる場合はスローします。

import { utils } from '@nodeblocks/backend-sdk';

const { validateAuthSecrets } = utils;

validateAuthSecrets(authSecrets); // throws on invalid configuration
validateAuthSecrets(authSecrets, 24); // optional minimum length (default: 18)

エラー: シークレットが欠落している、または最小長より短い場合、ステータス 500NodeblocksError をスローします。

generateMailBody

URL とオプションをメールテンプレートに補間します。

import { utils } from '@nodeblocks/backend-sdk';

const { generateMailBody } = utils;

const body = generateMailBody(
'Click here: ${url}',
'https://example.com/reset?token=${token}',
{ token: 'abc' }
);

authSecretsValidationErrorMessage

無効な認証シークレットに対する人間可読なエラーを返します(一時的なヘルパー)。

import { utils } from '@nodeblocks/backend-sdk';

const { authSecretsValidationErrorMessage } = utils;

const msg = authSecretsValidationErrorMessage(authSecrets);
if (msg) throw new Error(msg);

// Optional minimum length (default: 18)
const msg2 = authSecretsValidationErrorMessage(authSecrets, 24);

🔐 暗号化関数

encrypt

AES-256-CBC を使用して文字列を暗号化します。iv_hex:ciphertext_hex を返します。

import { utils } from '@nodeblocks/backend-sdk';

const { encrypt } = utils;

const encrypted = encrypt(authSecrets.authEncSecret, 'sensitive-data');

decrypt

AES-256-CBC エンベロープ(iv_hex:ciphertext_hex)を復号します。

import { utils } from '@nodeblocks/backend-sdk';

const { decrypt } = utils;

const decrypted = decrypt(authSecrets.authEncSecret, encryptedData);

エラー: 入力が空、形式不正、または不正の場合、ステータス 401NodeblocksError をスローします。


🔑 パスワード関数

hash

コスト係数 10 の bcrypt を使用してパスワードをハッシュ化します。

import { utils } from '@nodeblocks/backend-sdk';

const { hash } = utils;

const hashedPassword = await hash('user-password');

実装: 10 回のソルトラウンドで bcrypt を使用します(bcryptHash(s, 10))。

compareHash

パスワードとハッシュを比較します。

import { utils } from '@nodeblocks/backend-sdk';

const { compareHash } = utils;

const isValid = await compareHash('user-password', hashedPassword);

📊 トークンタイプ

トークンインターフェースは utils ではなく、types 名前空間(ソース: src/types/authentication.ts)からエクスポートされます:

import { types } from '@nodeblocks/backend-sdk';

type UserAccessTokenInfo = types.UserAccessTokenInfo;
type AppAccessTokenInfo = types.AppAccessTokenInfo;
type RefreshTokenInfo = types.RefreshTokenInfo;
type OnetimeTokenInfo = types.OnetimeTokenInfo;

ユーザーアクセストークン

interface UserAccessTokenInfo {
accessType: 'user';
identityId: string;
type: 'access';
stateful: boolean;
fingerprint?: string;
ip?: string;
domain?: string;
target?: string;
userAgent?: string;
}

アプリアクセストークン

interface AppAccessTokenInfo {
accessType: 'app';
appId: string;
type: 'access';
}

リフレッシュトークン

interface RefreshTokenInfo {
type: 'refresh';
jti: string;
identityId: string;
stateful: true;
fingerprint?: string;
ip?: string;
domain?: string;
userAgent?: string;
}

ワンタイムトークン

interface OnetimeTokenInfo {
type: 'onetime';
data: Record<string, unknown>;
stateful: true;
fingerprint?: string;
ip?: string;
domain?: string;
target?: string;
userAgent?: string;
}