> **アプリ用の認証キーの配布は準備中です。**
> アプリ連携の認証APIは実装されていますが、現在は一般向けのキー配布を開始していません。受付開始日や登録方法は、決まり次第案内します。以下は実装されている仕組みの解説です。

あいもげのアプリ連携は、外部ブラウザーで利用者が承認し、アプリ専用の資格を発行する方式です。`POST /app-authorizations` で開始し、承認後に `POST /app-credentials` で資格を受け取ります。

このページでいう `credential` は、認証APIが発行するアプリ専用の秘密の値です。配布アプリに全利用者共通のキーを埋め込む方式ではありません。

## 準備するもの

| 項目 | 内容 |
| --- | --- |
| APIの起点URL | [APIドキュメント](https://api.nijiurachan.net/ui)と運営の案内で確認する接続先 |
| APIバージョン | このガイドでは `2026-08-29` |
| 板のslug | `GET /boards` で確認する対象の板。`X-Board-Key` に指定 |
| `clientId` | 運営に登録されたアプリID。現行仕様の初期対象は `futacha-aimg` |
| `redirectUri` | 承認後にアプリへ戻るURI。運営の登録文字列と完全一致するもの |
| `installationId` | インストール単位のUUID。再認証でも維持する |

任意のアプリID・戻り先で認証できるわけではありません。戻り先のワイルドカードや動的なポート番号は受け付けません。例に載っているIDやURIを使うだけでは本番利用の登録になりません。

`clientId` と `installationId` は公開識別子で、秘密鍵ではありません。

アプリから投稿APIを動作確認する際は、[てすとjun](https://nijiurachan.net/b/test)を対象板にしてください。板のslugは `test` です。アプリの登録と利用者の承認は別途必要です。

## 全体の流れ

1. アプリでstateとPKCE verifierを生成する。
2. `POST /app-authorizations` で認証を開始する。
3. 応答の `authorizationUrl` を外部ブラウザーで開く。
4. 利用者がアプリ名を確認して許可する。
5. 登録済みの戻り先でcodeとstateを受け取る。
6. `POST /app-credentials` でcodeを専用資格へ交換する。
7. APIには `x-aimg-token` ヘッダーで専用資格を送る。

Cloudflareの確認、ブラウザー用トークンの取得、同意画面はWeb側が担当します。アプリがブラウザーのCookieや投稿トークンをコピーしたり、`POST /tokens` に架空のmetricsを送ったりする手順ではありません。

## 1. stateとPKCEを準備する

`state` は、戻ってきた結果が自分の開始した認証か確認する値です。`codeVerifier` は、その認証を開始したアプリだけがコードを交換するための秘密の値です。認証のたびに、別々の暗号学的乱数から生成します。

- state：base64url文字の32〜128文字。
- verifier：43〜128文字。英数字と `-._~` が使える。
- challenge：verifierのASCIIバイト列のSHA-256を、paddingなしbase64urlにした43文字。
- `codeChallengeMethod`：`S256`。

Node.jsでの生成例です。

```js
import { randomBytes, createHash } from 'node:crypto';

const state = randomBytes(32).toString('base64url');
const codeVerifier = randomBytes(32).toString('base64url');
const codeChallenge = createHash('sha256')
  .update(codeVerifier, 'ascii')
  .digest('base64url');
```

stateとverifierは進行中の認証に結び付けてアプリ内へ保持します。verifierを開始リクエストやブラウザーを開くURLへ入れないでください。

## 2. 認証を開始する

```http
POST /app-authorizations
Content-Type: application/json
X-Api-Version: 2026-08-29
X-Board-Key: 対象の板のslug
```

```json
{
  "clientId": "futacha-aimg",
  "redirectUri": "運営に登録した完全一致のURI",
  "installationId": "00000000-0000-4000-8000-000000000001",
  "state": "生成したstate",
  "codeChallenge": "計算したchallenge",
  "codeChallengeMethod": "S256"
}
```

説明用の文字列は実際の登録値・生成値に置き換えます。成功時は201で `{ id, expiresAt, authorizationUrl }` が返り、承認要求は10分間有効です。

返された `authorizationUrl` を外部ブラウザーで開きます。APIとWebのドメインや板の配置が異なることがあるため、承認画面のURLをアプリで独自に組み立てません。

## 3. ブラウザーで承認する

利用者が公式画面でアプリ名を確認し、許可・拒否・キャンセルを選びます。Web側がCloudflareの確認とブラウザー用認証を行います。

`GET /app-authorizations/{id}` と `POST /app-authorizations/{id}/decision` は、この画面のためのAPIです。ブラウザーセッション、CSRF token、正しいOriginが関わるため、アプリやSwagger UIから同意を代行しません。

ブラウザーを閉じた場合にも、アプリ側で待機を終了できるようにしてください。

## 4. アプリへ戻った結果を確認する

| 結果 | 戻り先URIのクエリ |
| --- | --- |
| 許可 | `code=...&state=...` |
| 拒否 | `error=access_denied&state=...` |
| キャンセル | `error=cancelled&state=...` |

URLとして解析し、パラメーター順序に依存しないようにします。戻り先のscheme・host・pathとstateを検証し、キャンセル済み・前回・別の認証の結果は採用しません。

codeは承認から60秒間、一度だけ有効です。正常な結果を受け取ったら速やかに交換します。

## 5. 専用資格へ交換する

```http
POST /app-credentials
Content-Type: application/json
X-Api-Version: 2026-08-29
X-Board-Key: 対象の板のslug
```

```json
{
  "clientId": "futacha-aimg",
  "redirectUri": "開始時と同じ登録URI",
  "code": "戻り先で受け取ったcode",
  "codeVerifier": "この認証の開始時に保存したverifier"
}
```

交換にブラウザーのCookieは不要です。成功時は201で `{ credential, credentialId, expiresAt }` が返ります。

credentialはOSの保護された資格情報保存領域へ保存し、不透明な文字列として扱います。ログ・URL・クラッシュレポートへ出力しないでください。ブラウザー用トークン、GROWI Access Tokenとは別の値です。

## 6. APIを呼び出す

```http
x-aimg-token: 受け取ったcredential
X-Api-Version: 2026-08-29
X-Board-Key: 対象の板のslug
```

`Bearer ` を付けず、値だけを送ります。別ドメインや添付アップロード先へ資格を自動転送しないでください。

認証しても、BAN・role・板の受付条件・投稿間隔・Altchaは免除されません。`GET /client-policy` で現在の板の条件を確認し、投稿ごとに未使用のAltchaの解を用意します。

スレ立て・返信には操作ごとのUUIDを `requestId` として付けます。通信断で結果が分からない場合は同じID・同じ内容を保持し、新しいUUIDで無条件に再送しません。同じ操作の再送では元の完了結果を回復できます。処理中は409 `IDEMPOTENCY_IN_PROGRESS`、同じIDで別の内容を送ると409 `IDEMPOTENCY_CONFLICT` です。

## 期限と接続解除

専用資格は最長21日間で、承認元トークンの有効性やアプリの停止にも影響されます。refresh tokenは発行しません。再認証が必要な場合は、新しいstate・verifierでブラウザー承認からやり直します。

同じアプリ・installationId・承認元の匿名主体で再認証すると、新しい資格の発行時に旧資格が失効します。交換応答を失った場合もcodeを無条件に再利用せず、同じinstallationIdで新しい認証を開始してください。

| 操作 | APIと必要な資格 |
| --- | --- |
| アプリ自身が解除 | `DELETE /app-credentials/current` に自分のcredential。成功204 |
| 接続済み一覧を取得 | `GET /app-credentials` に承認元ブラウザーのトークン。秘密値は返らない |
| ブラウザーから個別に解除 | `DELETE /app-credentials/{id}`。承認元ブラウザーのトークンと正しいOriginが必要 |

ブラウザーの承認画面をrequestIdなしで開くと、接続済みアプリの確認・取り消し画面を利用できます。一覧APIは、アプリが秘密のcredentialを再取得するためのAPIではありません。

## エラーの読み方

| HTTP・コード | 原因と対応 |
| --- | --- |
| 400 `APP_NOT_REGISTERED` | アプリID・戻り先の不一致や運営停止。登録内容を確認 |
| 400 `AUTHORIZATION_INVALID` | PKCE・CSRF・状態などが不正。古い認証を破棄し再開始 |
| 400 `AUTHORIZATION_EXPIRED` | 要求・codeが期限切れ。新しいstate・verifierで再開始 |
| 401 `BROWSER_AUTH_REQUIRED` | ブラウザー側の確認・トークンが不足または失効 |
| 409 `AUTHORIZATION_CONSUMED` | codeを交換済み。繰り返し交換しない |
| 429 `AUTHORIZATION_RATE_LIMITED` | 回数制限。`Retry-After`まで待つ |
| 401 `TOKEN_EXPIRED` | 承認元ブラウザートークンが期限切れ。必要に応じて再認証 |
| 422 `TOKEN_NOT_FOUND` | アプリ資格自身の期限切れ・失効・アプリ停止、資格不存在など。無限再試行しない |

HTMLのCloudflare確認画面や403はAPIのJSONエラーとは別です。[問い合わせ・不具合報告](/運営公式/問い合わせ・不具合報告)へ接続状況を知らせてください。

Swagger UIは入力と応答を調べるために使えますが、state/verifierの保持、アプリへの復帰、利用者の同意を一括で代行しません。配布開始後、登録済みのアプリと外部ブラウザーで一連の動作を検証してください。

---
[API利用ガイド](/運営公式/API利用ガイド) / [Swagger UIの使い方](/運営公式/Swagger%20UIの使い方) / 更新日：2026年10月1日

---

## Page Navigation

- Canonical URL: https://wiki.nijiurachan.net/運営公式/アプリ開発者向け認証ガイド
- Permalink: https://wiki.nijiurachan.net/6aa8cdddd878104439f6715f
- Parent: [運営公式](/6aa8caacd878104439f64039.md)
- Children: 0 total
- Total descendants: 0
- Siblings: 6 total
  - [API利用ガイド](/6aa8caadd878104439f64084.md)
  - [Swagger UIの使い方](/6aa8cdddd878104439f67113.md)
  - [利用規約とモデレーション](/6aa8caaed878104439f640d0.md)
  - [問い合わせ・不具合報告](/6aa8caafd878104439f6411c.md)
  - [編集する際の注意](/6ab5de219260a06592e5ede7.md)
  - [運営への支援](/6ac201659260a0659246a12f.md)
- Last updated: 2026-10-01T02:37:44.214Z by Admin
- Full page listing (all children regardless of count): https://wiki.nijiurachan.net/_api/v3/page-listing/children?id=6aa8cdddd878104439f6715f
