diff --git a/content/tw/docs/4.for-developers/api/token/3.oauth.md b/content/tw/docs/4.for-developers/api/token/3.oauth.md
new file mode 100644
index 00000000..509142b9
--- /dev/null
+++ b/content/tw/docs/4.for-developers/api/token/3.oauth.md
@@ -0,0 +1,178 @@
+---
+description: v2023.9.0以降で使用できる、OAuth2.0方式での認証方法について説明しています。
+---
+
+# OAuth方式でのアクセストークン取得方式
+
+アプリケーションを利用するユーザー(以下単に「ユーザー」と呼びます)のアクセストークンを取得するには、以下の手順で発行をリクエストします。
+
+:::tip
+
+以下に説明する方法は、[OAuth 2.0](https://datatracker.ietf.org/doc/html/rfc6749.html)と呼ばれるものです。普通のOAuthはアプリを作成しますが、[IndieAuth](https://indieauth.spec.indieweb.org/)の拡張でアプリ作成なしで使えるようになっています。
+
+OAuth方式は使えるライブラリが多いので、出来ればライブラリを使うのをおすすめします。
+
+現在、この方式を使うためにはウェブページが必要になります。どうしてもウェブページを用意できない場合、もしくはMisskey 2023.9.0以前のバージョンをサポートしたい場合、以下の方式を使ってください。
+
+- [Misskey専用のMiAuth方式でのアクセストークン取得方法](./oauth.md)
+- [アプリ作成方式でのアクセストークン取得方法(旧来型)。](./app.md)
+ :::
+
+## Step 1
+
+アプリ紹介のためのウェブページを作ります。ページがHTTPSアドレスでアクセスできるようにしてください。ページのとこかに以下のようなHTMLコードを書きます。
+
+```html
+
+
+
+
+
+```
+
+あとで`redirect_uri`のアドレスに認証コードが転送されます。
+
+## Step 2
+
+PKCE `code_verifier`と`code_challenge`文字列, 及び`state`文字列を生成します。
+
+- `code_verifier`の場合は最低43字、最高128字でアルファベット大・小文字及び`-._~`の中の文字に限られます。
+- `code_challenge`文字列は`code_verifier`文字列をSHA256アルゴリズムでハッシュしてbase64urlでエンコードした結果を使います。
+- `state`文字列には特別な制限はありません。ランダムな文字列を使います。
+
+:::danger
+
+この文字列は毎回生成し、使いまわさないようにしてください。
+
+:::
+
+:::tip
+
+[pkce-challenge](https://www.npmjs.com/package/pkce-challenge)とかのライブラリを使ったり、OAuthライブラリのPKCE機能を使うのがおすすめです。
+
+:::
+
+:::tip{label='例'}
+
+```js
+import crypto from "node:crypto";
+
+const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~";
+const codeVerifier = new Array(128)
+ .fill(0)
+ .map(() => chars[Math.floor(chars.length * Math.random())])
+ .join("");
+console.log('code_verifier', codeVerifier);
+
+const codeChallenge = crypto
+ .createHash("sha256")
+ .update(codeVerifier, "ascii")
+ .digest("base64url");
+console.log('code_challenge', codeChallenge);
+
+const state = crypto.randomUUID();
+console.log('state', state);
+```
+
+:::
+
+## Step 3
+
+相手サーバーのOAuth情報を取得します。データはJSON形式になっています。
+
+```
+https://{host}/.well-known/oauth-authorization-server
+```
+
+`{host}`の部分は、ユーザーのサーバーのホストに置き換えます。通常ホストはユーザーが入力します。
+
+ここでは`authorization_endpoint`と`token_endpoint`を使います。
+
+:::tip
+
+次のステップで使われる`scope`の情報も`scopes_supported`で確認できます。
+
+:::
+
+## Step 4
+
+アプリケーション認証フォームをユーザーのブラウザで表示させます。認証フォームは、以下の形式のURLで開くことができます:
+
+```
+{authorization_endpoint}?client_id={client_id}&response_type=code&redirect_uri={redirect_uri}&scope={scope}&code_challenge={code_challenge}&code_challenge_method=S256&state={state}
+```
+
+ここで、
+
+- `{authorization_endpoint}`の部分は、前の情報取得で得たアドレスに置き換えます。
+- `{client_id}`の部分は、アプリの紹介ページのアドレスに置き換えます。
+- `{code_challenge}`の部分は、前に生成した`code_challenge`文字列に置き換えます
+- `code_challenge_method`の部分は常に`S256`にします。
+- `{redirect_uri}`の部分は、紹介ページで使っている配達先のアドレスに置き換えます。
+- `{scope}`の部分は、アプリケーションが要求する権限に置き換えます。要求する権限を` `で区切って列挙します。権限の一覧は[こちら](../permission.md)で確認できます。
+- `{state}`の部分は、前に生成した`state`文字列に置き換えます。
+
+:::tip{label='例'}
+
+```
+https://misskey.local/oauth/authorize?client_id=http%3A%2F%2Fexample.com&code_challenge=C6hwMO2bmIzg3nqppTE9b79fvuOjlrKmH2xNiZSMHzw&code_challenge_method=S256&response_type=code&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect&scope=write%3Anotes&state=87c11f05-86eb-4eb2-9057-f6a98fc5e9ab
+```
+
+:::
+
+## Step 5
+
+ユーザーがアプリケーションアクセスを許可したら、`redirect_uri`のアドレスに認証コードがURLパラメータの形式で転送されます。
+
+| 名前 | 説明 |
+| ------- | ----------------------- |
+| `code` | ユーザーの認証コード。 |
+| `state` | 認証リクエストに使われた`state`文字列。 |
+
+:::tip{label='例'}
+
+```
+https://example.com/redirect?code=...&state=87c11f05-86eb-4eb2-9057-f6a98fc5e9ab
+```
+
+:::
+
+`state`文字列がちゃんと一致しているのか確認して、次のステップに進みます。
+
+## Step 6
+
+転送された認証コードを使ってアクセストークンをPOSTでリクエストします。リクエスト先は`token_endpoint`になります。データ形式は`application/json`と`application/x-www-form-urlencoded`を使えます。各パラメータは以下のようになります。
+
+| 名前 | 説明 |
+| --------------- | ------------------------------ |
+| `grant_type` | 常に`authorization_code`にします。 |
+| `client_id` | 認証リクエストに使われた`client_id`文字列。 |
+| `redirect_uri` | 認証リクエストに使われた`redirect_uri`文字列。 |
+| `scope` | 認証リクエストに使われた`scope`文字列。 |
+| `code` | 取得した認証コード。 |
+| `code_verifier` | 前に生成した`code_verifier`文字列。 |
+
+:::tip{label='例'}
+
+```js
+const res = await fetch(endpoint, {
+ method: "POST",
+ body: JSON.stringify({
+ grant_type: "authorization_code",
+ client_id: "https://example.com",
+ redirect_uri: "https://example.com/redirect",
+ scope: "write:notes",
+ code: "...",
+ code_verifier: "hjjbCYDmDpSLjirkO-PrfWKsRhDdJr-PAEGRClRwzUKlmFIIIrZNmSvUIraeIa~WqbqQnfbJV-Hc_IfuQkesBYUpukUi~lInDfU_AZjoZqbU.ioQTRzaFfZFfGnT-OAA",
+ }),
+ headers: {
+ "Content-Type": "application/json"
+ }
+});
+```
+
+:::
+
+レスポンスはJSONオブジェクト形式で、そこから`access_token`を取得して使います。