# パートナー向け認証

> 複数のユーザーの代理で公開 API を呼び出す SaaS パートナー向けに、認可コードフロー（PKCE 必須）でアクセストークンを取得する手順。

このページは、複数のネットdeゆうびんユーザーの代理で API を呼び出すサービス（SaaS など）を提供するパートナー向けです。自社のアカウントから郵便物を送るだけであれば、[認証](/guides/authentication/)の手順を使ってください。

パートナーは OAuth 2.0 の認可コードフロー（PKCE 必須）で認証します。ユーザーがブラウザ上で連携を承認すると、そのユーザーとして API を呼び出せるアクセストークンが発行されます。

## クライアント登録

認可コードフローのクライアントはマイページからは発行できません。サポートデスク（[de-api@yubin.app](mailto:de-api@yubin.app)）まで次の情報を取りまとめの上、申請ください。審査・登録後に `client_id` と `client_secret` が発行されます。

- クライアント表示名（同意画面に表示されます）
- リダイレクト URI（複数登録可能）
- スコープ

連携の開発と検証には[テスト環境](/partners/test-environment/)を使えます。テスト環境のクライアントは本番とは別に発行するので、必要な場合は申請時にあわせてお知らせください。

## エンドポイント

| 用途         | URL                                                            |
| ------------ | -------------------------------------------------------------- |
| ディスカバリ | `https://yubin.app/api/oauth/.well-known/openid-configuration` |
| 認可         | `https://yubin.app/api/oauth/auth`                             |
| トークン     | `https://yubin.app/api/oauth/token`                            |
| トークン失効 | `https://yubin.app/api/oauth/token/revocation`                 |
| API          | `https://api.yubin.app/`                                       |

オートディスカバリを使用するライブラリを使う場合は issuer に `https://yubin.app/api/oauth` を渡してください。

## スコープ

[認証](/guides/authentication/#スコープ)のスコープに加え、次のスコープを使えます。

| スコープ         | 内容                       |
| ---------------- | -------------------------- |
| `offline_access` | リフレッシュトークンの発行 |

クライアントに許可されていないスコープを要求してもエラーにはならず、そのスコープが黙って落とされたトークンが発行されます。実際に得られたスコープはトークンレスポンスの `scope` で確認してください。

## 1. 認可リクエスト

`code_verifier` をランダムに生成し、その SHA-256 を base64url エンコードした `code_challenge` を付けてブラウザを認可エンドポイントへ送ります。

```
GET https://yubin.app/api/oauth/auth
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://example.com/callback
  &scope=account:read mails:write offline_access
  &state=RANDOM_STATE
  &code_challenge=CODE_CHALLENGE
  &code_challenge_method=S256
  &prompt=consent
```

- `response_type` は `code` のみ対応します（implicit / hybrid は使えません）。
- PKCE はすべてのクライアントで必須です。`code_challenge_method` は `S256` を使ってください。
- `offline_access` を要求する場合は `prompt=consent` が必須です。付けないと `offline_access` は黙って落とされ、リフレッシュトークンが発行されません。
- OIDC のライブラリが `openid` を自動で付ける場合はそのままで構いません。
- `resource` パラメータは省略できます。省略時は公開 API 向けのアクセストークンが発行されます。

ユーザーがログインと同意を終えると `redirect_uri` に `code` と `state` が付いて戻ります。連携を拒否した場合は `error=access_denied` が返ります。

:::note
同意画面では、クレジットカードが未登録のユーザーにはカード登録フォームが表示されます。カードを登録しないと同意を完了できません（ボタンが「登録して許可する」になります）。連携後の発送依頼にカードが必要なためです。詳しくは[決済](/guides/payment/)を参照してください。
:::

## 2. トークン取得

```http
POST https://yubin.app/api/oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic BASE64(client_id:client_secret)

grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=https://example.com/callback
&code_verifier=CODE_VERIFIER
```

クライアント認証方式は `client_secret_basic` です。

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "...",
  "scope": "account:read mails:write"
}
```

## 3. API 呼び出し

```http
GET https://api.yubin.app/v1/account
Authorization: Bearer ACCESS_TOKEN
```

## 4. トークンの更新

```http
POST https://yubin.app/api/oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic BASE64(client_id:client_secret)

grant_type=refresh_token&refresh_token=REFRESH_TOKEN
```

:::caution
リフレッシュトークンはローテーションされます。更新のたびに新しい `refresh_token` が返るので、必ず保存し直してください。古いリフレッシュトークンは使えなくなります。
:::

## 連携の解除

トークン失効エンドポイント（`/token/revocation`）にアクセストークンまたはリフレッシュトークンを送ると失効させられます。ユーザー側からも yubin.app の画面で連携を解除できます。

## 認証エラー

エラーの形式はクライアントクレデンシャルフローと同じです。[認証エラー](/guides/authentication/#認証エラー)を参照してください。