Skip to main content

SuperTokens Rownd Python Plugin

Rownd migration plugin for supertokens_python.

This package is managed by Turborepo through package.json, but published as a Python package named supertokens-rownd.

Installation

Install from PyPI:

pip install supertokens-rownd

With uv:

uv add supertokens-rownd

For local development, install from this repository checkout with uv sync --dev.

Local Development

cd packages/rownd-python
uv sync --dev
uv run python -m build
uv run pytest

From the repository root, Turborepo can run the Python package tasks because this directory has a package.json workspace adapter:

npm run build -- --filter=@supertokens-plugins/rownd-python
npm run test -- --filter=@supertokens-plugins/rownd-python

Usage

from supertokens_python import (
    InputAppInfo,
    SupertokensConfig,
    SupertokensExperimentalConfig,
    init,
)
from supertokens_python.recipe import accountlinking, emailverification, passwordless, session, thirdparty, usermetadata
from supertokens_rownd import init as RowndMigrationPlugin

init(
    app_info=InputAppInfo(
        app_name="My App",
        api_domain="https://api.example.com",
        website_domain="https://example.com",
        api_base_path="/auth",
    ),
    framework="fastapi",
    supertokens_config=SupertokensConfig(
        connection_uri="https://try.supertokens.com",
    ),
    recipe_list=[
        accountlinking.init(),
        session.init(),
        usermetadata.init(),
        passwordless.init(
            contact_config=passwordless.ContactEmailOrPhoneConfig(),
            flow_type="MAGIC_LINK",
        ),
        emailverification.init(mode="OPTIONAL"),
        thirdparty.init(sign_in_and_up_feature=thirdparty.SignInAndUpFeature(providers=[])),
    ],
    experimental=SupertokensExperimentalConfig(
        plugins=[
            RowndMigrationPlugin(
                rownd_app_key="rownd_app_key",
                rownd_app_secret="rownd_app_secret",
                # Must match InputAppInfo.api_base_path.
                api_base_path="/auth",
                # Should match InputAppInfo.api_domain.
                api_domain="https://api.example.com",
                # Should match InputAppInfo.website_domain when using passwordless confirmation bypass.
                website_domain="https://example.com",
                app_name="My App",
                app_config={
                    "auth": {
                        "enforceSameDevicePasswordlessSignIn": True,
                    }
                },
            )
        ]
    ),
)

app_config.auth.enforceSameDevicePasswordlessSignIn controls the Hub UI policy for passwordless flows originating from mobile_app. It does not enforce server-side device binding.

Routes

The plugin registers these routes below api_base_path:

  • GET /plugin/rownd/app-config
  • POST /plugin/rownd/guest
  • POST /plugin/rownd/migrate
  • POST /plugin/migrate-session
  • POST /plugin/passwordless-cross-device-confirmation/validate
  • POST /plugin/rownd/signout

Migration and guest routes accept an optional tenantId query parameter and default to public. Compatibility user views, sessions, and pending email verification are scoped to that tenant; user metadata remains shared across tenant memberships.

Rownd passwordless identifiers are authoritative during migration. When an exact third-party identity and an existing Passwordless email belong to separate users, the plugin links the Passwordless method only if Rownd verifies that email, its owner is not already primary, and it is not mapped to another Rownd user. verified_data.email must be true or match data.email case-insensitively. Other ownership conflicts still fail migration.

After all Rownd users have migrated, retain the compatibility routes without Rownd credentials by configuring disable_rownd_user_migration=True. This removes both migration routes; when no app key is configured, it uses an internal app key for passwordless and verification-link rewriting.

Passwordless resend requests preserve Rownd display, redirect, client-domain, app-variant, and OAuth context. Combined OTP and magic-link deliveries add the Hub passwordlessFlowType=USER_INPUT_CODE_AND_MAGIC_LINK parameter; OTP-only deliveries are left unchanged.

  • GET /plugin/rownd/user
  • PUT /plugin/rownd/user
  • DELETE /plugin/rownd/user
  • GET /plugin/rownd/user/meta
  • PUT /plugin/rownd/user/meta
  • GET /plugin/rownd/user/field
  • PUT /plugin/rownd/user/field

Rownd Compatibility

The plugin exposes Rownd-compatible user/session behavior for migrated and new SuperTokens users:

  • Guest sessions use the guest third-party provider.
  • Instant sessions use the instant third-party provider and preserve auth_level: "instant".
  • Passwordless and third-party sign-in refresh Rownd session claims after account linking while preserving the linked guest's anonymous_id.
  • Compatibility reads combine metadata from the primary and linked recipe users. Profile and metadata writes target the primary user without relocating linked Rownd metadata.
  • Google and Apple third-party login methods are exposed as google_id and apple_id in Rownd-compatible user payloads.
  • OAuth2 Provider tokens and userinfo responses include Rownd claims plus standard email, phone, and profile claims when those scopes are requested.
  • OAuth2 resource=app:* requests are translated to SuperTokens audience=app:* for Rownd-compatible OAuth clients.
  • Rownd compatibility user routes ignore the global email verification claim validator for profile access; secure email changes apply their own checks.

Email Changes

When email sign-in is configured, changing the profile email starts a verified Passwordless email change for the initiating tenant. After verification, the plugin creates a Passwordless email method or reuses one already linked to the same primary user in that tenant. Existing Passwordless email and phone methods remain unchanged, so previous email addresses continue to work as login aliases. For accounts containing only real third-party methods, the plugin creates and links the first Passwordless method after verification. Guest/instant-only accounts and unsupported mixed-account topologies are rejected. Configure the maximum age of the initiating SuperTokens session:

RowndMigrationPlugin(
    rownd_app_key="rownd_app_key",
    rownd_app_secret="rownd_app_secret",
    app_config={"signInMethods": [{"method": "email"}]},
    email_change={"max_session_age_seconds": 600},
)

The flow requires Passwordless, EmailVerification, and AccountLinking. It rejects stale sessions, checks target ownership across all tenants, and binds pending verification metadata to the initiating user, session, tenant, purpose, and status before consuming the Core token. Completion revokes all account sessions and returns a replacement session. The tenant's canonical email method is tracked separately from its login aliases. Existing metadata using rownd_email_recipe_user_id remains supported; new updates also maintain the tenant-scoped rownd_email_recipe_user_ids map.

Successful profile or field updates that start verification return email_verification_pending: true. Until verification completes, the returned profile continues to expose the current canonical email.

Native clients using rowndDisplayContext: "mobile_app" must send rowndNativeEmailVerification: true in the request context. Older clients receive HTTP 426 before metadata or email-delivery side effects. Only validated display, client-domain, and native-capability values are propagated; request-provided redirect paths are ignored. This applies to both PUT /plugin/rownd/user and PUT /plugin/rownd/user/field.

Pending email-change links retain the raw SuperTokens token and add rowndPendingVerificationId. Custom email delivery must preserve both parameters. The marker selects the profile-change flow and requires the initiating session. Unmarked verification remains ordinary SuperTokens verification and is session-optional; removing the marker can therefore consume the raw token without completing the credential change. Concurrent duplicate consumption allows at most one completion. Failed completion and replacement-session creation are compensated; rollback failures require account reconciliation.

Passwordless Confirmation Bypass

Use create_magic_link_with_confirmation_bypass when your backend needs to create a passwordless magic link that can be opened on a different device without showing the SuperTokens cross-device confirmation prompt. This is intended for trusted server-side flows only.

First, configure the exact post-login paths that may use the bypass:

from supertokens_rownd import RowndPluginConfig

rownd_plugin_config = RowndPluginConfig(
    rownd_app_key="rownd_app_key",
    rownd_app_secret="rownd_app_secret",
    api_base_path="/auth",
    api_domain="https://api.example.com",
    website_domain="https://example.com",
    client_domains={"browser": "https://app.example.com"},
    cross_device_confirmation_bypass={
        "allowed_redirect_paths": ["/profile", "/settings/security"],
    },
)

Then call the helper from your backend after SuperTokens has been initialized with the Rownd plugin:

from supertokens_rownd import create_magic_link_with_confirmation_bypass

magic_link = await create_magic_link_with_confirmation_bypass(
    email="user@example.com",
    client_domain="browser",
    redirect_to_path="/profile",
    display_context="browser",
)

redirect_to_path is required and must match cross_device_confirmation_bypass.allowed_redirect_paths exactly after normalization. Absolute URLs are accepted only when their origin matches the resolved client_domain; they are normalized back to a relative path before being added to the magic link.

client_domain must be a configured client_domains key, not a raw domain. Omit it to use website_domain.

Pass exactly one of email or phone_number. The helper returns the rewritten magic link with bypassDeviceConfirmation=true.

Before skipping the cross-device confirmation prompt, the frontend should validate the callback against the plugin:

  • POST /plugin/passwordless-cross-device-confirmation/validate
  • Body: { "clientDomain": "browser", "redirectToPath": "/profile", "appVariantId": "optional_variant" }
  • Success response: { "status": "OK", "bypass": true }

If validation fails, the frontend should show the normal cross-device confirmation prompt.

Apple sign-in methods may include SuperTokens client type mapping fields:

"signInMethods": [
    {
        "method": "apple",
        "clientId": "com.example.service",
        "webClientType": "web",
        "iosClientType": "ios",
        "androidClientType": "android",
    }
]

See OAUTH_MIGRATION_TUTORIAL.md for OAuth/OIDC client migration steps.

Notes

The Python SDK plugin API does not currently pass app_info into plugin route construction. Configure api_base_path, api_domain, website_domain, and app_name on the Rownd plugin so it can register routes and rewrite Rownd hub links consistently.

api_base_path must match InputAppInfo.api_base_path. If these differ, Rownd plugin routes are mounted at the Rownd plugin value, not the SuperTokens app value.

api_domain should match InputAppInfo.api_domain. This value is added to rewritten Rownd hub links so browser and mobile flows can call back to the correct API domain.

website_domain should match InputAppInfo.website_domain. It is required when create_magic_link_with_confirmation_bypass is called without client_domain.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

supertokens_rownd-0.1.12.tar.gz (82.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

supertokens_rownd-0.1.12-py3-none-any.whl (44.3 kB view details)

Uploaded Python 3

File details

Details for the file supertokens_rownd-0.1.12.tar.gz.

File metadata

  • Download URL: supertokens_rownd-0.1.12.tar.gz
  • Upload date:
  • Size: 82.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for supertokens_rownd-0.1.12.tar.gz
Algorithm Hash digest
SHA256 eef2671bc6f8cd406a946b61642aa47fc46d12a7f477aeeca9052232f564486e
MD5 71ba11b50b37a26be13064de572400ce
BLAKE2b-256 ac16e4e0b7ab631d457fecdb07e0665793183dc8ab96bae0e098a5e00fd3fa76

See more details on using hashes here.

File details

Details for the file supertokens_rownd-0.1.12-py3-none-any.whl.

File metadata

  • Download URL: supertokens_rownd-0.1.12-py3-none-any.whl
  • Upload date:
  • Size: 44.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for supertokens_rownd-0.1.12-py3-none-any.whl
Algorithm Hash digest
SHA256 b8404a699b01fbccbab17979811831fa236c09c25e97e055658449f82f5055af
MD5 2b8a2d043cfe81e3e67ee4b0c15828b2
BLAKE2b-256 fd9a369037b1444e44bc40e2140590ebca3e01a2de44c847b69f967fe084ec18

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.1

2 files

0.2.0

2 files

0.1.13

2 files

This release

0.1.12 This release

2 files

0.1.11

2 files

0.1.10

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page