---
title: "OAuth-এর মাধ্যমে সংযোগ করুন"
description: "API কী শেয়ার না করেই MCP ক্লায়েন্ট এবং ThunderPhone CLI অনুমোদন করুন।"
---

OAuth আপনার অনুমোদিত অনুমতিগুলোসহ একটি অ্যাপকে একটি ThunderPhone সংস্থার সঙ্গে সংযুক্ত করতে দেয়। ডিরেক্টরি ক্লায়েন্টদের ডিফল্টভাবে OAuth ব্যবহার করা উচিত। যেসব ক্লায়েন্টের ম্যানুয়ালি কনফিগার করা Bearer টোকেন প্রয়োজন, তাদের জন্য সংস্থার API কী উপলভ্য থাকে।

## সংযোগ অনুমোদন করুন

আপনার MCP ক্লায়েন্টে সংযোগ শুরু করুন। ThunderPhone-এ সাইন ইন করুন, অ্যাপের নাম ও অনুরোধ করা অনুমতিগুলো যাচাই করুন, একটি সংস্থা বেছে নিন এবং **অনুমোদন করুন** নির্বাচন করুন। আপনি সংযোগটি শুরু না করে থাকলে বা অ্যাপটিকে বিশ্বাস না করলে **প্রত্যাখ্যান করুন** নির্বাচন করুন। অ্যাপের নাম তাদের ডেভেলপাররা সরবরাহ করেন এবং এটি কোনো যাচাইকরণ ব্যাজ নয়।

রিড অনুমতি নামযুক্ত ডেটা প্রকাশ করে, যার মধ্যে `calls:read` অনুরোধ করা হলে রেকর্ডিং ও ট্রান্সক্রিপ্ট অন্তর্ভুক্ত থাকে। রাইট অনুমতি রিসোর্স পরিবর্তন বা মুছে দিতে পারে; কল, ক্যাম্পেইন, ফোন কেনাকাটা ও ডিপ্লয়মেন্টে খরচ হতে পারে বা প্রোডাকশন প্রভাবিত হতে পারে। আপনার সংস্থার ভূমিকা এখনও প্রযোজ্য থাকবে।

CLI সংযোগের জন্য, আপনার টার্মিনালে দেখানো যাচাইকরণ লিংক খুলুন, আট-অক্ষরের কোডটি মিলিয়ে নিন, আপনার সংস্থা নির্বাচন করুন এবং অনুমোদন করুন। শুধু লিংক খুললেই অ্যাক্সেস দেওয়া হয় না। কোড 15 মিনিট পরে মেয়াদ শেষ হয়।

## একটি অ্যাপ সংযোগ বিচ্ছিন্ন করুন

ড্যাশবোর্ডে **সংস্থা → API কী → অনুমোদিত অ্যাপ** খুলুন এবং **প্রত্যাহার করুন** বেছে নিন। এটি বর্তমান সংস্থার জন্য আপনার নির্বাচিত অনুমোদন, এর অ্যাক্সেস ও রিফ্রেশ টোকেনসহ, প্রত্যাহার করে। অ্যাপটিকে আবার অনুমোদন করতে চাইলে সেখান থেকে পুনরায় সংযোগ করুন।

## MCP ক্লায়েন্টের জন্য ডিসকভারি

সার্ভার URL `https://api.thunderphone.com/v1/mcp` ব্যবহার করুন। বৈধ প্রমাণীকরণ ছাড়া একটি অনুরোধ `401` পায়, যার সঙ্গে থাকে:

```http
WWW-Authenticate: Bearer resource_metadata="https://api.thunderphone.com/.well-known/oauth-protected-resource"
```

সেই ডকুমেন্টটি ফেচ করুন, তারপর `https://api.thunderphone.com/.well-known/oauth-authorization-server` থেকে অনুমোদন সার্ভারের মেটাডেটা ফেচ করুন। রিসোর্স মেটাডেটা `/.well-known/oauth-protected-resource/v1/mcp`-এও উপলভ্য। এন্ডপয়েন্ট তৈরি করার পরিবর্তে ফেরত পাওয়া এন্ডপয়েন্টগুলো ব্যবহার করুন। রিসোর্স আইডেন্টিফায়ার হলো `https://api.thunderphone.com/v1/mcp`।

সার্ভারটি **S256 PKCE**-সহ authorization code, রোটেটিং refresh token, পাবলিক dynamic client registration, revocation এবং device authorization grant সমর্থন করে। কোনো client secret বা implicit grant নেই। OpenID discovery-ও `/.well-known/openid-configuration`-এ উপলভ্য; এতে একই authorization-server ফিল্ডের পাশাপাশি `subject_types_supported: ["public"]` এবং userinfo এন্ডপয়েন্ট অন্তর্ভুক্ত থাকে। ID token এবং Client ID Metadata Document (CIMD) সমর্থিত নয়।

### একটি পাবলিক ক্লায়েন্ট নিবন্ধন করুন

`POST /v1/oauth/register`-এ JSON পাঠান:

```json
{
  "client_name": "My MCP client",
  "redirect_uris": ["http://127.0.0.1:8765/callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"]
}
```

ফেরত পাওয়া `client_id` সংরক্ষণ করুন। রিডাইরেক্টে অবশ্যই HTTPS ব্যবহার করতে হবে, অথবা `127.0.0.1` কিংবা `localhost`-এ HTTP ব্যবহার করতে হবে। পোর্ট ও পাথসহ সঠিক callback URI নিবন্ধন করুন। fragment এবং embedded credential প্রত্যাখ্যান করা হয়। ঐচ্ছিক `client_uri` ও `logo_uri`-তে অবশ্যই HTTPS ব্যবহার করতে হবে; নিবন্ধনের সময় ThunderPhone সেগুলো ফেচ করে না। নিবন্ধনে rate limit প্রযোজ্য। নিবন্ধিত ক্লায়েন্টের মেয়াদ শেষ হয় না এবং কোনো সংযোগ revoke করা হলেও তারা নিবন্ধিত থাকে। HTTPS callback-এর মধ্যে `https://chatgpt.com/connector/oauth/<id>` এবং `https://chatgpt.com/connector_platform_oauth_redirect` অন্তর্ভুক্ত। প্রতিটি সংযোগ নিজস্ব ক্লায়েন্ট নিবন্ধন করতে পারে।

### Authorization code

আবিষ্কৃত authorization endpoint-এ `client_id`, সঠিক নিবন্ধিত `redirect_uri`, `response_type=code`, একটি র্যান্ডম `state`, `scope`, `code_challenge`, `code_challenge_method=S256` এবং `resource=https://api.thunderphone.com/v1/mcp` দিয়ে খুলুন। একটি নতুন উচ্চ-এনট্রপি PKCE verifier-এর unpadded base64url SHA-256 digest হিসেবে challenge গণনা করুন। কোড এক্সচেঞ্জ করার আগে ফেরত পাওয়া `state` এবং `iss` পরীক্ষা করুন। প্রত্যাখ্যান ও protocol error-সহ প্রতিটি authorization response, আবিষ্কৃত `issuer`-এর সঙ্গে হুবহু মিলে যাওয়া `iss` দিয়ে issuer শনাক্ত করে। অবৈধ ক্লায়েন্ট বা callback-এর ত্রুটি সেই callback-এ রিডাইরেক্ট না করেই স্থানীয়ভাবে ফেরত দেওয়া হয়।

form encoding ব্যবহার করে `POST /v1/oauth/token`-এ এক্সচেঞ্জ করুন (JSON-ও গ্রহণ করা হয়):

```text
grant_type=authorization_code
client_id=<your client id>
code=<single-use authorization code>
redirect_uri=<exact registered redirect URI>
code_verifier=<original PKCE verifier>
resource=https://api.thunderphone.com/v1/mcp
```

ঐচ্ছিক `resource` প্যারামিটার authorization এবং token উভয় অনুরোধেই গ্রহণ করা হয় (refresh ও device exchange-সহ)। এটি বাদ দিলে, আবিষ্কৃত MCP রিসোর্স ডিফল্ট হিসেবে ব্যবহৃত হয়। উপস্থিত থাকলে, এটি অবশ্যই সেই রিসোর্সের সঙ্গে হুবহু মিলতে হবে; অন্য মান `invalid_target` ফেরত দেয়। Access token-এ সেই audience থাকে, এবং MCP অনুপস্থিত বা ভিন্ন audience-সহ token-কে `401` ও একটি discovery challenge দিয়ে প্রত্যাখ্যান করে।

Authorization request এবং code 10 মিনিট পর মেয়াদ শেষ হয়। প্রতিটি token response-এ `access_token`, `token_type` (`Bearer`), `expires_in` (ডিফল্টভাবে 3600 সেকেন্ড), `refresh_token`, `scope`, `organization_id` এবং `organization_name` থাকে। Access token শুধু `Authorization: Bearer` header-এর মাধ্যমে পাঠান। URL, লগ, source control বা চ্যাটে কখনও token রাখবেন না।

### রিফ্রেশ ও revoke

Token endpoint-এ `grant_type=refresh_token`, `client_id`, `refresh_token` এবং `resource` দিয়ে রিফ্রেশ করুন। নতুন refresh token অ্যাটমিকভাবে সংরক্ষণ করুন এবং পুরোনোটি ব্যবহার বন্ধ করুন। সফল রিফ্রেশ ছাড়া 30 দিন পর refresh token-এর মেয়াদ শেষ হয়। একটি ঐচ্ছিক `scope` অনুমোদিত permission সীমিত করতে পারে। `offline_access` সবসময় অন্তর্ভুক্ত থাকে এবং refresh token সবসময় ইস্যু করা হয়। `scope` ছাড়া প্রাথমিক অনুরোধ শুধুমাত্র `offline_access` প্রদান করে, তাই ক্লায়েন্টের প্রয়োজনীয় permission অনুরোধ করা উচিত।

কোড পুনর্ব্যবহার এবং রোটেট করা refresh token পুনর্ব্যবহার সম্পূর্ণ authorization revoke করে। একটি ক্লায়েন্টের মধ্যে refresh কার্যক্রম serialise করুন; সফলভাবে এক্সচেঞ্জ করা credential পুনরায় চালানো নিরাপদ retry কৌশল নয়।

সংযোগ বিচ্ছিন্ন করতে, `POST /v1/oauth/revoke`-এ `token` এবং `client_id` পাঠান। যেকোনো token revoke করলে, সেটি থেকে ইস্যু করা সব token-সহ তার authorization revoke হয়। একটি অজানা token তার অস্তিত্ব প্রকাশ না করেই সফলতা ফেরত দেয়। Dashboard session নিজেদের authorization `GET /v1/oauth/grants`-এ তালিকাভুক্ত করতে এবং `DELETE /v1/oauth/grants/<id>`-এ একটি revoke করতে পারে; এখানে `X-ThunderPhone-Org` organization নির্বাচন করে।

### Device authorization

Device authorization শুধু আগে থেকে নিবন্ধিত ক্লায়েন্টের জন্য সীমাবদ্ধ; dynamicভাবে নিবন্ধিত ক্লায়েন্ট `unauthorized_client` পায়। আগে থেকে নিবন্ধিত পাবলিক ক্লায়েন্ট `thunderphone-cli` device authorization এবং refresh সমর্থন করে। `POST /v1/oauth/device/code`-এ `client_id=thunderphone-cli` এবং `scope` পাঠান। ব্যবহারকারীকে `user_code` এবং `verification_uri` দেখান, অথবা `verification_uri_complete` খুলুন।

Token endpoint-এ `grant_type=urn:ietf:params:oauth:grant-type:device_code`, `client_id` এবং `device_code` দিয়ে poll করুন এবং ফেরত পাওয়া `interval` (5 সেকেন্ড) অন্তত অপেক্ষা করুন। `authorization_pending`-এ চালিয়ে যান। `slow_down`-এ, পরবর্তী প্রতিটি অনুরোধের জন্য response-এ ফেরত দেওয়া নতুন `interval` ব্যবহার করুন (5 সেকেন্ড বৃদ্ধি করা)। `access_denied`, `expired_token` বা অন্য কোনো ত্রুটিতে থামুন। কখনও device code স্বয়ংক্রিয়ভাবে অনুমোদন করবেন না।

আগে থেকে নিবন্ধিত `thunderphone-mcp` ক্লায়েন্ট যেকোনো পোর্টে `http://127.0.0.1/callback` এবং `http://localhost/callback` গ্রহণ করে। Scheme, host, path এবং query অবশ্যই মিলতে হবে; token exchange-এ authorization থেকে পাওয়া সঠিক redirect URI (পোর্টসহ) ব্যবহার করতে হবে। Dynamicভাবে নিবন্ধিত ক্লায়েন্টের জন্য পোর্টসহ সঠিক redirect-URI মিল প্রয়োজন। অন্য পাথ প্রয়োজন হলে আলাদা callback dynamicভাবে নিবন্ধন করুন।

### অ্যাকাউন্ট পরিচয় ও workspace domain পরীক্ষা

আপনার ক্লায়েন্টের প্রয়োজনীয় operation scope-এর পাশাপাশি `openid email` উভয়ই অনুরোধ করুন। Bearer header-এ access token দিয়ে আবিষ্কৃত `userinfo_endpoint` (`GET /v1/oauth/userinfo`) কল করুন। একটি সফল response-এ থাকে:

```json
{
  "sub": "123",
  "email": "person@example.com",
  "email_verified": true,
  "name": "Example User",
  "org_id": 456
}
```

`sub` হলো স্থিতিশীল ব্যবহারকারী আইডেন্টিফায়ার; `org_id` হলো সম্মতির সময় নির্বাচিত organization। এন্ডপয়েন্টটির জন্য উভয় identity scope প্রয়োজন এবং যেকোনো একটি অনুপস্থিত থাকলে `403` ফেরত দেয়। অ্যাকাউন্টে কোনো যাচাইকৃত email profile না থাকলে, যাচাই না হওয়া email বিশ্বস্ত বলে নিশ্চিত করার পরিবর্তে এটি `error=access_denied`-সহ `403` ফেরত দেয়। অবৈধ, মেয়াদোত্তীর্ণ, revoke করা বা ভুল-audience token `401` ফেরত দেয়। মানব session token এবং organization API key userinfo কল করতে পারে না। কোনো ID token ইস্যু করা হয় না।

## উপলভ্য অনুমতিসমূহ

| বিভাগ | স্কোপ |
| --- | --- |
| এজেন্ট এবং এজেন্ট ইমপোর্ট | `agents:read`, `agents:write` |
| কল | `calls:read`, `calls:write` |
| ফোন নম্বর এবং VoIP | `numbers:read`, `numbers:write` |
| জ্ঞান | `knowledge:read`, `knowledge:write` |
| ক্যাম্পেইন | `campaigns:read`, `campaigns:write` |
| ইন্টিগ্রেশন, webhook এন্ডপয়েন্ট, MCP সার্ভার | `integrations:read`, `integrations:write` |
| ভয়েস | `voices:read` |
| পরীক্ষার দৃশ্যপট, পরীক্ষার রান, যাচাইকরণ | `testing:read`, `testing:write` |
| বিলিং | `billing:read` |
| অ্যাকাউন্ট পরিচয় এবং যাচাইকৃত ইমেল | `openid`, `email` (userinfo-এর জন্য উভয়ই প্রয়োজন) |
| স্থায়ী সংযোগ | `offline_access` (সবসময় অন্তর্ভুক্ত) |

GET, HEAD এবং OPTIONS রিড স্কোপ ব্যবহার করে; অন্যান্য মেথড রাইট স্কোপ ব্যবহার করে। OAuth-এর মাধ্যমে ভয়েস এবং বিলিং মিউটেশন উপলভ্য নয়; `POST /v1/voices/preview` `voices:read` ব্যবহার করে, কারণ এটি কনফিগারেশন পরিবর্তন না করে একটি ভয়েসের প্রিভিউ করে। MCP টুল তাদের অন্তর্নিহিত REST অপারেশনের স্কোপ প্রয়োগ করে। অনুমোদনদানকারী ব্যবহারকারী উভয় সংস্থার সদস্য হলেও ক্রস-অর্গানাইজেশন ট্রান্সফার প্রত্যাখ্যান করা হয়। API কী ব্যবস্থাপনা এবং মানব অ্যাকাউন্ট সেটিংসসহ অন্যান্য API বিভাগ OAuth-এর মাধ্যমে উপলভ্য নয়। কোনো REST অপারেশনে অনুপস্থিত অনুমতি `WWW-Authenticate: Bearer error="insufficient_scope", scope="..."` সহ `403` ফেরত দেয়। অবৈধ বা মেয়াদোত্তীর্ণ অ্যাক্সেস টোকেন `401` ফেরত দেয়।


### MCP টুল প্রমাণীকরণ সংকেত

`tools/list`-এর প্রতিটি টুলে সেই টুলের REST অপারেশনের স্কোপসহ `securitySchemes: [{"type": "oauth2", "scopes": ["agents:read"]}]` অন্তর্ভুক্ত থাকে। পাবলিক ডকুমেন্টেশন টুলগুলো খালি স্কোপ তালিকা ব্যবহার করে এবং তবুও একটি প্রমাণীকৃত সংযোগ প্রয়োজন।

কোনো টুলের স্কোপ অনুপস্থিত থাকা একটি বৈধ টোকেন HTTP `200` পায়, যেখানে JSON-RPC `result`-এ `isError: true`, `content`-এ ব্যাখ্যামূলক লেখা এবং `_meta["mcp/www_authenticate"]` থাকে। পরেরটি `resource_metadata`, `error="insufficient_scope"`, `error_description` এবং প্রয়োজনীয় `scope`-সহ একটি Bearer চ্যালেঞ্জ ধারণকারী অ্যারে। টুলটি কার্যকর হয় না। সম্প্রসারিত সম্মতি অনুরোধ করতে এই চ্যালেঞ্জ ব্যবহার করুন। অনুপস্থিত বা অবৈধ প্রমাণীকরণ `WWW-Authenticate` সহ HTTP `401` ফেরত দিতে থাকে; REST স্কোপ ব্যর্থতা HTTP `403` ফেরত দিতে থাকে।

## শংসাপত্র সংরক্ষণ

API স্টেজিং এবং প্রোডাকশনে প্রতি ঘণ্টায় `python manage.py oauth_cleanup` চালায়। এটি মেয়াদোত্তীর্ণ অনুমোদন অনুরোধ এবং ডিভাইস কোড সরিয়ে দেয়। মেয়াদোত্তীর্ণ অ্যাক্সেস টোকেন, অনুমোদন কোড এবং রিফ্রেশ-টোকেন হ্যাশ কেবল তাদের গ্র্যান্ট প্রত্যাহার হওয়ার পরে বা সম্পূর্ণ টোকেন পরিবার নিষ্ক্রিয় হওয়ার পরে অপসারণ করা হয়। ব্যবহৃত হ্যাশগুলো সংরক্ষিত থাকে যতক্ষণ টোকেন পরিবারে ব্যবহারযোগ্য রিফ্রেশ টোকেন, অনুমোদন কোড, অনুমোদিত ডিভাইস কোড বা অ্যাক্সেস টোকেন থাকে, যাতে ক্লিনআপ পুনরায় ব্যবহারের শনাক্তকরণ নিষ্ক্রিয় করতে না পারে।
