Skip to main content
The same catalog is on veriqa.app/channels. The two are kept in sync, and a difference between them is a defect, not two opinions.
The user confirms a sign-in in a messaging app or a mailbox they already use — with nothing extra to install. Your application receives ordinary OpenID Connect tokens whichever channel was used. Every channel issues the base claims channel_type, channel_user_id and name — a card lists what the channel adds on top. For channels not shipped yet it shows what the platform’s API allows. Besides the claims, a channel’s description uses two terms: secret message and confirmation in the channel.

Secret message

A secret message is the message with the sign-in code that the user sends to the channel themselves after tapping the link or scanning the QR code. Veriqa fills it in, the messaging app shows it pre-filled, and the user only taps Send. Not every channel needs one. Examples:
  • Telegram and MAX: not needed — the messaging app opens the bot and hands it the code on its own.
  • WhatsApp: needed, for stronger security — the pre-filled message goes out with one tap.
  • Email: the same with a pre-filled email — the one-tap email (Push mode) — or optionally a classic magic link.

Confirmation in the channel

Confirmation in the channel is a feature where the bot asks right in the chat whether to let the sign-in through — which app and from which device — with Confirm and Decline buttons. It can be switched to automatic mode, and then the sign-in goes through without an extra request: the LoginConfirmation.Mode key in the configuration reference. Examples:
  • Telegram: the question comes as soon as the user opens the link.
  • WhatsApp: the question comes in reply to the secret message.
  • Email: no question in the channel — optionally it is asked on a page in the browser.

Built in

These ship with Veriqa — enable the ones you need in configuration.

Telegram

Claims on top of the base: given_name, family_name, preferred_username, locale, picturePhone number: phone_number and phone_number_verified on request — the user shares the number with a button in the chat (phone number)Confirmation in the channel: yesSecret message: not needed

WhatsApp

Claims on top of the base: given_name, preferred_username (if the user has turned on a WhatsApp username)Phone number: phone_number and phone_number_verified automatically when WhatsApp sends the number with the message; when the user hides it behind a username — on request, the user shares the number with a button in the chat (phone number)User identifier: sub and channel_user_id carry the business-scoped user ID (BSUID) — unique per Meta business portfolio and new when the user changes the number; preferred_username is a hint, not the identityConfirmation in the channel: yesSecret message: needed — one tap

WhatsApp through Twilio

The same WhatsApp channel, delivered through a Twilio account instead of the Meta WhatsApp Business Platform — one configuration key picks the provider (delivery through Twilio).Claims on top of the base: given_name, preferred_username (if the user has turned on a WhatsApp username)Phone number: phone_number and phone_number_verified automatically when WhatsApp sends the number with the message; a number hidden behind a username is not asked for — the request with a button in the chat is sent by the Meta Cloud API provider only (phone number)User identifier: sub and channel_user_id carry the business-scoped user ID (BSUID), as with the Meta provider; preferred_username is a hint, not the identityConfirmation in the channel: yes — two quick-reply buttonsSecret message: needed — one tap

MAX

Claims on top of the base: given_name, family_name, preferred_username, locale, picturePhone number: phone_number and phone_number_verified on request — the user shares the number with a button in the chat; webhook mode only (phone number)Confirmation in the channel: yesSecret message: not needed

Instagram

The user confirms in Instagram Direct, in a conversation with your Instagram professional account. Signing in users outside your own team needs access granted by Meta (channel setup).Claims on top of the base: preferred_username, picturePhone number: phone_number on request, with phone_number_verified: false — the user shares the number of their Instagram profile with a button in the chat; the button shows only in the Instagram mobile app and only if the profile has a number (phone number)Confirmation in the channel: yesSecret message: not needed

Messenger

The user confirms in Messenger, in a conversation with your Facebook Page. Signing in users outside your own team needs access granted by Meta (channel setup).Claims on top of the base: given_name, family_name, picture, locale — when Meta lets the app read the user’s profilePhone number: phone_number on request, with phone_number_verified: false — the user shares the number of their profile with a button in the chat; the button shows only if the profile has a number (phone number)Confirmation in the channel: yesSecret message: not needed

WeChat

The user scans the QR code with WeChat and confirms in the chat with your Official Account. The channel needs a verified Service Account (channel setup).Claims on top of the base: none — only the base ones; name holds the OpenIDConfirmation in the channel: yesSecret message: not needed

Viber

The user confirms in Viber, in a conversation with your bot. The adapter has been run only against a mock of the Bot API and has not been verified on the live Viber platform. Since February 5, 2024, Viber issues new bots on commercial terms only — get the bot and its token from Viber before a deployment (channel setup).Claims on top of the base: picture, localePhone number: phone_number on request, with phone_number_verified: false — the user shares the number with a button in the chat (phone number)Confirmation in the channel: yesSecret message: not needed

Email

Claims on top of the base: email, email_verified, preferred_username, veriqa_channel, veriqa_email_modeConfirmation in the channel: no — optionally in the browserSecret message: needed — one tap, or a classic magic linkTwo modes: the one-tap email (the user sends a pre-filled email, so nothing has to be delivered to them and no link can be used up by a mail gateway) and the classic magic link, which is on by default. What each one gives you — choosing between them.Receiving the one-tap email: through the webhook of an inbound mail provider, or without one — Veriqa reads an ordinary mailbox itself (one-tap email over IMAP).

Any channel over HTTP

Connect a channel Veriqa does not ship — your own bot, a corporate messaging app, a regional platform — as an external service in any language. Veriqa talks to it over HTTP, and the platform’s keys stay with your service. It is also one way to bring a bot you already run into the Veriqa flow — without publishing a new one; the other ways are compared in You already have a bot.
  • Claims on top of the base: whatever your adapter returns
  • Confirmation in the channel: declared by the adapter
  • Secret message: declared by the adapter

WhatsApp through Baileys

A working reference adapter in Node that links a WhatsApp number as a companion device, the way WhatsApp Web does — no Meta Business account and no provider. Meant for debugging WhatsApp scenarios, for small teams and for your own use.Risk: it runs on an unofficial WhatsApp Web client, and WhatsApp may ban the linked number — link a separate number you can afford to lose.Claims on top of the base: phone_number, given_nameConfirmation in the channel: yes — a poll with two optionsSecret message: needed — one tapThe sample: samples/node/custom-channel-whatsapp-baileys/.
How to write one, with reference adapters in Python and Node — An HTTP channel adapter in any language.

Pseudo-channels: Google, Apple and Huawei

A sign-in at an identity provider, wrapped into the shape of a channel. The screen shows a QR code, the user signs in to their Google, Apple or Huawei account on their own phone and confirms on a page there, and the sign-in completes on the screen. This is not a delivery channel: there is no chat or mailbox behind it, so no message can be sent to the user “in the channel”, and the question “is it you signing in?” is asked by a page on the phone. A pseudo-channel works under hop mode. Where it helps: signing in with Google on a device with no keyboard, such as a TV; on an operating system outside Google’s ecosystem and in a native app; confirming actions; and wherever typing a Google or Apple password is risky — on a shared or someone else’s computer, for instance. A user who has none of the messaging apps can sign in too, with the account their phone already has.

Google

Claims on top of the base: email, email_verified, given_name, family_name, picture, localeConfirmation in the channel: yes — on a page on the phoneSecret message: not neededDelivery: a sample .NET assembly in the host process — samples/dotnet/pseudo-channels

Apple

Claims on top of the base: email, email_verifiedConfirmation in the channel: yes — on a page on the phoneSecret message: not neededDelivery: a sample .NET assembly in the host process — samples/dotnet/pseudo-channels

Huawei

Claims on top of the base: email, email_verified, localeConfirmation in the channel: yes — on a page on the phoneSecret message: not neededDelivery: upcoming — a separate service next to Veriqa, connected as an HTTP channel, together with Google and Apple; see Coming next

Separate adapters: the channel-adapters repository

Adapters for LINE, Slack, Microsoft Teams, Discord, Zalo, KakaoTalk and Threema are already implemented, but they live outside the core, in the channel-adapters repository (see the source code). Each one is a separate .NET assembly, Veriqa.ChannelAdapter.<Channel>, built on the core contracts package. The host that embeds Veriqa registers it together with a channel declaration for the core (CoreChannelDeclaration); without the declaration the sign-in page does not offer the channel. The README of each adapter covers the sign-in flow, the platform setup and a minimal host; the ones run live also have a section on what the live platform revealed. “Live run” means a sign-in on the real platform with a real bot or app; “against an API stand-in” means a full sign-in against a local double of the platform API, written from its documentation.

LINE

Claims on top of the base: picture, localeStart: a line.me link with the text pre-filledTested: against an API stand-in

Slack

Claims on top of the base: given_name, family_name, preferred_username, email, picture, localeStart: the /veriqa <code> command in SlackTested: live run — both confirm and decline

Microsoft Teams

Claims on top of the base: given_name, family_name, preferred_username, emailStart: a deep link to a chat with the botTested: against an API stand-in

Discord

Claims on top of the base: preferred_username, picture, localeStart: a QR code or a link to the OAuth2 authorization page, or the /veriqa code:<code> command; the bot has to share a server with the userTested: live run — both confirm and decline, with claims from the real profile

Zalo

Claims on top of the base: pictureStart: the text auth_<code> sent to the botTested: against an API stand-in

KakaoTalk

Claims on top of the base: emailPhone number: not through the bot — only with your own Kakao Login or Kakao Sync integration (phone number)Start: the text auth_<code> sent to the botTested: against an API stand-in

Threema

Claims on top of the base: none — only the base onesStart: a threema.id linkTested: against an API stand-in
Slack, Zalo and KakaoTalk have no link that carries the transaction to the bot, so the sign-in page does not offer them by itself yet: the user gets the sign-in code some other way. The same repository has relays for Instagram and Messenger through the SendPulse and UChat chatbots: inside the host process, or as a separate service connected as an HTTP channel.