Skip to content

Implement WhatsApp magic link authentication flow with SuperTokens #266

@lamurian

Description

@lamurian

User Story

As a user, I want to log in via WhatsApp magic link so that I can seamlessly upgrade my anonymous session to an authenticated session without needing a password.

Description

We need to extend our current SuperTokens-based session management to support WhatsApp magic link authentication. The flow should support both anonymous guest sessions and persistent authenticated sessions. A new button ("Login with WhatsApp") will be added to the custom prebuilt UI. When clicked, users will be redirected to the Konsulin WhatsApp bot with a pre-defined authentication request. The bot will generate and send a magic link via WhatsApp using the omnichannel service. Clicking the link should complete authentication and upgrade the session.

In addition, the registration process must trigger integrations:

  • A webhook to create a new contact in the omnichannel system.
  • A Patient resource creation in the FHIR system if the WhatsApp number is not registered, or an update to the existing Patient resource to include the SuperTokens identifier.

The predefined text:

Request login, authenticate me.

Example of successful authentication request:

Image

Proposed Flow

  • Extend SuperTokens Passwordless Recipe to support WhatsApp magic link flow.
  • Customize prebuilt UI to add "Login with WhatsApp" button.
  • Redirect user to Konsulin bot with predefined text message ("Authenticate me") using WhatsApp universal link.
  • Bot generates and sends a WhatsApp magic link via the omnichannel service.
  • User clicks the link, completing authentication and upgrading session.
  • Trigger webhook to create new contact in the omnichannel system.
  • Create a new Patient resource in FHIR if WhatsApp number is not registered.
  • Update existing Patient resource with SuperTokens identifier if WhatsApp number already exists.

Reference

  • SuperTokens Passwordless Recipe documentation and its implementation in Konsulin
    Passwordless.init({
    contactMethod: 'EMAIL',
    onHandleEvent: async context => {
    if (context.action === 'SUCCESS') {
    const { id: userId, emails } = context.user;
    const roles = await getClaimValue({ claim: UserRoleClaim });
    localStorage.setItem('skip-response-cleanup', 'true');
    if (
    context.isNewRecipeUser &&
    context.user.loginMethods.length == 1
    ) {
    // Create FHIR Profile for new user
    const profile = await createProfile({
    userId,
    email: emails[0],
    type: roles.includes('practitioner')
    ? 'Practitioner'
    : 'Patient'
    });
    const cookieData = {
    userId,
    role_name: roles.includes('practitioner')
    ? 'practitioner'
    : 'patient',
    email: emails[0],
    profile_picture: profile?.photo ? profile?.photo[0]?.url : '',
    fullname: mergeNames(profile?.name),
    fhirId: profile?.id ?? ''
    };
    await setCookies('auth', JSON.stringify(cookieData));
    } else {
    const result = await getProfileByIdentifier({
    userId,
    type: roles.includes('practitioner')
    ? 'Practitioner'
    : 'Patient'
    });
    const cookieData = {
    userId,
    role_name: roles.includes('practitioner')
    ? 'practitioner'
    : 'patient',
    email: emails[0],
    profile_picture: result?.photo ? result?.photo[0]?.url : '',
    fullname: mergeNames(result?.name, result?.qualification),
    fhirId: result?.id ?? ''
    };
    await setCookies('auth', JSON.stringify(cookieData));
    }
    routerInfo.router.refresh();
    }
    }
    })
  • Konsulin omnichannel service integration via the Konsulin api webhook endpoint [base]/api/v1/hook
  • FHIR Patient resource management
  • Existing session management implementation with SuperTokens

Notes:

  • Ensure smooth migration from anonymous to authenticated session without breaking continuity.
  • Pay attention to idempotency when creating or updating Patient resources to avoid duplicates.
  • Security considerations: validate WhatsApp magic link origin and integrity before upgrading session.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions