プレビュー版
PocketSign Link v2 は現在プレビュー版です。正式提供までに仕様が変更される可能性があります。
エラーリファレンス
PocketSign Link v2 のエラーは、返り方が場面ごとに異なります。 このページでは、エラーの全体像と横断的なハンドリング指針をまとめます。 各 API 固有のエラーコードは、それぞれの API ページを参照してください。
エラーの見え方
| 場面 | 返り方 | 詳細ページ |
|---|---|---|
authorize のフロントチャネル | redirect_uri へのクエリパラメータ、または画面遷移失敗 | 認可リクエスト |
par | サーバー間のエラーレスポンス | 認可リクエスト |
token | サーバー間のエラーレスポンス | トークン |
userinfo / introspect / revoke | サーバー間のエラーレスポンス | UserInfo・Introspection |
| IdP ConnectRPC API | ConnectRPC detail の error reason | IdPUserService API / IdPClientService API |
| Registry 読み取り系 | result.error フィールド | RegistryUserService API / RegistryClientService API |
| Registry 書き込み系 | ConnectRPC detail の error reason | RegistryUserService API / RegistryClientService API |
OIDC エラーのハンドリング指針
prompt=none系のエラー(login_required、interaction_required、consent_required)は、そのまま失敗画面にせず、ユーザー操作が必要なことを RP で扱うinvalid_clientは運用設定や秘密情報の問題として扱うinvalid_grantは再ログインや再認可に戻す判断材料にする
userinfo / introspect / revoke での注意
userinfo
- Bearer トークンなら
Authorization: Bearer - DPoP トークンなら
Authorization: DPoPとDPoPproof が必要
introspect / revoke
- クライアント認証が必要
- トークン自体が無効でも、
revokeは RFC 7009 に従い200 OKを返すことがある
ConnectRPC の detail error
PocketSign Link v2 の ConnectRPC API では、標準の Connect エラーコード(NOT_FOUND、PERMISSION_DENIED など)に加えて、エラーの原因を特定するための detail error を返します。
detail error は ConnectRPC の error details として、google.rpc.ErrorInfo の reason フィールドに格納されます。
レスポンス形式
{
"code": "not_found",
"message": "subscription not found",
"details": [
{
"type": "google.rpc.ErrorInfo",
"value": {
"reason": "REGISTRY_USER_SERVICE_ERROR_CODE_SUBSCRIPTION_NOT_FOUND"
}
}
]
}
| フィールド | 説明 |
|---|---|
code | Connect の標準エラーコード(not_found、permission_denied、invalid_argument、failed_precondition など) |
message | エラーの概要メッセージ |
details[].value.reason | PocketSign Link v2 固有のエラーコード。エラーの原因を一意に特定できる |
RP 側でエラーハンドリングを実装する際は、code だけでなく reason を使って分岐することで、より適切なエラー処理が可能になります。
reason で分岐する
同じ Connect code でも reason が異なる場合があります。たとえば permission_denied は「権限なし」「一時停止」「期限切れ」の 3 通りがあり、それぞれ RP 側で異なる対応が必要です。
| reason | 対応の例 |
|---|---|
*_PERMISSION_DENIED | 権限要求の導線を提示する |
*_PERMISSION_SUSPENDED | ユーザーに権限の再有効化を案内する |
*_PERMISSION_EXPIRED | 再認可を促す |
*_SUBSCRIPTION_NOT_FOUND | サブスクリプションの存在を確認する |
*_RESOURCE_DEFINITION_NOT_FOUND | リソース ID またはエイリアスの指定を確認する |
*_JSON_SCHEMA_VALIDATION_FAILED | 書き込む値をリソース定義の JSON Schema に合わせる |
*_INVALID_VALUE_FORMAT | リソースの値形式(文字列 / JSON / バイナリ)を確認する |
その他の reasonについては、API ドキュメント を参照してください。
details の取得方法
ConnectRPC クライアントライブラリを使っている場合、エラーレスポンスの details から google.rpc.ErrorInfo を取得して reason を参照します。
- Go
- TypeScript
import (
"errors"
"connectrpc.com/connect"
"google.golang.org/genproto/googleapis/rpc/errdetails"
)
_, err := client.WriteResourceValue(ctx, req)
if err != nil {
var connectErr *connect.Error
if errors.As(err, &connectErr) {
for _, detail := range connectErr.Details() {
value, unwrapErr := detail.Value()
if unwrapErr != nil {
continue
}
if errorInfo, ok := value.(*errdetails.ErrorInfo); ok {
switch errorInfo.GetReason() {
case "REGISTRY_USER_SERVICE_ERROR_CODE_PERMISSION_DENIED":
// 権限要求の導線を表示
case "REGISTRY_USER_SERVICE_ERROR_CODE_PERMISSION_SUSPENDED":
// ユーザーに権限の再有効化を案内
case "REGISTRY_USER_SERVICE_ERROR_CODE_PERMISSION_EXPIRED":
// 再認可を促す
case "REGISTRY_USER_SERVICE_ERROR_CODE_JSON_SCHEMA_VALIDATION_FAILED":
// 書き込む値を修正
default:
// その他のエラー
}
}
}
}
}
import { ConnectError } from "@connectrpc/connect";
import { ErrorInfo } from "@buf/googleapis_googleapis.bufbuild_es/google/rpc/error_details_pb";
try {
await client.writeResourceValue(request);
} catch (err) {
const connectErr = ConnectError.from(err);
const errorInfo = connectErr.findDetails(ErrorInfo).at(0);
if (errorInfo) {
switch (errorInfo.reason) {
case "REGISTRY_USER_SERVICE_ERROR_CODE_PERMISSION_DENIED":
// 権限要求の導線を表示
break;
case "REGISTRY_USER_SERVICE_ERROR_CODE_PERMISSION_SUSPENDED":
// ユーザーに権限の再有効化を案内
break;
case "REGISTRY_USER_SERVICE_ERROR_CODE_PERMISSION_EXPIRED":
// 再認可を促す
break;
case "REGISTRY_USER_SERVICE_ERROR_CODE_JSON_SCHEMA_VALIDATION_FAILED":
// 書き込む値を修正
break;
default:
// その他のエラー
break;
}
}
}