feat: sync HTTP callback OIDC setup
This commit is contained in:
parent
bf72c246b6
commit
f53579416e
26 changed files with 557 additions and 133 deletions
|
|
@ -51,7 +51,7 @@ This document describes every setting loaded by `internal/config`. Defaults and
|
|||
| Setting | Type / code default | Description and constraints |
|
||||
|---|---|---|
|
||||
| `TELESRV_DEBUG_ADDR` | nullable address / `127.0.0.1:6060` | pprof/debug listener. Empty disables it. Keep loopback-only; use an SSH tunnel for production profiling. |
|
||||
| `TELESRV_BOT_API_ADDR` | nullable address / empty | Minimal HTTP Bot API listener. Empty disables it. It shares MTProto app/store facts. |
|
||||
| `TELESRV_BOT_API_ADDR` | nullable address / empty | Minimal HTTP Bot API listener. Empty disables it. It shares MTProto app/store facts. `setWebhook` accepts any valid `http://` or `https://` host/IP and port in `1..65535`. |
|
||||
| `TELESRV_ADMIN_API_ADDR` | nullable address / empty | In-process Admin write API listener. Empty disables it; production should bind loopback. |
|
||||
| `TELESRV_ADMIN_API_TOKEN` | secret string / empty | Admin API bearer token. Required when the Admin API is enabled and must match the Admin UI token configuration. |
|
||||
| `TELESRV_ADMIN_UI_ADDR` | address / `127.0.0.1:2600` | Standalone `cmd/telesrv-admin` listen address. |
|
||||
|
|
@ -62,7 +62,189 @@ This document describes every setting loaded by `internal/config`. Defaults and
|
|||
| `TELESRV_PUBLIC_APP_SCHEME` | URL scheme / `telesrv` | Automatic app-open scheme on landing pages. Must match patched client registration. `tg`, `http`, and `https` are rejected. |
|
||||
| `TELESRV_PUBLIC_WEB_BASE_URL` | HTTP(S) URL / `https://web.telesrv.net` | Web-client root used by public username pages. Same URL validation as `TELESRV_PUBLIC_BASE_URL`. |
|
||||
| `TELESRV_PUBLIC_APP_NAME` | string / `telesrv` | Public landing-page product name; trimmed, non-empty, no control characters, maximum 64 Unicode characters. |
|
||||
| `TELESRV_PUBLIC_LINK_WEB_ADDR` | nullable address / empty | Read-only username/avatar/sticker/emoji/chatlist landing-page listener. Empty disables it. Production should bind loopback behind exact nginx routes. `.env.example` enables `127.0.0.1:2401` for development. |
|
||||
| `TELESRV_PUBLIC_LINK_WEB_ADDR` | nullable address / empty | Read-only username/avatar/sticker/emoji/chatlist/collectible-gift landing-page listener. Empty disables it. Production should bind loopback behind exact nginx routes. `.env.example` enables `127.0.0.1:2401` for development. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_ENABLE` | bool / `false` | Mount the self-hosted Telegram Login/OIDC provider on `TELESRV_PUBLIC_LINK_WEB_ADDR`. Enabling it requires that listener and all key files below. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_ISSUER` | absolute origin URL / `TELESRV_PUBLIC_BASE_URL` | Exact public issuer used in discovery and tokens. HTTPS is required by default; paths, credentials, query, and fragment are rejected. The next setting permits any HTTP host/IP. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP` | bool / `false` | When enabled, permits any valid HTTP issuer, BotFather Web origin, redirect URI, and native HTTP callback, without loopback, subnet, or port restrictions. When disabled, those Web URLs still require HTTPS. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_SIGNING_KEYS_FILE` | path / `data/telegram-login/signing-keys.json` | JOSE private-key ring generated by `cmd/telegramloginkeygen`; active plus retiring public keys are published through JWKS. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_CODE_KEYS_FILE` | path / `data/telegram-login/code-keys.json` | AES-256-GCM envelope-key ring for recoverable, one-time authorization codes. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_SECRET_PEPPER_FILE` | path / `data/telegram-login/client-secret-pepper` | Deployment pepper for HMAC-SHA-256 client-secret hashes. The file must contain a base64 encoding of exactly 32 random bytes. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_REQUEST_TTL` | duration / `5m` | Pending authorization lifetime; bounded to `1m..15m`. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_CODE_TTL` | duration / `2m` | One-time code lifetime; bounded to `30s..10m`. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_ID_TOKEN_TTL` | duration / `1h` | Signed ID-token lifetime; bounded to `1m..24h`. Retiring signing keys must cover this window. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_TRUSTED_PROXY_CIDRS` | comma-separated CIDRs / empty | Only requests whose direct peer is in this list may supply `Forwarded`/`X-Forwarded-*` client metadata. The documented nginx deployment uses `127.0.0.1/32,::1/128`. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_RETENTION` | duration / `168h` | Retention after terminal request/code/revocation state; bounded to `1h..90d`. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_SWEEP_INTERVAL` | duration / `5m` | Retention worker interval; bounded to `10s..1h`. |
|
||||
| `TELESRV_TELEGRAM_LOGIN_SWEEP_BATCH` | int / `500` | Maximum rows per retention pass; bounded to `1..1000`. |
|
||||
|
||||
### 3.1 Complete Telegram Login / OIDC setup
|
||||
|
||||
#### 1. Generate `data/telegram-login` once
|
||||
|
||||
Run this from the `telesrv` repository root:
|
||||
|
||||
```powershell
|
||||
go run ./cmd/telegramloginkeygen -mode init -dir data/telegram-login
|
||||
Get-ChildItem .\data\telegram-login
|
||||
```
|
||||
|
||||
The same command works on Linux; restrict the generated directory afterward:
|
||||
|
||||
```bash
|
||||
go run ./cmd/telegramloginkeygen -mode init -dir data/telegram-login
|
||||
chmod 0700 data/telegram-login
|
||||
chmod 0600 data/telegram-login/*
|
||||
```
|
||||
|
||||
Initialization creates the following private files. It never prints key material and refuses to
|
||||
overwrite an existing `signing-keys.json`, `code-keys.json`, or `client-secret-pepper`:
|
||||
|
||||
- `signing-keys.json` plus three `signing-*.pem` files: the manifest and private keys for RS256,
|
||||
ES256, and EdDSA ID-token signatures;
|
||||
- `code-keys.json`: the AES-256-GCM envelope-key ring for one-time authorization codes;
|
||||
- `client-secret-pepper`: a 32-byte deployment pepper used to store and verify OIDC Client Secret
|
||||
digests.
|
||||
|
||||
The repository ignores `data/*` by default. Never put this directory in Git, release archives,
|
||||
logs, or ordinary backups. All instances must mount the same protected files and restart together
|
||||
after rotation. Losing the pepper invalidates existing Client Secret verification. Losing a signing
|
||||
key that is still in its publication window invalidates otherwise-live ID tokens against JWKS.
|
||||
|
||||
#### 2. Configure and start the Provider
|
||||
|
||||
This example exposes OIDC directly at `http://192.0.2.25:2401`; replace it with the server address
|
||||
that clients can actually reach. Bind `0.0.0.0:2401` for direct LAN/public access, or keep
|
||||
`127.0.0.1:2401` when an on-host reverse proxy is the only caller:
|
||||
|
||||
```env
|
||||
TELESRV_PUBLIC_BASE_URL=http://192.0.2.25:2401
|
||||
TELESRV_PUBLIC_LINK_WEB_ADDR=0.0.0.0:2401
|
||||
TELESRV_PUBLIC_APP_SCHEME=telesrv
|
||||
|
||||
TELESRV_TELEGRAM_LOGIN_ENABLE=true
|
||||
TELESRV_TELEGRAM_LOGIN_ISSUER=http://192.0.2.25:2401
|
||||
TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP=true
|
||||
TELESRV_TELEGRAM_LOGIN_SIGNING_KEYS_FILE=data/telegram-login/signing-keys.json
|
||||
TELESRV_TELEGRAM_LOGIN_CODE_KEYS_FILE=data/telegram-login/code-keys.json
|
||||
TELESRV_TELEGRAM_LOGIN_SECRET_PEPPER_FILE=data/telegram-login/client-secret-pepper
|
||||
```
|
||||
|
||||
For HTTPS, set the issuer and public base to the exact HTTPS origin and leave
|
||||
`TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP=false`. The issuer becomes the token `iss` and the root of all
|
||||
discovery endpoints, so its scheme, host, and port must exactly match the address used by relying
|
||||
parties. Start or restart `telesrv`, then verify the public endpoints:
|
||||
|
||||
```powershell
|
||||
curl.exe http://192.0.2.25:2401/.well-known/openid-configuration
|
||||
curl.exe http://192.0.2.25:2401/.well-known/jwks.json
|
||||
curl.exe -I http://192.0.2.25:2401/js/telegram-login.js
|
||||
```
|
||||
|
||||
The discovery `issuer` must equal the configured value, and its `authorization_endpoint`,
|
||||
`token_endpoint`, and `jwks_uri` must be reachable by the relying party. A reverse proxy must pass
|
||||
through `/.well-known/openid-configuration`, `/.well-known/jwks.json`, `/auth`, `/auth/status`,
|
||||
`/token`, `/crossapp`, `/inapp`, `/telegram-login.js`, and `/js/telegram-login.js` unchanged.
|
||||
|
||||
#### 3. Create an OIDC Client with the local `@BotFather`
|
||||
|
||||
Create a bot with `/newbot` or select an existing bot. In the local `@BotFather`, run `/setlogin`
|
||||
and choose that bot. Initial setup returns:
|
||||
|
||||
- `Client ID`: the bot user ID as a decimal string;
|
||||
- `Client Secret`: shown once, separate from the Bot API token, and meant to be saved immediately
|
||||
in a secret manager.
|
||||
|
||||
Send each configuration command separately. This example runs the relying party at
|
||||
`http://192.0.2.30:3000`:
|
||||
|
||||
```text
|
||||
add origin http://192.0.2.30:3000
|
||||
add redirect http://192.0.2.30:3000/oauth/callback
|
||||
algorithm RS256
|
||||
enable
|
||||
```
|
||||
|
||||
An `origin` is an exact Web origin without a path, query, or fragment; it authorizes the JS SDK,
|
||||
popup CORS, and legacy `login_url`. A `redirect` is the exact full URI that receives an
|
||||
Authorization Code. Wildcards and prefix matching are not supported. Use `/logininfo` to inspect
|
||||
status and registrations; use `/setlogin` to add/remove URLs, change the algorithm, or disable the
|
||||
client; use `/resetloginsecret` to rotate the Client Secret. Available algorithms are RS256,
|
||||
ES256, EdDSA, and ES256K only when its build/key ring is present. EdDSA and ES256K accept only the
|
||||
`openid` scope.
|
||||
|
||||
#### 4. Integrate a relying party with standard OIDC
|
||||
|
||||
Start by loading:
|
||||
|
||||
```text
|
||||
http://192.0.2.25:2401/.well-known/openid-configuration
|
||||
```
|
||||
|
||||
The standard flow is Authorization Code with PKCE S256:
|
||||
|
||||
1. Generate random `state`, `nonce`, and PKCE `code_verifier`; derive the S256 `code_challenge`.
|
||||
2. Open the discovery `authorization_endpoint` with `client_id`, the exact `redirect_uri`,
|
||||
`response_type=code`, a `scope` containing `openid`, `state`, `nonce`, `code_challenge`, and
|
||||
`code_challenge_method=S256`.
|
||||
3. After the user approves in TDesktop/Android, verify `state` at the relying-party callback and
|
||||
read the one-time code.
|
||||
4. Server-side, POST `grant_type=authorization_code`, the code, the same `redirect_uri`, and
|
||||
`code_verifier` to the discovery `token_endpoint`. Confidential clients authenticate with HTTP
|
||||
Basic or `client_secret_post`.
|
||||
5. Verify the ID-token signature with the discovery `jwks_uri`, then strictly validate `iss`,
|
||||
`aud`, `exp`, `nonce`, and a non-empty `sub`. Decoding without signature verification is not
|
||||
sufficient.
|
||||
|
||||
Supported scopes are `openid`, `profile`, `phone`, and `telegram:bot_access`. The provider does not
|
||||
currently expose UserInfo, refresh tokens, or an introspection endpoint. Browser applications may
|
||||
load `<issuer>/js/telegram-login.js` for the local JS SDK. A Client Secret must remain server-side.
|
||||
|
||||
#### 5. Verify the complete path with the Bedolaga demo
|
||||
|
||||
Install the demo dependencies:
|
||||
|
||||
```powershell
|
||||
python -m venv "$env:TEMP\telesrv-bedolaga-demo-venv"
|
||||
& "$env:TEMP\telesrv-bedolaga-demo-venv\Scripts\python.exe" -m pip install `
|
||||
-r .\cmd\bots\bedolagaformat\requirements.txt
|
||||
```
|
||||
|
||||
Put the Client ID/Secret from step 3 and the same bot's Bot API token only in process environment:
|
||||
|
||||
```powershell
|
||||
$env:TELESRV_BOT_TOKEN = "<bot_id>:<bot_api_secret>"
|
||||
$env:TELESRV_BOT_API_SERVER = "http://192.0.2.25:8081"
|
||||
$env:TELESRV_BOT_LOGIN_DEMO = "1"
|
||||
$env:TELESRV_BOT_LOGIN_ISSUER = "http://192.0.2.25:2401"
|
||||
$env:TELESRV_BOT_LOGIN_CLIENT_ID = "<Client ID returned by BotFather>"
|
||||
$env:TELESRV_BOT_LOGIN_CLIENT_SECRET = "<one-time OIDC Client Secret>"
|
||||
$env:TELESRV_BOT_LOGIN_PUBLIC_URL = "http://192.0.2.30:3000"
|
||||
$env:TELESRV_BOT_LOGIN_LISTEN = "0.0.0.0:3000"
|
||||
|
||||
& "$env:TEMP\telesrv-bedolaga-demo-venv\Scripts\python.exe" `
|
||||
.\cmd\bots\bedolagaformat\demo.py --drop-pending --login-demo
|
||||
```
|
||||
|
||||
The BotFather origin must equal `TELESRV_BOT_LOGIN_PUBLIC_URL`, and the redirect must equal
|
||||
`<TELESRV_BOT_LOGIN_PUBLIC_URL>/oauth/callback`. Send `/logindemo` to the bot. The first button
|
||||
tests Bot API `login_url` plus the HMAC callback; the second page tests the local JS SDK popup and
|
||||
Authorization Code + PKCE/JWKS. Omitting the Client Secret leaves JS popup verification available
|
||||
but explicitly disables the server-side code flow.
|
||||
|
||||
#### 6. Rotate keys
|
||||
|
||||
When rotating a signing key, retain the old public key for at least the configured ID-token TTL
|
||||
plus ten minutes. Restart all instances together after the operation:
|
||||
|
||||
```powershell
|
||||
go run ./cmd/telegramloginkeygen -mode rotate-signing -algorithm RS256 `
|
||||
-id-token-ttl 1h -publish-for 2h -dir data/telegram-login
|
||||
go run ./cmd/telegramloginkeygen -mode rotate-code -dir data/telegram-login
|
||||
```
|
||||
|
||||
Run `rotate-signing` separately for RS256, ES256, or EdDSA. `rotate-code` retains old code keys and
|
||||
adds a new active key. Do not edit manifests or PEM files manually, and never generate divergent
|
||||
key rings independently on different instances.
|
||||
|
||||
## 4. PostgreSQL, Redis, files, and seed data
|
||||
|
||||
|
|
@ -95,7 +277,7 @@ The language-pack file manifest is authoritative. To add a language, place `data
|
|||
| `TELESRV_AUTH_CODE_RATE_WINDOW` | duration / `10m` | Shared window for phone and auth-key issuance limits. |
|
||||
| `TELESRV_PHONE_CODE_DELIVERY_PROVIDER` | enum / `development` | `development` uses fixed codes; `webhook` generates random SMS codes for login, registration, and phone changes. Both modes first commit the same code to the durable 777000 dialog for existing accounts; Webhook is additive. |
|
||||
| `TELESRV_EMAIL_CODE_DELIVERY_PROVIDER` | enum / `smtp` | Delivery implementation for login-email and email setup/change codes: `smtp` or `webhook`. Existing-account login-email codes are first mirrored to 777000; setup/change remains provider-only. |
|
||||
| `TELESRV_OTP_WEBHOOK_URL` | absolute URL / empty | Required when any provider selects `webhook`; see [otp-delivery.md](otp-delivery.md) for the fixed v1 contract. Must use `http`/`https` and contain no userinfo. |
|
||||
| `TELESRV_OTP_WEBHOOK_URL` | absolute URL / empty | Required when any provider selects `webhook`; see [otp-delivery.md](otp-delivery.md) for the fixed v1 contract. Any valid `http://` or `https://` host/IP and port is accepted; userinfo is rejected. |
|
||||
| `TELESRV_OTP_WEBHOOK_SECRET` | secret string / empty | Optional HMAC-SHA256 signing secret; enables `X-Telesrv-Signature` when non-empty. |
|
||||
| `TELESRV_OTP_WEBHOOK_TIMEOUT` | duration / `5s` | Webhook HTTP timeout; must be positive when Webhook delivery is enabled. |
|
||||
| `TELESRV_LOGIN_EMAIL_ENABLE` | bool / `false` | Enables login-email verification. SMTP settings are required only when the email provider is `smtp`. |
|
||||
|
|
@ -207,6 +389,19 @@ The following fallback keys are accepted from the **process environment only**.
|
|||
| `TELESRV_STARS_STARTING_GRANT` | int64 / `1000` | Idempotent lazy starting Stars balance for all accounts; `0` disables automatic grant. |
|
||||
| `TELESRV_PREMIUM_SWEEP_INTERVAL` | duration / `1m` | Expired-premium cleanup/push interval. Read paths derive expiry independently. |
|
||||
| `TELESRV_PREMIUM_SWEEP_BATCH` | int / `500` | Maximum expired premium rows processed per sweep. |
|
||||
| `TELESRV_STARGIFT_SWEEP_INTERVAL` | duration / `15s` | Local Star Gift offer/auction lifecycle sweep interval; no blockchain connection is made. |
|
||||
| `TELESRV_STARGIFT_SWEEP_BATCH` | int / `1000` | Maximum offer/auction/outbox work claimed per lifecycle sweep. |
|
||||
| `TELESRV_STARGIFT_TON_STARTING_GRANT` | int64 / `10000000000` | Nanoton granted idempotently on a user's first access to the internal telesrv TON ledger; `0` disables it. This is not an on-chain asset. |
|
||||
| `TELESRV_STARGIFT_TRANSFER_STARS` | int64 / `25` | Stars charged for a collectible transfer; `0` enables the free-transfer RPC. |
|
||||
| `TELESRV_STARGIFT_DROP_DETAILS_STARS` | int64 / `25` | Stars charged to remove a collectible's original sender/message details. |
|
||||
| `TELESRV_STARGIFT_OFFER_MIN_STARS` | int / `1` | Minimum Stars offer snapshotted for user-owned collectibles; `0` disables the offer entry point. |
|
||||
| `TELESRV_STARGIFT_STARS_PROCEEDS_PERMILLE` | int / `1000` | Seller share in Stars sales, in permille; the remainder is recorded as platform commission. |
|
||||
| `TELESRV_STARGIFT_TON_PROCEEDS_PERMILLE` | int / `1000` | Seller share in internal-TON sales, in permille; this affects only the local ledger. |
|
||||
| `TELESRV_STARGIFT_EXPORT_DELAY` | duration / `0s` | Delay snapshotted into `can_export_at` when a collectible is issued. |
|
||||
| `TELESRV_STARGIFT_TRANSFER_DELAY` | duration / `0s` | Delay snapshotted into `can_transfer_at`. |
|
||||
| `TELESRV_STARGIFT_RESELL_DELAY` | duration / `0s` | Delay snapshotted into `can_resell_at`. |
|
||||
| `TELESRV_STARGIFT_CRAFT_DELAY` | duration / `0s` | Delay snapshotted into `can_craft_at`. |
|
||||
| `TELESRV_STARGIFT_CRAFT_CHANCE_PERMILLE` | int / `250` | Per-input local craft success contribution, capped at 1000 permille. |
|
||||
|
||||
## 11. Private calls, group calls, TURN, SFU, and livestream
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
| 参数 | 类型 / 代码默认值 | 说明与约束 |
|
||||
|---|---|---|
|
||||
| `TELESRV_DEBUG_ADDR` | nullable address / `127.0.0.1:6060` | pprof/debug 监听;空值关闭。生产必须保持 loopback,通过 SSH 隧道抓取。 |
|
||||
| `TELESRV_BOT_API_ADDR` | nullable address / 空 | 最小 HTTP Bot API 监听;空值关闭,与 MTProto 共用 app/store 事实。 |
|
||||
| `TELESRV_BOT_API_ADDR` | nullable address / 空 | 最小 HTTP Bot API 监听;空值关闭,与 MTProto 共用 app/store 事实。`setWebhook` 接受任意合法 `http://` 或 `https://` 主机/IP 与 `1..65535` 端口。 |
|
||||
| `TELESRV_ADMIN_API_ADDR` | nullable address / 空 | 进程内 Admin 写 API;空值关闭,生产应只监听 loopback。 |
|
||||
| `TELESRV_ADMIN_API_TOKEN` | secret string / 空 | Admin API bearer token;启用 Admin API 时必须显式配置,并与 Admin UI 使用的 token 一致。 |
|
||||
| `TELESRV_ADMIN_UI_ADDR` | address / `127.0.0.1:2600` | 独立 `cmd/telesrv-admin` 监听地址。 |
|
||||
|
|
@ -62,7 +62,181 @@
|
|||
| `TELESRV_PUBLIC_APP_SCHEME` | URL scheme / `telesrv` | 落地页自动唤起客户端的 scheme,必须与 patched 客户端注册值一致;禁止 `tg`、`http`、`https`。 |
|
||||
| `TELESRV_PUBLIC_WEB_BASE_URL` | HTTP(S) URL / `https://web.telesrv.net` | username 页面 Web 客户端入口,校验规则同 `TELESRV_PUBLIC_BASE_URL`。 |
|
||||
| `TELESRV_PUBLIC_APP_NAME` | string / `telesrv` | 公开落地页产品名;trim 后非空、无控制字符、最多 64 个 Unicode 字符。 |
|
||||
| `TELESRV_PUBLIC_LINK_WEB_ADDR` | nullable address / 空 | 只读 username/avatar/sticker/emoji/chatlist 落地页监听;空值关闭。生产应 loopback + nginx 精确反代;`.env.example` 为开发启用 `127.0.0.1:2401`。 |
|
||||
| `TELESRV_PUBLIC_LINK_WEB_ADDR` | nullable address / 空 | 只读 username/avatar/sticker/emoji/chatlist/collectible gift 落地页监听;空值关闭。生产应 loopback + nginx 精确反代;`.env.example` 为开发启用 `127.0.0.1:2401`。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_ENABLE` | bool / `false` | 在 `TELESRV_PUBLIC_LINK_WEB_ADDR` 上挂载自建 Telegram Login/OIDC Provider;启用时必须同时配置该 listener 与下列全部密钥文件。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_ISSUER` | 绝对 origin URL / `TELESRV_PUBLIC_BASE_URL` | discovery 与 token 使用的精确公开 issuer;默认必须 HTTPS,禁止 path、credentials、query、fragment。开启下一项后可直接配置任意 HTTP 域名/IP。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP` | bool / `false` | 开启后允许任意合法 HTTP issuer、BotFather Web origin、redirect URI 和 native HTTP callback,不限制为 loopback,也不限制 IP 网段或端口。关闭时这些 Web URL 仍必须 HTTPS。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_SIGNING_KEYS_FILE` | path / `data/telegram-login/signing-keys.json` | 由 `cmd/telegramloginkeygen` 生成的 JOSE 私钥环;JWKS 会发布 active 和仍在退役窗口内的公钥。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_CODE_KEYS_FILE` | path / `data/telegram-login/code-keys.json` | 用于可恢复一次性 authorization code 的 AES-256-GCM envelope key ring。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_SECRET_PEPPER_FILE` | path / `data/telegram-login/client-secret-pepper` | HMAC-SHA-256 Client Secret 摘要的部署 pepper 文件,内容必须是恰好 32 个随机字节的 base64 编码。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_REQUEST_TTL` | duration / `5m` | pending authorization 生命周期,限定 `1m..15m`。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_CODE_TTL` | duration / `2m` | 一次性 code 生命周期,限定 `30s..10m`。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_ID_TOKEN_TTL` | duration / `1h` | ID token 生命周期,限定 `1m..24h`;退役签名公钥必须覆盖该窗口。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_TRUSTED_PROXY_CIDRS` | 逗号分隔 CIDR / 空 | 只有直连 peer 落在该列表时才信任 `Forwarded`/`X-Forwarded-*` 客户端元数据;文档中的单机 nginx 部署使用 `127.0.0.1/32,::1/128`。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_RETENTION` | duration / `168h` | terminal request/code/revocation 后的保留期,限定 `1h..90d`。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_SWEEP_INTERVAL` | duration / `5m` | retention worker 周期,限定 `10s..1h`。 |
|
||||
| `TELESRV_TELEGRAM_LOGIN_SWEEP_BATCH` | int / `500` | 每轮最大清理行数,限定 `1..1000`。 |
|
||||
|
||||
### 3.1 Telegram Login / OIDC 完整启用流程
|
||||
|
||||
#### 1. 一次性生成 `data/telegram-login`
|
||||
|
||||
在 `telesrv` 仓库根目录执行:
|
||||
|
||||
```powershell
|
||||
go run ./cmd/telegramloginkeygen -mode init -dir data/telegram-login
|
||||
Get-ChildItem .\data\telegram-login
|
||||
```
|
||||
|
||||
Linux 部署也可使用同一命令;生成后应限制目录权限:
|
||||
|
||||
```bash
|
||||
go run ./cmd/telegramloginkeygen -mode init -dir data/telegram-login
|
||||
chmod 0700 data/telegram-login
|
||||
chmod 0600 data/telegram-login/*
|
||||
```
|
||||
|
||||
初始化会生成以下私密文件,命令不会把密钥内容输出到终端,并会拒绝覆盖已经存在的
|
||||
`signing-keys.json`、`code-keys.json` 或 `client-secret-pepper`:
|
||||
|
||||
- `signing-keys.json` 和三个 `signing-*.pem`:RS256、ES256、EdDSA ID token 签名私钥及清单;
|
||||
- `code-keys.json`:一次性 authorization code 使用的 AES-256-GCM envelope key ring;
|
||||
- `client-secret-pepper`:保存和校验 OIDC Client Secret 摘要时使用的 32 字节部署 pepper。
|
||||
|
||||
`data/*` 默认已被仓库 `.gitignore` 排除。不要把该目录放入 Git、发布压缩包、日志或
|
||||
普通备份;多实例必须挂载同一份受保护的文件,并在轮换后一起重启。丢失 pepper 会让
|
||||
现有 Client Secret 无法验证,丢失仍在发布窗口内的签名私钥会让尚未过期的 ID token
|
||||
无法继续通过 JWKS 验证。
|
||||
|
||||
#### 2. 配置并启动 Provider
|
||||
|
||||
以下示例直接通过 `http://192.0.2.25:2401` 对外提供 OIDC;请替换成客户端实际可达的
|
||||
服务器 IP。直接监听局域网/公网网卡时使用 `0.0.0.0:2401`,仅由同机反向代理转发时
|
||||
应改回 `127.0.0.1:2401`:
|
||||
|
||||
```env
|
||||
TELESRV_PUBLIC_BASE_URL=http://192.0.2.25:2401
|
||||
TELESRV_PUBLIC_LINK_WEB_ADDR=0.0.0.0:2401
|
||||
TELESRV_PUBLIC_APP_SCHEME=telesrv
|
||||
|
||||
TELESRV_TELEGRAM_LOGIN_ENABLE=true
|
||||
TELESRV_TELEGRAM_LOGIN_ISSUER=http://192.0.2.25:2401
|
||||
TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP=true
|
||||
TELESRV_TELEGRAM_LOGIN_SIGNING_KEYS_FILE=data/telegram-login/signing-keys.json
|
||||
TELESRV_TELEGRAM_LOGIN_CODE_KEYS_FILE=data/telegram-login/code-keys.json
|
||||
TELESRV_TELEGRAM_LOGIN_SECRET_PEPPER_FILE=data/telegram-login/client-secret-pepper
|
||||
```
|
||||
|
||||
使用 HTTPS 时,把 `TELESRV_TELEGRAM_LOGIN_ISSUER` 和公开根地址改成精确 HTTPS
|
||||
origin,并保持 `TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP=false`。issuer 是 token 的 `iss`
|
||||
以及 discovery 中所有端点的根地址,scheme、host 和 port 必须与依赖方访问的地址完全
|
||||
一致。启动或重启 `telesrv` 后,先验证公开端点:
|
||||
|
||||
```powershell
|
||||
curl.exe http://192.0.2.25:2401/.well-known/openid-configuration
|
||||
curl.exe http://192.0.2.25:2401/.well-known/jwks.json
|
||||
curl.exe -I http://192.0.2.25:2401/js/telegram-login.js
|
||||
```
|
||||
|
||||
discovery 返回的 `issuer` 必须等于配置值,`authorization_endpoint`、`token_endpoint`
|
||||
和 `jwks_uri` 必须可从依赖方访问。使用反向代理时需原样转发
|
||||
`/.well-known/openid-configuration`、`/.well-known/jwks.json`、`/auth`、`/auth/status`、
|
||||
`/token`、`/crossapp`、`/inapp`、`/telegram-login.js` 和 `/js/telegram-login.js`。
|
||||
|
||||
#### 3. 用本服 `@BotFather` 创建 OIDC Client
|
||||
|
||||
先用 `/newbot` 创建或选择已有 bot,然后在本服 `@BotFather` 中执行 `/setlogin` 并选择
|
||||
该 bot。首次配置会返回:
|
||||
|
||||
- `Client ID`:bot user ID 的十进制字符串;
|
||||
- `Client Secret`:只显示一次,与 Bot API token 不同,必须立即保存到密钥管理系统。
|
||||
|
||||
接着逐条发送配置命令。下面假设依赖方页面运行在 `http://192.0.2.30:3000`:
|
||||
|
||||
```text
|
||||
add origin http://192.0.2.30:3000
|
||||
add redirect http://192.0.2.30:3000/oauth/callback
|
||||
algorithm RS256
|
||||
enable
|
||||
```
|
||||
|
||||
`origin` 只能是无 path/query/fragment 的精确 Web origin,用于 JS SDK、popup CORS 和
|
||||
legacy `login_url`;`redirect` 是 Authorization Code Flow 返回 code 的精确完整 URI。
|
||||
不支持 wildcard 或 prefix 匹配。用 `/logininfo` 检查状态和登记值;用 `/setlogin`
|
||||
增删 URL、切换签名算法或 disable;用 `/resetloginsecret` 轮换 Client Secret。可用的
|
||||
签名算法为 RS256、ES256、EdDSA,以及仅在对应构建和 key ring 已提供时可选的 ES256K;
|
||||
EdDSA/ES256K 只允许 `openid` scope。
|
||||
|
||||
#### 4. 依赖方接入标准 OIDC
|
||||
|
||||
依赖方应首先读取:
|
||||
|
||||
```text
|
||||
http://192.0.2.25:2401/.well-known/openid-configuration
|
||||
```
|
||||
|
||||
标准流程为 Authorization Code + PKCE S256:
|
||||
|
||||
1. 生成随机 `state`、`nonce` 和 PKCE `code_verifier`,计算 S256 `code_challenge`;
|
||||
2. 浏览器打开 discovery 中的 `authorization_endpoint`,携带 `client_id`、精确
|
||||
`redirect_uri`、`response_type=code`、包含 `openid` 的 `scope`、`state`、`nonce`、
|
||||
`code_challenge` 和 `code_challenge_method=S256`;
|
||||
3. 用户在 TDesktop/Android 中确认后,依赖方 callback 校验 `state` 并取得一次性 code;
|
||||
4. 服务端向 discovery 中的 `token_endpoint` POST `grant_type=authorization_code`、code、
|
||||
同一 `redirect_uri` 和 `code_verifier`,机密 client 使用 HTTP Basic 或
|
||||
`client_secret_post` 提交 Client Secret;
|
||||
5. 用 discovery 的 `jwks_uri` 验证 ID token 签名,并严格校验 `iss`、`aud`、`exp`、
|
||||
`nonce` 和非空 `sub`。不要只解码而不验签。
|
||||
|
||||
支持的 scope 为 `openid`、`profile`、`phone`、`telegram:bot_access`。当前不提供
|
||||
UserInfo、refresh token 或 introspection endpoint。浏览器前端可以加载
|
||||
`<issuer>/js/telegram-login.js` 使用本地 JS SDK;Client Secret 只能留在服务端。
|
||||
|
||||
#### 5. 使用 Bedolaga demo 验证完整链路
|
||||
|
||||
安装 demo 依赖:
|
||||
|
||||
```powershell
|
||||
python -m venv "$env:TEMP\telesrv-bedolaga-demo-venv"
|
||||
& "$env:TEMP\telesrv-bedolaga-demo-venv\Scripts\python.exe" -m pip install `
|
||||
-r .\cmd\bots\bedolagaformat\requirements.txt
|
||||
```
|
||||
|
||||
将第 3 步得到的 Client ID/Secret 和同一个 Bot API token 仅放入进程环境:
|
||||
|
||||
```powershell
|
||||
$env:TELESRV_BOT_TOKEN = "<bot_id>:<bot_api_secret>"
|
||||
$env:TELESRV_BOT_API_SERVER = "http://192.0.2.25:8081"
|
||||
$env:TELESRV_BOT_LOGIN_DEMO = "1"
|
||||
$env:TELESRV_BOT_LOGIN_ISSUER = "http://192.0.2.25:2401"
|
||||
$env:TELESRV_BOT_LOGIN_CLIENT_ID = "<BotFather 返回的 Client ID>"
|
||||
$env:TELESRV_BOT_LOGIN_CLIENT_SECRET = "<只显示一次的 OIDC Client Secret>"
|
||||
$env:TELESRV_BOT_LOGIN_PUBLIC_URL = "http://192.0.2.30:3000"
|
||||
$env:TELESRV_BOT_LOGIN_LISTEN = "0.0.0.0:3000"
|
||||
|
||||
& "$env:TEMP\telesrv-bedolaga-demo-venv\Scripts\python.exe" `
|
||||
.\cmd\bots\bedolagaformat\demo.py --drop-pending --login-demo
|
||||
```
|
||||
|
||||
确保 BotFather 登记的 origin 等于 `TELESRV_BOT_LOGIN_PUBLIC_URL`,redirect 等于
|
||||
`<TELESRV_BOT_LOGIN_PUBLIC_URL>/oauth/callback`。在客户端向 bot 发送 `/logindemo`:第一颗
|
||||
按钮验证 Bot API `login_url` 和 HMAC 回调,第二颗按钮页面分别验证本地 JS SDK popup
|
||||
以及 Authorization Code + PKCE/JWKS。省略 Client Secret 时只能验证 JS popup,服务端
|
||||
code flow 会明确禁用。
|
||||
|
||||
#### 6. 密钥轮换
|
||||
|
||||
签名 key 轮换时,旧公钥发布窗口必须至少覆盖配置的 ID token TTL 再加 10 分钟;操作
|
||||
完成后所有实例一起重启:
|
||||
|
||||
```powershell
|
||||
go run ./cmd/telegramloginkeygen -mode rotate-signing -algorithm RS256 `
|
||||
-id-token-ttl 1h -publish-for 2h -dir data/telegram-login
|
||||
go run ./cmd/telegramloginkeygen -mode rotate-code -dir data/telegram-login
|
||||
```
|
||||
|
||||
`rotate-signing` 可分别用于 RS256、ES256、EdDSA;`rotate-code` 保留旧 code key 并新增
|
||||
active key。不要手工编辑 manifest 或 PEM,不要在各实例上分别生成不一致的 key ring。
|
||||
|
||||
## 4. PostgreSQL、Redis、文件与 seed
|
||||
|
||||
|
|
@ -95,7 +269,7 @@
|
|||
| `TELESRV_AUTH_CODE_RATE_WINDOW` | duration / `10m` | 手机号与 auth-key 发码限流共用窗口。 |
|
||||
| `TELESRV_PHONE_CODE_DELIVERY_PROVIDER` | enum / `development` | `development` 使用固定码;`webhook` 为登录、注册、改号生成随机 SMS code 并调用 OTP Webhook。已有账号在两种模式下都先 durable 写入同码 777000 消息,Webhook 只是附加渠道。 |
|
||||
| `TELESRV_EMAIL_CODE_DELIVERY_PROVIDER` | enum / `smtp` | 登录邮箱、邮箱 setup/change 的投递实现:`smtp` 或 `webhook`。已有账号的登录邮箱码会先同码镜像到 777000;邮箱 setup/change 仍只走 provider。 |
|
||||
| `TELESRV_OTP_WEBHOOK_URL` | absolute URL / 空 | 任一 provider 选择 `webhook` 时必填;固定 v1 协议见 [otp-delivery.md](otp-delivery.md)。只允许 `http`/`https` 且不得含 userinfo。 |
|
||||
| `TELESRV_OTP_WEBHOOK_URL` | absolute URL / 空 | 任一 provider 选择 `webhook` 时必填;固定 v1 协议见 [otp-delivery.md](otp-delivery.md)。允许任意合法 `http://` 或 `https://` 主机/IP 与端口,不得含 userinfo。 |
|
||||
| `TELESRV_OTP_WEBHOOK_SECRET` | secret string / 空 | 可选 HMAC-SHA256 签名密钥;非空时发送 `X-Telesrv-Signature`。 |
|
||||
| `TELESRV_OTP_WEBHOOK_TIMEOUT` | duration / `5s` | Webhook HTTP 请求超时,启用 Webhook 时必须为正数。 |
|
||||
| `TELESRV_LOGIN_EMAIL_ENABLE` | bool / `false` | 启用登录邮箱验证码;email provider 为 `smtp` 时要求 SMTP 配置,`webhook` 时不依赖 SMTP。 |
|
||||
|
|
@ -207,6 +381,19 @@
|
|||
| `TELESRV_STARS_STARTING_GRANT` | int64 / `1000` | 对所有账号幂等惰性授予的 Stars 起始余额;`0` 关闭自动赠送。 |
|
||||
| `TELESRV_PREMIUM_SWEEP_INTERVAL` | duration / `1m` | 过期 Premium 清理/推送周期;读取路径独立即时派生到期状态。 |
|
||||
| `TELESRV_PREMIUM_SWEEP_BATCH` | int / `500` | 单次 sweep 最大处理行数。 |
|
||||
| `TELESRV_STARGIFT_SWEEP_INTERVAL` | duration / `15s` | Star Gift 报价/竞拍本地生命周期清扫周期;不会连接区块链。 |
|
||||
| `TELESRV_STARGIFT_SWEEP_BATCH` | int / `1000` | 单次礼物生命周期清扫最多处理的报价、竞拍与 outbox 工作量。 |
|
||||
| `TELESRV_STARGIFT_TON_STARTING_GRANT` | int64 / `10000000000` | 每个用户首次访问 telesrv 内部 TON 账本时幂等授予的 nanoton;`0` 关闭赠送。它不是链上资产。 |
|
||||
| `TELESRV_STARGIFT_TRANSFER_STARS` | int64 / `25` | collectible 转赠费用;设为 `0` 时使用免费转赠 RPC。 |
|
||||
| `TELESRV_STARGIFT_DROP_DETAILS_STARS` | int64 / `25` | 移除 collectible 原始发送者/附言信息所需 Stars。 |
|
||||
| `TELESRV_STARGIFT_OFFER_MIN_STARS` | int / `1` | collectible 签发时固化的用户持有礼物最低 Stars 报价;`0` 不开放报价入口。 |
|
||||
| `TELESRV_STARGIFT_STARS_PROCEEDS_PERMILLE` | int / `1000` | Stars 成交时卖方实收比例(千分比);差额作为平台佣金写入成交记录。 |
|
||||
| `TELESRV_STARGIFT_TON_PROCEEDS_PERMILLE` | int / `1000` | 内部 TON 成交时卖方实收比例(千分比);只影响本地账本。 |
|
||||
| `TELESRV_STARGIFT_EXPORT_DELAY` | duration / `0s` | collectible 签发时固化到 `can_export_at` 的等待期。 |
|
||||
| `TELESRV_STARGIFT_TRANSFER_DELAY` | duration / `0s` | 签发时固化到 `can_transfer_at` 的等待期。 |
|
||||
| `TELESRV_STARGIFT_RESELL_DELAY` | duration / `0s` | 签发时固化到 `can_resell_at` 的等待期。 |
|
||||
| `TELESRV_STARGIFT_CRAFT_DELAY` | duration / `0s` | 签发时固化到 `can_craft_at` 的等待期;可 Craft 礼物即使为 `0s` 也写升级时间这一正数能力边界,0 只表示不具备 Craft 能力或已终结。 |
|
||||
| `TELESRV_STARGIFT_CRAFT_CHANCE_PERMILLE` | int / `250` | 每份输入礼物贡献的本地合成成功概率,累计上限 1000‰。 |
|
||||
|
||||
## 11. 私聊通话、群通话、TURN、SFU 与直播
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue