Skip to content

feat(openidconnect): add a Telegram provider - #1495

Open
smotim wants to merge 3 commits into
SocialiteProviders:masterfrom
smotim:feat/openidconnect-telegram
Open

smotim wants to merge 3 commits into
SocialiteProviders:masterfrom
smotim:feat/openidconnect-telegram

Conversation

@smotim

@smotim smotim commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Telegram Login speaks OpenID Connect now (docs), and the generic provider already does almost all the work. This adds a small TelegramProvider for the few places where Telegram differs, available as the telegram shorthand.

Some background: I've been running Telegram login and account linking in production since April through my own package, smotim/socialiteproviders-telegram-oidc. When the OpenID Connect provider landed here, I realised Telegram doesn't need a package of its own, just its quirks written down on top of this one. So here they are.

To avoid confusion with what's already here: Telegram is the legacy Login Widget (hash-signed payload), and TelegramWebApp validates Mini App initData. Neither of them does OIDC.

Where Telegram differs

  • There's no userinfo endpoint. Telegram's discovery document doesn't advertise one and never returns an email, so the userinfo call the base provider makes for an email-less id_token fails on the missing userinfo_endpoint key. Every claim is already in the id_token, so getUserByToken() returns null.
  • sub is an opaque value, not the user id people actually need. The id that bots, Mini Apps and the Bot API know is the id claim, and it only comes with the profile scope. getId() returns id, sub stays in getRaw(), and profile is always requested. A token without id is refused rather than falling back to sub, because I learned the hard way that a silent fallback splits one person into two accounts.
  • There's no email scope, so the defaults are openid profile.
  • Nickname and avatar come from preferred_username and picture.

Checked against the real thing

On top of the unit tests, I ran this branch against Telegram with a real bot:

  • the nonce round-trips through the redirect flow, so it stays on;
  • client_secret_basic without client_id in the body is accepted;
  • id arrives as a numeric string, not a number as in the docs example (the provider accepts both);
  • the id_token is valid for just 30 seconds, hence the note about clock sync and clock_skew in the README.

Happy to reshape

  • If you'd rather keep getId() = sub for consistency with the base class, I can switch it. For Telegram, though, id is what everyone ends up needing.
  • Instead of overriding getUserByToken(), the base provider could skip userinfo whenever discovery has no userinfo_endpoint (it's RECOMMENDED, not REQUIRED, in OIDC Discovery 1.0). I can send that as a separate PR if you prefer the general fix.

Tests are in tests/OpenIDConnect/Unit/TelegramProviderTest.php, built on the existing InteractsWithOidc harness with a discovery document shaped like Telegram's. All 206 OpenID Connect tests pass on PHP 8.5, and Pint is clean.

I paired with Claude Code on this; I reviewed every line and ran the flow against a real bot myself.

Telegram Login speaks OpenID Connect
(https://core.telegram.org/bots/telegram-login) but differs from the
generic defaults in three ways:

- Its discovery document has no userinfo_endpoint, and Telegram never
  returns an email, so the userinfo call made for an email-less id_token
  failed on the missing key. Every claim is already in the id_token.
- The user id that bots and Mini Apps know is the numeric `id` claim of
  the `profile` scope; `sub` is a different, opaque value. getId() returns
  `id`, `profile` is always requested, and a token without `id` is refused.
- There is no `email` scope, so the scopes default to `openid profile`.

The provider is available as the `telegram` shorthand.

Checked against Telegram with a real bot: the nonce round-trips through
the redirect flow, client_secret_basic is accepted, `id` arrives as a
numeric string, and the id_token is valid for 30 seconds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@atymic
atymic requested a lite review from Copilot September 23, 2026 00:55

@atymic atymic left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

Should we deprecate the old provider?

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Filter unsupported email scopes before adding Telegram’s required profile scope.

Review effort: Lite
Findings: None

What changed in this PR

Adds a built-in Telegram OpenID Connect provider with Telegram-specific claims, scopes, and userinfo handling.

Changes:

  • Adds and registers the telegram provider.
  • Maps Telegram IDs, usernames, and avatars.
  • Adds documentation and unit tests.
File Summary
tests/​OpenIDConnect/​Unit/​TelegramProviderTest.php Tests Telegram OIDC behavior.
src/​OpenIDConnect/​README.md Documents configuration and provider behavior.
src/​OpenIDConnect/​Providers/​TelegramProvider.php Implements Telegram-specific OIDC handling.
src/​OpenIDConnect/​OpenIDConnectServiceProvider.php Registers the provider shorthand.
src/​OpenIDConnect/​docs/​extending.md Documents the new shorthand.
src/​OpenIDConnect/​config/​oidc.php Updates configuration documentation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@smotim

smotim commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for the PR!

Should we deprecate the old provider?

I wouldn't deprecate it just yet. Telegram does label the Login Widget as legacy, but it doesn't look like it's been switched off. I checked it myself back in April and it still worked. People who already use it would get a deprecation warning with no real reason to migrate.

What I'd suggest instead is adding a note to the Telegram provider's docs page pointing to the OpenID Connect flow and the new telegram shorthand, so new users don't pick the legacy one by mistake.

Also, a small heads-up: yesterday I sent an email to the address in the security policy about two issues, with a patch attached. Just making sure it didn't end up in spam. No rush, of course.

The other built-in providers are named there, and it is what people
search the docs page for.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants