Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Telegram Login Auth Laravel Package

azate/laravel-telegram-login-auth

Laravel package that adds Telegram Login authentication to your app. It verifies signed Telegram Login Widget data, integrates with Laravel guards, and lets users sign in via Telegram with configurable routes, middleware, and user provisioning.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish

composer require azate/laravel-telegram-login-auth
php artisan vendor:publish --provider="Azate\TelegramLoginAuth\TelegramLoginAuthServiceProvider"

This typically publishes a config file (config/telegram-login-auth.php or similar) and possibly a migration for storing Telegram IDs on your users table. Check the vendor/azate/laravel-telegram-login-auth/ directory right after install — with a package this small (37 stars), the README and the source are your best documentation. Read src/ top-to-bottom; it's likely under a dozen files.

Configure credentials

Add your bot credentials to .env:

TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
TELEGRAM_BOT_USERNAME=your_bot_name

The bot token is what the package uses to validate the hash returned by the Telegram Login Widget. The bot username is what renders the widget on your page. These are two different values — don't confuse them.

First use case: log a user in from a Telegram widget

  1. Register the routes (the service provider usually auto-registers a callback route, or you publish/define your own).
  2. Drop the Telegram Login Widget <script> into your login blade, pointing its data-auth-url (or data-onauth handler) at the package's callback route.
  3. Point the widget at your callback, which validates the payload, resolves or creates a User, and calls Auth::login().

A minimal blade snippet:

<script async src="https://telegram.org/js/telegram-widget.js?22"
        data-telegram-login="{{ config('telegram-login-auth.bot_username') }}"
        data-size="large"
        data-auth-url="{{ route('telegram.login.callback') }}"
        data-request-access="write"></script>

If the package ships a route macro or a Socialite-style driver, use it — otherwise bind its service into your own controller and call the verifier directly. Look first at the package's routes/ file and the Http/Controllers namespace to see exactly what it exposes.

Implementation Patterns

Standalone controller integration

The most common pattern for a small package like this is to let the provider handle verification and then dispatch a domain event, or to inject the package's verifier class into your own controller. Prefer the latter for control over user creation:

public function __invoke(TelegramLoginRequest $request, TelegramVerifier $verifier)
{
    $payload = $verifier->validate($request->all()); // throws on bad hash
    $user = User::firstOrCreate(
        ['telegram_id' => $payload['id']],
        ['name' => $payload['first_name'].' '.$payload['last_name'], 'email' => null]
    );
    Auth::login($user, remember: true);
    return redirect()->intended('/dashboard');
}

Pairing with existing auth

Since Telegram does not return an email, the standard pattern is:

  • If the Telegram ID matches an existing user, log them in.
  • If not, offer a "link your Telegram account" flow for logged-in users, or create a user with a placeholder email.
  • Never auto-login based on a phone number or username — only on the Telegram numeric id.

Extending user creation

If the package exposes a user_model config key (common in similar packages), point it at your own App\Models\User. If it uses a hardcoded model, extend it or override the callback route with your own controller and disable the package's route registration (config('telegram-login-auth.routes.enabled', false)).

Middleware and session

Wrap the callback in web middleware (it needs a session for Auth::login). If you use Sanctum or API tokens, exchange the Telegram verification for a token inside the same controller rather than relying on session state.

Testing pattern

Because the verifier only depends on the bot token, you can fake the hash in tests: compute hash_hmac('sha256', $dataCheckString, hash('sha256', $token, true)) against a dummy token in config(). Assert both the success redirect and the rejection path (tampered auth_date, expired timestamp).

Gotchas and Tips

  • Hash order is exact. Telegram's data_check_string must be the URL-decoded key-value pairs sorted alphabetically and joined with \n, excluding hash. If the package accepts the raw request, ensure $request->all() preserves values exactly — Laravel's request normalization can mangle names with special characters.
  • auth_date expiry is on you. Telegram does not expire the widget payload server-side. Reject payloads older than a few minutes (check auth_date against now()) if the package's verifier doesn't. This is a one-line check that prevents replay attacks.
  • HTTPS-only widget. Telegram refuses to render the Login Widget on non-HTTPS origins (localhost is a common exception). In local dev, either use a tunnel (ngrok, Expose) or set the bot domain explicitly in BotFather.
  • Bot domain binding. Set the allowed domain in BotFather (/setdomain) to the widget's host. If mismatch, the widget loads but auth-url callbacks fail silently — an easy hour to lose.
  • CSRF and POST vs GET. The Login Widget can POST to data-auth-url. If the callback is POST and behind VerifyCsrfToken, exempt just that route, or configure data-auth-url as GET and let the package's route handle it.
  • Token leakage. Never log the full request payload in production — it contains the signed user data. Also ensure TELEGRAM_BOT_TOKEN is only ever read from config(), not accessed directly in views.
  • Config caching trap. If the package reads env() directly instead of config(), php artisan config:cache will silently zero out the token. Verify in config/telegram-login-auth.php — if any line has env() you'll want to re-cache after every deploy or override with config() in a service provider.
  • Extension points to check first: the service provider (register / boot bindings), any published config flags for routes, middleware, user_model, and redirect_to. If these exist, use them instead of forking; for a 37-star package, upstream changes are infrequent, so a thin wrapper controller ages better than a patch.
  • Debugging failed verification: log the computed data_check_string and the received hash side by side in a local environment, and diff them character by character — 90% of "hash mismatch" bugs are an extra field, wrong sort order, or URL-encoded characters that weren't decoded.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums