Skip to content

Commit 56bb005

Browse files
committed
feat: enhance OAuth2Adapter by adding OAuth2UserInfo interface and updating getTokenFromCode return type
1 parent 90feac5 commit 56bb005

5 files changed

Lines changed: 259 additions & 101 deletions

File tree

adminforth/documentation/docs/tutorial/05-Adapters/09-chat-surface-adapters.md

Lines changed: 52 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ sidebar_position: 8
77

88
# Telegram Chat Surface Adapter
99

10-
Chat surface adapters connect external chat products to the [Agent plugin](/docs/tutorial/Plugins/agent/).
10+
Chat surface adapters connect external chat products to the [Agent plugin](/docs/tutorial/Plugins/agent/). They only receive and send chat messages. User linking is handled through OAuth connected accounts.
11+
12+
For Telegram you need both adapters:
1113

1214
```bash
1315
pnpm i @adminforth/chat-surface-adapter-telegram
16+
pnpm i @adminforth/telegram-oauth-adapter
1417
```
1518

1619
Create a Telegram bot with BotFather and add the token to `.env`:
@@ -23,57 +26,62 @@ TELEGRAM_WEBHOOK_SECRET=your_random_secret
2326

2427
The webhook secret confirms that the request came through Telegram.
2528

26-
## Admin user field `externalUserId`
29+
## External identity `externalUserId`
2730

28-
External chat accounts are linked by the Agent plugin, not by the Telegram adapter directly. The plugin stores linked external user ids in a JSON field on the AdminForth auth user resource.
31+
External chat accounts are resolved through OAuth connected accounts. The Telegram OAuth adapter writes the Telegram user id into `externalUserId` on the external identities resource. The Agent plugin then uses that field to map incoming Telegram messages to AdminForth users.
2932

30-
By default this field is named `externalUserId`. Add it to your `adminuser` resource:
33+
Add the field to your external identities resource:
3134

3235
```ts
3336
{
3437
name: 'externalUserId',
35-
type: AdminForthDataTypes.JSON,
38+
type: AdminForthDataTypes.STRING,
3639
},
3740
```
3841

3942
Also add the matching column to your database schema and run a migration. For example, with Prisma and PostgreSQL:
4043

4144
```prisma title="schema.prisma"
42-
model adminuser {
43-
// existing fields
44-
externalUserId Json?
45-
}
46-
```
47-
48-
For Prisma SQLite, store the same field as text:
49-
50-
```prisma title="schema.prisma"
51-
model adminuser {
45+
model AdminUserExternalIdentity {
5246
// existing fields
5347
externalUserId String?
5448
}
5549
```
5650

57-
AdminForth should still define this resource column as `AdminForthDataTypes.JSON`; the SQLite connector serializes it into the text column and parses it back.
58-
5951
Then create and apply the migration using your app's migration scripts:
6052

6153
```bash
62-
pnpm makemigration --name add-adminuser-external-user-id
54+
pnpm makemigration --name add-external-identity-external-user-id
6355
pnpm migrate:local
6456
```
6557

66-
When a Telegram account is linked, the field stores data like this:
58+
Configure the OAuth plugin with Telegram OAuth:
6759

68-
```json
69-
{
70-
"telegram": "123456789"
71-
}
72-
```
60+
```ts title="./resources/adminuser.ts"
61+
import OAuthPlugin from '@adminforth/oauth';
62+
import TelegramOauthAdapter from '@adminforth/telegram-oauth-adapter';
7363

74-
If your field is named differently, configure `chatExternalIdsField` on the Agent plugin.
64+
new OAuthPlugin({
65+
emailField: 'email',
66+
externalIdentityResource: {
67+
resourceId: 'admin_user_external_identities',
68+
phoneField: 'phone',
69+
fullNameField: 'fullName',
70+
avatarUrlField: 'avatarUrl',
71+
metaField: 'meta',
72+
},
73+
adapters: [
74+
new TelegramOauthAdapter({
75+
clientID: process.env.TELEGRAM_CLIENT_ID as string,
76+
clientSecret: process.env.TELEGRAM_CLIENT_SECRET as string,
77+
redirectUri: process.env.TELEGRAM_OAUTH_REDIRECT_URI as string,
78+
scopes: ['openid', 'profile', 'phone'],
79+
}),
80+
],
81+
});
82+
```
7583

76-
Register the adapter in the Agent plugin:
84+
Then register the Telegram chat surface adapter in the Agent plugin:
7785

7886
```ts
7987
import AdminForthAgent from '@adminforth/agent';
@@ -103,28 +111,35 @@ new AdminForthAgent({
103111
}),
104112
//diff-add
105113
],
106-
// optional, defaults to 'externalUserId'
107114
//diff-add
108-
chatExternalIdsField: 'externalUserId',
115+
chatExternalIdentityResource: {
116+
//diff-add
117+
resourceId: 'admin_user_external_identities',
118+
//diff-add
119+
surfaces: {
120+
//diff-add
121+
telegram: {
122+
//diff-add
123+
provider: 'AdminForthAdapterTelegramOauth2',
124+
//diff-add
125+
},
126+
//diff-add
127+
},
128+
//diff-add
129+
},
109130
});
110131
```
111132

112-
When `botUsername` is configured, the Agent plugin adds **Chat Surfaces** to the user menu settings pages. A logged-in AdminForth user can open that page and click **Connect**. The Telegram adapter returns a URL like:
113-
114-
```txt
115-
https://t.me/<botUsername>?start=<link-token>
116-
```
117-
118-
After the user starts the bot with that token, AdminForth stores the Telegram user id in `externalUserId.telegram`. The same page also supports reconnecting and disconnecting the Telegram account.
133+
External chat users are resolved through OAuth connected accounts. Configure OAuth `externalIdentityResource` and Agent `chatExternalIdentityResource`, then let users connect Telegram from **Connected Accounts**.
119134

120-
You can also prefill the JSON field manually if you do not want to use the connect page.
135+
The `provider` value must match the Telegram OAuth adapter class name. Users must connect Telegram in **Settings -> Connected Accounts** before the Telegram bot can identify them.
121136

122137
## Adapter options
123138

124139
All options for `new TelegramChatSurfaceAdapter(options)`:
125140

126141
- `botToken` (string, required) — Telegram bot token from BotFather.
127-
- `botUsername` (string, optional) — bot username used to build the account-link URL for the **Chat Surfaces** settings page.
142+
- `botUsername` (string, optional) — bot username. OAuth connected accounts are used for user linking.
128143
- `webhookSecret` (string, optional) — secret token configured in Telegram `setWebhook`.
129144
- `streamingMode` (`draft` | `typing` | `off`, optional) — streaming behavior for Telegram responses.
130145
- Default: `draft`.

adminforth/documentation/docs/tutorial/08-Plugins/01-agent.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,25 +287,41 @@ The plugin adds a chat surface to the admin UI, keeps session history per admin
287287
## Chat surfaces (Telegram, etc.)
288288

289289
By default, the Agent plugin exposes a chat surface inside the AdminForth admin UI.
290-
If you want to talk to the same agent from external chat products (Telegram, etc.), connect a **chat surface adapter**.
290+
If you want to talk to the same agent from external chat products (Telegram, Slack, Teams, etc.), configure both:
291+
292+
- a **chat surface adapter** that receives messages from the external chat product
293+
- an **OAuth adapter** for the same provider so users can connect that external account in **Connected Accounts**
294+
295+
For example, Telegram Agent access needs both `@adminforth/chat-surface-adapter-telegram` and `@adminforth/telegram-oauth-adapter`.
291296

292297
Register adapters through `chatSurfaceAdapters`:
293298

294299
```ts
295300
import AdminForthAgent from '@adminforth/agent';
296-
import SomeChatSurfaceAdapter from '@adminforth/some-chat-surface-adapter';
301+
import TelegramChatSurfaceAdapter from '@adminforth/chat-surface-adapter-telegram';
297302

298303
new AdminForthAgent({
299304
// ...modes, sessionResource, turnResource, etc.
300305
chatSurfaceAdapters: [
301-
new SomeChatSurfaceAdapter({
302-
// adapter-specific options
306+
new TelegramChatSurfaceAdapter({
307+
botToken: process.env.TELEGRAM_BOT_TOKEN as string,
308+
webhookSecret: process.env.TELEGRAM_WEBHOOK_SECRET,
303309
}),
304310
],
311+
chatExternalIdentityResource: {
312+
resourceId: 'admin_user_external_identities',
313+
surfaces: {
314+
telegram: {
315+
provider: 'AdminForthAdapterTelegramOauth2',
316+
},
317+
},
318+
},
305319
});
306320
```
307321

308-
When an adapter supports account linking, the Agent plugin adds a user menu settings page named **Chat Surfaces** where logged-in users can connect, reconnect, and disconnect external accounts.
322+
External chat users are resolved through the OAuth external identities resource. The `provider` value in `chatExternalIdentityResource.surfaces` must match the OAuth adapter class that writes connected accounts, for example `AdminForthAdapterTelegramOauth2`.
323+
324+
Users connect their Telegram account from **Settings -> Connected Accounts**. After that, messages from the Telegram bot can be matched to the AdminForth user through the external identity `externalUserId`.
309325

310326
For Telegram setup, including required user fields, webhook URL, environment variables, and adapter options, see:
311327

0 commit comments

Comments
 (0)