diff --git a/v2/community/database-setup/mysql.mdx b/v2/community/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/community/database-setup/mysql.mdx +++ b/v2/community/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/community/database-setup/postgresql.mdx b/v2/community/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/community/database-setup/postgresql.mdx +++ b/v2/community/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/community/sdks.mdx b/v2/community/sdks.mdx index 55ad26806..d5c8770a5 100644 --- a/v2/community/sdks.mdx +++ b/v2/community/sdks.mdx @@ -60,6 +60,10 @@ import GuidesLink from "/src/components/guidesLink" - SuperTokens provides React based pre-built UI components, for other frontend frameworks you will need to build custom UI and use the `supertokens-web-js` SDK to communicate with the APIs exposed by the SuperTokens backend SDK. - For other backend frameworks, you can follow our [guide on how to spin up a separate server configured with the SuperTokens backend SDK](/docs/community/other-frameworks) to authenticate requests and issue session tokens. +## SDK Migration + +See the [updating SuperTokens](./updating-supertokens) page for steps on how to migrate SDKs. + :::info Visit the [API reference page](./apis) to learn more. ::: \ No newline at end of file diff --git a/v2/community/supertokens-core/self-hosted/self-hosted-with-aws.mdx b/v2/community/supertokens-core/self-hosted/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/community/supertokens-core/self-hosted/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/community/updating-supertokens.mdx b/v2/community/updating-supertokens.mdx new file mode 100644 index 000000000..ad5a2ee0d --- /dev/null +++ b/v2/community/updating-supertokens.mdx @@ -0,0 +1,65 @@ +--- +id: updating-supertokens +title: Updating Supertokens core and SDKs +hide_title: true +--- + + + + +# Updating SuperTokens core and SDKs + +:::important +You need to follow these steps in order to properly update supertokens +::: + +In order to maintain compatibility and keep up on new features, we recommend updating your core and SDKs whenever possible. + +## 1. Updating your core + +You will need to shut down your core in order to update it. After it's off, run the migration scripts for all versions inbetween +your starting version and the latest version. You may then bring your core back online. + +In the rare occasion that the supertokens core version you have updated to shows as incompatible with your current front-end and +back-end sdk's in the [compatibility table](./compatibility-table), then refrain from running your back-end and front-end SDKs until after you update them. + +- ### Self-hosted core +See the migration sections in the [supertokens-core changelog](https://github.com/supertokens/supertokens-core/blob/master/CHANGELOG.md). + +- ### Managed core +If you're using the managed core service, please email us at team@supertokens.com from your registered email to request a core update. + +## 2. Update your back-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### NodeJS +See the migration sections in the [supertokens-node changelog](https://github.com/supertokens/supertokens-node/blob/master/CHANGELOG.md). + +- ### GoLang +See the migration sections in the [supertokens-golang changelog](https://github.com/supertokens/supertokens-golang/blob/master/CHANGELOG.md). + +- ### Python +See the migration sections in the [supertokens-python changelog](https://github.com/supertokens/supertokens-python/blob/master/CHANGELOG.md). + +## 3. Update your front-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### ReactJS +See the migration sections in the [supertokens-auth-react changelog](https://github.com/supertokens/supertokens-auth-react/blob/master/CHANGELOG.md). + +- ### Vanilla JS +See the migration sections in the [supertokens-web-js changelog](https://github.com/supertokens/supertokens-web-js/blob/master/CHANGELOG.md). + +- ### React Native +See the migration sections in the [supertokens-react-native changelog](https://github.com/supertokens/supertokens-react-native/blob/master/CHANGELOG.md). + +- ### iOS +See the migration sections in the [supertokens-ios changelog](https://github.com/supertokens/supertokens-ios/blob/master/CHANGELOG.md). + +- ### Flutter +See the migration sections in the [supertokens-flutter changelog](https://github.com/supertokens/supertokens-flutter/blob/master/CHANGELOG.md). + +- ### Android +See the migration sections in the [supertokens-android changelog](https://github.com/supertokens/supertokens-android/blob/master/CHANGELOG.md). \ No newline at end of file diff --git a/v2/contribute/checklists/saas/upgrading-users-core-version.md b/v2/contribute/checklists/saas/upgrading-users-core-version.md index 0f1cef44a..ee2d8ee31 100644 --- a/v2/contribute/checklists/saas/upgrading-users-core-version.md +++ b/v2/contribute/checklists/saas/upgrading-users-core-version.md @@ -6,1054 +6,4 @@ hide_title: true # Upgrading user's core version -- Tables to update: - - apps (update core_version, plugin_interface_versio and plugin_version) - - aws_containers (update image_version) -- System Manager: - - Find instance id - - Find StartUpdateSuperTokens command for relevant app - - Copy to new - - Change imageVersion parameter - - Make sure the Document version is relevant to the new core version - - Run command and check the container is updated and running - -# Core DB Migration - -### 3.3 to 3.4 -- No change - -### 3.4 to 3.5 -- Change `user_id` in `emailverification_verified_emails` to `VARCHAR(128)` -- Change `user_id` in `emailverification_tokens` to `VARCHAR(128)` -- Add new table (use the db_user associated with user's core or remember to change the owner of the new tables to db_user): - ``` - CREATE TABLE IF NOT EXISTS all_auth_recipe_users( - user_id CHAR(36) NOT NULL, - recipe_id VARCHAR(128) NOT NULL, - time_joined BIGINT NOT NULL, - PRIMARY KEY (user_id) - ); - CREATE INDEX all_auth_recipe_users_pagination_index ON all_auth_recipe_users (time_joined DESC, user_id DESC); - ``` - This means that the content from other `emailpassword_users` and from `thirdparty_users` need to be copied into this table -- Deleted index `emailpassword_user_pagination_index` and `thirdparty_users_pagination_index` - -### 3.5 to 3.6 -- No manual change required - -### 3.6 to 3.7 -- No manual change required - -### 3.7 to 3.8 -- No manual change required -- Adds new tables for passwordless (is added automatically): - - `passwordless_users` that stores the users of the passwordless recipe - - `passwordless_devices` that stores devices/information about passwordless login attempts - - `passwordless_codes` that stores the codes each device can consume to finish the login process - -### 3.8 to 3.9 -- No manual change required - -### 3.9 to 3.10 -- No manual change required - -### 3.10 to 3.11 -- No manual change required - -### 3.11 to 3.12 -- No manual change required - -### 3.12 to 3.13 -- No manual change required - -### 3.13 to 3.14 -- No manual change required - -### 3.14 to 3.15 -- No manual change required - -### 3.15 to 3.16 -- No manual change required - -### 3.16 to 4.0 -- Run: `ALTER TABLE thirdparty_users ALTER COLUMN third_party_user_id TYPE VARCHAR(256); ALTER TABLE emailpassword_users ALTER COLUMN password_hash TYPE VARCHAR(256);` - -### 4.0 to 4.1 -- No manual change required - -### 4.1 to 4.2 -- No manual change required - -### 4.2 to 4.3 -- No manual change required - -### 4.3 to 4.4 -- No manual change required - -### 4.4 to 4.5 -- No manual change required - -### 4.5 to 4.6 -- No manual change required - -### 4.6 to 5.0 -- Renamed `access_token_signing_key_update_interval` to `access_token_dynamic_signing_key_update_interval` in config -- If `access_token_signing_key_dynamic` is currently set to `false` then run: - ```sql - ALTER TABLE session_info ADD COLUMN use_static_key BOOLEAN NOT NULL DEFAULT(true); - ALTER TABLE session_info ALTER COLUMN use_static_key DROP DEFAULT; - INSERT INTO jwt_signing_keys(key_id, key_string, algorithm, created_at) - select CONCAT('s-', created_at_time) as key_id, value as key_string, 'RS256' as algorithm, created_at_time as created_at - from session_access_token_signing_keys; - ``` -- If `access_token_signing_key_dynamic` is currently set to `true`, or it not set at all: - ```sql - ALTER TABLE session_info ADD COLUMN use_static_key BOOLEAN NOT NULL DEFAULT(false); - ALTER TABLE session_info ALTER COLUMN use_static_key DROP DEFAULT; - ``` - -### 5.0 to 6.0 -- Follow these steps: https://github.com/supertokens/backend/issues/275#issuecomment-1647547145 -- Use the following migration script -```sql --- General Tables - -CREATE TABLE IF NOT EXISTS apps ( - app_id VARCHAR(64) NOT NULL DEFAULT 'public', - created_at_time BIGINT, - CONSTRAINT apps_pkey PRIMARY KEY(app_id) -); - -INSERT INTO apps (app_id, created_at_time) - VALUES ('public', 0) ON CONFLICT DO NOTHING; - ------------------------------------------------------------- - -CREATE TABLE IF NOT EXISTS tenants ( - app_id VARCHAR(64) NOT NULL DEFAULT 'public', - tenant_id VARCHAR(64) NOT NULL DEFAULT 'public', - created_at_time BIGINT , - CONSTRAINT tenants_pkey - PRIMARY KEY (app_id, tenant_id), - CONSTRAINT tenants_app_id_fkey FOREIGN KEY(app_id) - REFERENCES apps (app_id) ON DELETE CASCADE -); - -INSERT INTO tenants (app_id, tenant_id, created_at_time) - VALUES ('public', 'public', 0) ON CONFLICT DO NOTHING; - -CREATE INDEX IF NOT EXISTS tenants_app_id_index ON tenants (app_id); - ------------------------------------------------------------- - -ALTER TABLE key_value - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public', - ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE key_value - DROP CONSTRAINT key_value_pkey; - -ALTER TABLE key_value - ADD CONSTRAINT key_value_pkey - PRIMARY KEY (app_id, tenant_id, name); - -ALTER TABLE key_value - DROP CONSTRAINT IF EXISTS key_value_tenant_id_fkey; - -ALTER TABLE key_value - ADD CONSTRAINT key_value_tenant_id_fkey - FOREIGN KEY (app_id, tenant_id) - REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS key_value_tenant_id_index ON key_value (app_id, tenant_id); - ------------------------------------------------------------- - -CREATE TABLE IF NOT EXISTS app_id_to_user_id ( - app_id VARCHAR(64) NOT NULL DEFAULT 'public', - user_id CHAR(36) NOT NULL, - recipe_id VARCHAR(128) NOT NULL, - CONSTRAINT app_id_to_user_id_pkey - PRIMARY KEY (app_id, user_id), - CONSTRAINT app_id_to_user_id_app_id_fkey - FOREIGN KEY(app_id) REFERENCES apps (app_id) ON DELETE CASCADE -); - -INSERT INTO app_id_to_user_id (user_id, recipe_id) - SELECT user_id, recipe_id - FROM all_auth_recipe_users ON CONFLICT DO NOTHING; - -CREATE INDEX IF NOT EXISTS app_id_to_user_id_app_id_index ON app_id_to_user_id (app_id); - ------------------------------------------------------------- - -ALTER TABLE all_auth_recipe_users - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public', - ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE all_auth_recipe_users - DROP CONSTRAINT all_auth_recipe_users_pkey CASCADE; - -ALTER TABLE all_auth_recipe_users - ADD CONSTRAINT all_auth_recipe_users_pkey - PRIMARY KEY (app_id, tenant_id, user_id); - -ALTER TABLE all_auth_recipe_users - DROP CONSTRAINT IF EXISTS all_auth_recipe_users_tenant_id_fkey; - -ALTER TABLE all_auth_recipe_users - ADD CONSTRAINT all_auth_recipe_users_tenant_id_fkey - FOREIGN KEY (app_id, tenant_id) - REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; - -ALTER TABLE all_auth_recipe_users - DROP CONSTRAINT IF EXISTS all_auth_recipe_users_user_id_fkey; - -ALTER TABLE all_auth_recipe_users - ADD CONSTRAINT all_auth_recipe_users_user_id_fkey - FOREIGN KEY (app_id, user_id) - REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; - -DROP INDEX all_auth_recipe_users_pagination_index; - -CREATE INDEX all_auth_recipe_users_pagination_index ON all_auth_recipe_users (time_joined DESC, user_id DESC, tenant_id DESC, app_id DESC); - -CREATE INDEX IF NOT EXISTS all_auth_recipe_user_id_index ON all_auth_recipe_users (app_id, user_id); - -CREATE INDEX IF NOT EXISTS all_auth_recipe_tenant_id_index ON all_auth_recipe_users (app_id, tenant_id); - --- Multitenancy - -CREATE TABLE IF NOT EXISTS tenant_configs ( - connection_uri_domain VARCHAR(256) DEFAULT '', - app_id VARCHAR(64) DEFAULT 'public', - tenant_id VARCHAR(64) DEFAULT 'public', - core_config TEXT, - email_password_enabled BOOLEAN, - passwordless_enabled BOOLEAN, - third_party_enabled BOOLEAN, - CONSTRAINT tenant_configs_pkey - PRIMARY KEY (connection_uri_domain, app_id, tenant_id) -); - ------------------------------------------------------------- - -CREATE TABLE IF NOT EXISTS tenant_thirdparty_providers ( - connection_uri_domain VARCHAR(256) DEFAULT '', - app_id VARCHAR(64) DEFAULT 'public', - tenant_id VARCHAR(64) DEFAULT 'public', - third_party_id VARCHAR(28) NOT NULL, - name VARCHAR(64), - authorization_endpoint TEXT, - authorization_endpoint_query_params TEXT, - token_endpoint TEXT, - token_endpoint_body_params TEXT, - user_info_endpoint TEXT, - user_info_endpoint_query_params TEXT, - user_info_endpoint_headers TEXT, - jwks_uri TEXT, - oidc_discovery_endpoint TEXT, - require_email BOOLEAN, - user_info_map_from_id_token_payload_user_id VARCHAR(64), - user_info_map_from_id_token_payload_email VARCHAR(64), - user_info_map_from_id_token_payload_email_verified VARCHAR(64), - user_info_map_from_user_info_endpoint_user_id VARCHAR(64), - user_info_map_from_user_info_endpoint_email VARCHAR(64), - user_info_map_from_user_info_endpoint_email_verified VARCHAR(64), - CONSTRAINT tenant_thirdparty_providers_pkey - PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id), - CONSTRAINT tenant_thirdparty_providers_tenant_id_fkey - FOREIGN KEY(connection_uri_domain, app_id, tenant_id) - REFERENCES tenant_configs (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE -); - -CREATE INDEX IF NOT EXISTS tenant_thirdparty_providers_tenant_id_index ON tenant_thirdparty_providers (connection_uri_domain, app_id, tenant_id); - ------------------------------------------------------------- - -CREATE TABLE IF NOT EXISTS tenant_thirdparty_provider_clients ( - connection_uri_domain VARCHAR(256) DEFAULT '', - app_id VARCHAR(64) DEFAULT 'public', - tenant_id VARCHAR(64) DEFAULT 'public', - third_party_id VARCHAR(28) NOT NULL, - client_type VARCHAR(64) NOT NULL DEFAULT '', - client_id VARCHAR(256) NOT NULL, - client_secret TEXT, - scope VARCHAR(128)[], - force_pkce BOOLEAN, - additional_config TEXT, - CONSTRAINT tenant_thirdparty_provider_clients_pkey - PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id, client_type), - CONSTRAINT tenant_thirdparty_provider_clients_third_party_id_fkey - FOREIGN KEY (connection_uri_domain, app_id, tenant_id, third_party_id) - REFERENCES tenant_thirdparty_providers (connection_uri_domain, app_id, tenant_id, third_party_id) ON DELETE CASCADE -); - -CREATE INDEX IF NOT EXISTS tenant_thirdparty_provider_clients_third_party_id_index ON tenant_thirdparty_provider_clients (connection_uri_domain, app_id, tenant_id, third_party_id); - --- Session - -ALTER TABLE session_info - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public', - ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE session_info - DROP CONSTRAINT session_info_pkey CASCADE; - -ALTER TABLE session_info - ADD CONSTRAINT session_info_pkey - PRIMARY KEY (app_id, tenant_id, session_handle); - -ALTER TABLE session_info - DROP CONSTRAINT IF EXISTS session_info_tenant_id_fkey; - -ALTER TABLE session_info - ADD CONSTRAINT session_info_tenant_id_fkey - FOREIGN KEY (app_id, tenant_id) - REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS session_expiry_index ON session_info (expires_at); - -CREATE INDEX IF NOT EXISTS session_info_tenant_id_index ON session_info (app_id, tenant_id); - ------------------------------------------------------------- - -ALTER TABLE session_access_token_signing_keys - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE session_access_token_signing_keys - DROP CONSTRAINT session_access_token_signing_keys_pkey CASCADE; - -ALTER TABLE session_access_token_signing_keys - ADD CONSTRAINT session_access_token_signing_keys_pkey - PRIMARY KEY (app_id, created_at_time); - -ALTER TABLE session_access_token_signing_keys - DROP CONSTRAINT IF EXISTS session_access_token_signing_keys_app_id_fkey; - -ALTER TABLE session_access_token_signing_keys - ADD CONSTRAINT session_access_token_signing_keys_app_id_fkey - FOREIGN KEY (app_id) - REFERENCES apps (app_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS access_token_signing_keys_app_id_index ON session_access_token_signing_keys (app_id); - --- JWT - -ALTER TABLE jwt_signing_keys - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE jwt_signing_keys - DROP CONSTRAINT jwt_signing_keys_pkey CASCADE; - -ALTER TABLE jwt_signing_keys - ADD CONSTRAINT jwt_signing_keys_pkey - PRIMARY KEY (app_id, key_id); - -ALTER TABLE jwt_signing_keys - DROP CONSTRAINT IF EXISTS jwt_signing_keys_app_id_fkey; - -ALTER TABLE jwt_signing_keys - ADD CONSTRAINT jwt_signing_keys_app_id_fkey - FOREIGN KEY (app_id) - REFERENCES apps (app_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS jwt_signing_keys_app_id_index ON jwt_signing_keys (app_id); - --- EmailVerification - -ALTER TABLE emailverification_verified_emails - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE emailverification_verified_emails - DROP CONSTRAINT emailverification_verified_emails_pkey CASCADE; - -ALTER TABLE emailverification_verified_emails - ADD CONSTRAINT emailverification_verified_emails_pkey - PRIMARY KEY (app_id, user_id, email); - -ALTER TABLE emailverification_verified_emails - DROP CONSTRAINT IF EXISTS emailverification_verified_emails_app_id_fkey; - -ALTER TABLE emailverification_verified_emails - ADD CONSTRAINT emailverification_verified_emails_app_id_fkey - FOREIGN KEY (app_id) - REFERENCES apps (app_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS emailverification_verified_emails_app_id_index ON emailverification_verified_emails (app_id); - ------------------------------------------------------------- - -ALTER TABLE emailverification_tokens - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public', - ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE emailverification_tokens - DROP CONSTRAINT emailverification_tokens_pkey CASCADE; - -ALTER TABLE emailverification_tokens - ADD CONSTRAINT emailverification_tokens_pkey - PRIMARY KEY (app_id, tenant_id, user_id, email, token); - -ALTER TABLE emailverification_tokens - DROP CONSTRAINT IF EXISTS emailverification_tokens_tenant_id_fkey; - -ALTER TABLE emailverification_tokens - ADD CONSTRAINT emailverification_tokens_tenant_id_fkey - FOREIGN KEY (app_id, tenant_id) - REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS emailverification_tokens_tenant_id_index ON emailverification_tokens (app_id, tenant_id); - --- EmailPassword - -ALTER TABLE emailpassword_users - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE emailpassword_users - DROP CONSTRAINT emailpassword_users_pkey CASCADE; - -ALTER TABLE emailpassword_users - DROP CONSTRAINT IF EXISTS emailpassword_users_email_key CASCADE; - -ALTER TABLE emailpassword_users - ADD CONSTRAINT emailpassword_users_pkey - PRIMARY KEY (app_id, user_id); - -ALTER TABLE emailpassword_users - DROP CONSTRAINT IF EXISTS emailpassword_users_user_id_fkey; - -ALTER TABLE emailpassword_users - ADD CONSTRAINT emailpassword_users_user_id_fkey - FOREIGN KEY (app_id, user_id) - REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; - ------------------------------------------------------------- - -CREATE TABLE IF NOT EXISTS emailpassword_user_to_tenant ( - app_id VARCHAR(64) DEFAULT 'public', - tenant_id VARCHAR(64) DEFAULT 'public', - user_id CHAR(36) NOT NULL, - email VARCHAR(256) NOT NULL, - CONSTRAINT emailpassword_user_to_tenant_email_key - UNIQUE (app_id, tenant_id, email), - CONSTRAINT emailpassword_user_to_tenant_pkey - PRIMARY KEY (app_id, tenant_id, user_id), - CONSTRAINT emailpassword_user_to_tenant_user_id_fkey - FOREIGN KEY (app_id, tenant_id, user_id) - REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE -); - -ALTER TABLE emailpassword_user_to_tenant - DROP CONSTRAINT IF EXISTS emailpassword_user_to_tenant_email_key; - -ALTER TABLE emailpassword_user_to_tenant - ADD CONSTRAINT emailpassword_user_to_tenant_email_key - UNIQUE (app_id, tenant_id, email); - -ALTER TABLE emailpassword_user_to_tenant - DROP CONSTRAINT IF EXISTS emailpassword_user_to_tenant_user_id_fkey; - -ALTER TABLE emailpassword_user_to_tenant - ADD CONSTRAINT emailpassword_user_to_tenant_user_id_fkey - FOREIGN KEY (app_id, tenant_id, user_id) - REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE; - -INSERT INTO emailpassword_user_to_tenant (user_id, email) - SELECT user_id, email FROM emailpassword_users ON CONFLICT DO NOTHING; - ------------------------------------------------------------- - -ALTER TABLE emailpassword_pswd_reset_tokens - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE emailpassword_pswd_reset_tokens - DROP CONSTRAINT emailpassword_pswd_reset_tokens_pkey CASCADE; - -ALTER TABLE emailpassword_pswd_reset_tokens - ADD CONSTRAINT emailpassword_pswd_reset_tokens_pkey - PRIMARY KEY (app_id, user_id, token); - -ALTER TABLE emailpassword_pswd_reset_tokens - DROP CONSTRAINT IF EXISTS emailpassword_pswd_reset_tokens_user_id_fkey; - -ALTER TABLE emailpassword_pswd_reset_tokens - ADD CONSTRAINT emailpassword_pswd_reset_tokens_user_id_fkey - FOREIGN KEY (app_id, user_id) - REFERENCES emailpassword_users (app_id, user_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS emailpassword_pswd_reset_tokens_user_id_index ON emailpassword_pswd_reset_tokens (app_id, user_id); - --- Passwordless - -ALTER TABLE passwordless_users - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE passwordless_users - DROP CONSTRAINT passwordless_users_pkey CASCADE; - -ALTER TABLE passwordless_users - ADD CONSTRAINT passwordless_users_pkey - PRIMARY KEY (app_id, user_id); - -ALTER TABLE passwordless_users - DROP CONSTRAINT IF EXISTS passwordless_users_email_key; - -ALTER TABLE passwordless_users - DROP CONSTRAINT IF EXISTS passwordless_users_phone_number_key; - -ALTER TABLE passwordless_users - DROP CONSTRAINT IF EXISTS passwordless_users_user_id_fkey; - -ALTER TABLE passwordless_users - ADD CONSTRAINT passwordless_users_user_id_fkey - FOREIGN KEY (app_id, user_id) - REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; - ------------------------------------------------------------- - -CREATE TABLE IF NOT EXISTS passwordless_user_to_tenant ( - app_id VARCHAR(64) DEFAULT 'public', - tenant_id VARCHAR(64) DEFAULT 'public', - user_id CHAR(36) NOT NULL, - email VARCHAR(256), - phone_number VARCHAR(256), - CONSTRAINT passwordless_user_to_tenant_email_key - UNIQUE (app_id, tenant_id, email), - CONSTRAINT passwordless_user_to_tenant_phone_number_key - UNIQUE (app_id, tenant_id, phone_number), - CONSTRAINT passwordless_user_to_tenant_pkey - PRIMARY KEY (app_id, tenant_id, user_id), - CONSTRAINT passwordless_user_to_tenant_user_id_fkey - FOREIGN KEY (app_id, tenant_id, user_id) - REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE -); - -ALTER TABLE passwordless_user_to_tenant - DROP CONSTRAINT IF EXISTS passwordless_user_to_tenant_user_id_fkey; - -ALTER TABLE passwordless_user_to_tenant - ADD CONSTRAINT passwordless_user_to_tenant_user_id_fkey - FOREIGN KEY (app_id, tenant_id, user_id) - REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE; - -INSERT INTO passwordless_user_to_tenant (user_id, email, phone_number) - SELECT user_id, email, phone_number FROM passwordless_users ON CONFLICT DO NOTHING; - ------------------------------------------------------------- - -ALTER TABLE passwordless_devices - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public', - ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE passwordless_devices - DROP CONSTRAINT passwordless_devices_pkey CASCADE; - -ALTER TABLE passwordless_devices - ADD CONSTRAINT passwordless_devices_pkey - PRIMARY KEY (app_id, tenant_id, device_id_hash); - -ALTER TABLE passwordless_devices - DROP CONSTRAINT IF EXISTS passwordless_devices_tenant_id_fkey; - -ALTER TABLE passwordless_devices - ADD CONSTRAINT passwordless_devices_tenant_id_fkey - FOREIGN KEY (app_id, tenant_id) - REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; - -DROP INDEX IF EXISTS passwordless_devices_email_index; - -CREATE INDEX IF NOT EXISTS passwordless_devices_email_index ON passwordless_devices (app_id, tenant_id, email); - -DROP INDEX IF EXISTS passwordless_devices_phone_number_index; - -CREATE INDEX IF NOT EXISTS passwordless_devices_phone_number_index ON passwordless_devices (app_id, tenant_id, phone_number); - -CREATE INDEX IF NOT EXISTS passwordless_devices_tenant_id_index ON passwordless_devices (app_id, tenant_id); - ------------------------------------------------------------- - -ALTER TABLE passwordless_codes - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public', - ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE passwordless_codes - DROP CONSTRAINT passwordless_codes_pkey CASCADE; - -ALTER TABLE passwordless_codes - ADD CONSTRAINT passwordless_codes_pkey - PRIMARY KEY (app_id, tenant_id, code_id); - -ALTER TABLE passwordless_codes - DROP CONSTRAINT IF EXISTS passwordless_codes_device_id_hash_fkey; - -ALTER TABLE passwordless_codes - ADD CONSTRAINT passwordless_codes_device_id_hash_fkey - FOREIGN KEY (app_id, tenant_id, device_id_hash) - REFERENCES passwordless_devices (app_id, tenant_id, device_id_hash) ON DELETE CASCADE; - -ALTER TABLE passwordless_codes - DROP CONSTRAINT passwordless_codes_link_code_hash_key; - -ALTER TABLE passwordless_codes - DROP CONSTRAINT IF EXISTS passwordless_codes_link_code_hash_key; - -ALTER TABLE passwordless_codes - ADD CONSTRAINT passwordless_codes_link_code_hash_key - UNIQUE (app_id, tenant_id, link_code_hash); - -DROP INDEX IF EXISTS passwordless_codes_created_at_index; - -CREATE INDEX IF NOT EXISTS passwordless_codes_created_at_index ON passwordless_codes (app_id, tenant_id, created_at); - -DROP INDEX IF EXISTS passwordless_codes_device_id_hash_index; -CREATE INDEX IF NOT EXISTS passwordless_codes_device_id_hash_index ON passwordless_codes (app_id, tenant_id, device_id_hash); - --- ThirdParty - -ALTER TABLE thirdparty_users - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE thirdparty_users - DROP CONSTRAINT thirdparty_users_pkey CASCADE; - -ALTER TABLE thirdparty_users - DROP CONSTRAINT IF EXISTS thirdparty_users_user_id_key CASCADE; - -ALTER TABLE thirdparty_users - ADD CONSTRAINT thirdparty_users_pkey - PRIMARY KEY (app_id, user_id); - -ALTER TABLE thirdparty_users - DROP CONSTRAINT IF EXISTS thirdparty_users_user_id_fkey; - -ALTER TABLE thirdparty_users - ADD CONSTRAINT thirdparty_users_user_id_fkey - FOREIGN KEY (app_id, user_id) - REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; - -DROP INDEX IF EXISTS thirdparty_users_thirdparty_user_id_index; - -CREATE INDEX IF NOT EXISTS thirdparty_users_thirdparty_user_id_index ON thirdparty_users (app_id, third_party_id, third_party_user_id); - -DROP INDEX IF EXISTS thirdparty_users_email_index; - -CREATE INDEX IF NOT EXISTS thirdparty_users_email_index ON thirdparty_users (app_id, email); - ------------------------------------------------------------- - -CREATE TABLE IF NOT EXISTS thirdparty_user_to_tenant ( - app_id VARCHAR(64) DEFAULT 'public', - tenant_id VARCHAR(64) DEFAULT 'public', - user_id CHAR(36) NOT NULL, - third_party_id VARCHAR(28) NOT NULL, - third_party_user_id VARCHAR(256) NOT NULL, - CONSTRAINT thirdparty_user_to_tenant_third_party_user_id_key - UNIQUE (app_id, tenant_id, third_party_id, third_party_user_id), - CONSTRAINT thirdparty_user_to_tenant_pkey - PRIMARY KEY (app_id, tenant_id, user_id), - CONSTRAINT thirdparty_user_to_tenant_user_id_fkey - FOREIGN KEY (app_id, tenant_id, user_id) - REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE -); - -ALTER TABLE thirdparty_user_to_tenant - DROP CONSTRAINT IF EXISTS thirdparty_user_to_tenant_third_party_user_id_key; - -ALTER TABLE thirdparty_user_to_tenant - ADD CONSTRAINT thirdparty_user_to_tenant_third_party_user_id_key - UNIQUE (app_id, tenant_id, third_party_id, third_party_user_id); - -ALTER TABLE thirdparty_user_to_tenant - DROP CONSTRAINT IF EXISTS thirdparty_user_to_tenant_user_id_fkey; - -ALTER TABLE thirdparty_user_to_tenant - ADD CONSTRAINT thirdparty_user_to_tenant_user_id_fkey - FOREIGN KEY (app_id, tenant_id, user_id) - REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE; - -INSERT INTO thirdparty_user_to_tenant (user_id, third_party_id, third_party_user_id) - SELECT user_id, third_party_id, third_party_user_id FROM thirdparty_users ON CONFLICT DO NOTHING; - --- UserIdMapping - -ALTER TABLE userid_mapping - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE userid_mapping - DROP CONSTRAINT IF EXISTS userid_mapping_pkey CASCADE; - -ALTER TABLE userid_mapping - ADD CONSTRAINT userid_mapping_pkey - PRIMARY KEY (app_id, supertokens_user_id, external_user_id); - -ALTER TABLE userid_mapping - DROP CONSTRAINT IF EXISTS userid_mapping_supertokens_user_id_key; - -ALTER TABLE userid_mapping - ADD CONSTRAINT userid_mapping_supertokens_user_id_key - UNIQUE (app_id, supertokens_user_id); - -ALTER TABLE userid_mapping - DROP CONSTRAINT IF EXISTS userid_mapping_external_user_id_key; - -ALTER TABLE userid_mapping - ADD CONSTRAINT userid_mapping_external_user_id_key - UNIQUE (app_id, external_user_id); - -ALTER TABLE userid_mapping - DROP CONSTRAINT IF EXISTS userid_mapping_supertokens_user_id_fkey; - -ALTER TABLE userid_mapping - ADD CONSTRAINT userid_mapping_supertokens_user_id_fkey - FOREIGN KEY (app_id, supertokens_user_id) - REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS userid_mapping_supertokens_user_id_index ON userid_mapping (app_id, supertokens_user_id); - --- UserRoles - -ALTER TABLE roles - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE roles - DROP CONSTRAINT roles_pkey CASCADE; - -ALTER TABLE roles - ADD CONSTRAINT roles_pkey - PRIMARY KEY (app_id, role); - -ALTER TABLE roles - DROP CONSTRAINT IF EXISTS roles_app_id_fkey; - -ALTER TABLE roles - ADD CONSTRAINT roles_app_id_fkey - FOREIGN KEY (app_id) - REFERENCES apps (app_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS roles_app_id_index ON roles (app_id); - ------------------------------------------------------------- - -ALTER TABLE role_permissions - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE role_permissions - DROP CONSTRAINT role_permissions_pkey CASCADE; - -ALTER TABLE role_permissions - ADD CONSTRAINT role_permissions_pkey - PRIMARY KEY (app_id, role, permission); - -ALTER TABLE role_permissions - DROP CONSTRAINT IF EXISTS role_permissions_role_fkey; - -ALTER TABLE role_permissions - ADD CONSTRAINT role_permissions_role_fkey - FOREIGN KEY (app_id, role) - REFERENCES roles (app_id, role) ON DELETE CASCADE; - -DROP INDEX IF EXISTS role_permissions_permission_index; - -CREATE INDEX IF NOT EXISTS role_permissions_permission_index ON role_permissions (app_id, permission); - -CREATE INDEX IF NOT EXISTS role_permissions_role_index ON role_permissions (app_id, role); - ------------------------------------------------------------- - -ALTER TABLE user_roles - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public', - ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE user_roles - DROP CONSTRAINT user_roles_pkey CASCADE; - -ALTER TABLE user_roles - ADD CONSTRAINT user_roles_pkey - PRIMARY KEY (app_id, tenant_id, user_id, role); - -ALTER TABLE user_roles - DROP CONSTRAINT IF EXISTS user_roles_tenant_id_fkey; - -ALTER TABLE user_roles - ADD CONSTRAINT user_roles_tenant_id_fkey - FOREIGN KEY (app_id, tenant_id) - REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; - -ALTER TABLE user_roles - DROP CONSTRAINT IF EXISTS user_roles_role_fkey; - -ALTER TABLE user_roles - ADD CONSTRAINT user_roles_role_fkey - FOREIGN KEY (app_id, role) - REFERENCES roles (app_id, role) ON DELETE CASCADE; - -DROP INDEX IF EXISTS user_roles_role_index; - -CREATE INDEX IF NOT EXISTS user_roles_role_index ON user_roles (app_id, tenant_id, role); - -CREATE INDEX IF NOT EXISTS user_roles_tenant_id_index ON user_roles (app_id, tenant_id); - -CREATE INDEX IF NOT EXISTS user_roles_app_id_role_index ON user_roles (app_id, role); - --- UserMetadata - -ALTER TABLE user_metadata - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE user_metadata - DROP CONSTRAINT user_metadata_pkey CASCADE; - -ALTER TABLE user_metadata - ADD CONSTRAINT user_metadata_pkey - PRIMARY KEY (app_id, user_id); - -ALTER TABLE user_metadata - DROP CONSTRAINT IF EXISTS user_metadata_app_id_fkey; - -ALTER TABLE user_metadata - ADD CONSTRAINT user_metadata_app_id_fkey - FOREIGN KEY (app_id) - REFERENCES apps (app_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS user_metadata_app_id_index ON user_metadata (app_id); - --- Dashboard - -ALTER TABLE dashboard_users - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE dashboard_users - DROP CONSTRAINT dashboard_users_pkey CASCADE; - -ALTER TABLE dashboard_users - ADD CONSTRAINT dashboard_users_pkey - PRIMARY KEY (app_id, user_id); - -ALTER TABLE dashboard_users - DROP CONSTRAINT IF EXISTS dashboard_users_email_key; - -ALTER TABLE dashboard_users - ADD CONSTRAINT dashboard_users_email_key - UNIQUE (app_id, email); - -ALTER TABLE dashboard_users - DROP CONSTRAINT IF EXISTS dashboard_users_app_id_fkey; - -ALTER TABLE dashboard_users - ADD CONSTRAINT dashboard_users_app_id_fkey - FOREIGN KEY (app_id) - REFERENCES apps (app_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS dashboard_users_app_id_index ON dashboard_users (app_id); - ------------------------------------------------------------- - -ALTER TABLE dashboard_user_sessions - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE dashboard_user_sessions - DROP CONSTRAINT dashboard_user_sessions_pkey CASCADE; - -ALTER TABLE dashboard_user_sessions - ADD CONSTRAINT dashboard_user_sessions_pkey - PRIMARY KEY (app_id, session_id); - -ALTER TABLE dashboard_user_sessions - DROP CONSTRAINT IF EXISTS dashboard_user_sessions_user_id_fkey; - -ALTER TABLE dashboard_user_sessions - ADD CONSTRAINT dashboard_user_sessions_user_id_fkey - FOREIGN KEY (app_id, user_id) - REFERENCES dashboard_users (app_id, user_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS dashboard_user_sessions_user_id_index ON dashboard_user_sessions (app_id, user_id); - --- TOTP - -ALTER TABLE totp_users - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE totp_users - DROP CONSTRAINT totp_users_pkey CASCADE; - -ALTER TABLE totp_users - ADD CONSTRAINT totp_users_pkey - PRIMARY KEY (app_id, user_id); - -ALTER TABLE totp_users - DROP CONSTRAINT IF EXISTS totp_users_app_id_fkey; - -ALTER TABLE totp_users - ADD CONSTRAINT totp_users_app_id_fkey - FOREIGN KEY (app_id) - REFERENCES apps (app_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS totp_users_app_id_index ON totp_users (app_id); - ------------------------------------------------------------- - -ALTER TABLE totp_user_devices - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE totp_user_devices - DROP CONSTRAINT totp_user_devices_pkey; - -ALTER TABLE totp_user_devices - ADD CONSTRAINT totp_user_devices_pkey - PRIMARY KEY (app_id, user_id, device_name); - -ALTER TABLE totp_user_devices - DROP CONSTRAINT IF EXISTS totp_user_devices_user_id_fkey; - -ALTER TABLE totp_user_devices - ADD CONSTRAINT totp_user_devices_user_id_fkey - FOREIGN KEY (app_id, user_id) - REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS totp_user_devices_user_id_index ON totp_user_devices (app_id, user_id); - ------------------------------------------------------------- - -ALTER TABLE totp_used_codes - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public', - ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE totp_used_codes - DROP CONSTRAINT totp_used_codes_pkey CASCADE; - -ALTER TABLE totp_used_codes - ADD CONSTRAINT totp_used_codes_pkey - PRIMARY KEY (app_id, tenant_id, user_id, created_time_ms); - -ALTER TABLE totp_used_codes - DROP CONSTRAINT IF EXISTS totp_used_codes_user_id_fkey; - -ALTER TABLE totp_used_codes - ADD CONSTRAINT totp_used_codes_user_id_fkey - FOREIGN KEY (app_id, user_id) - REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE; - -ALTER TABLE totp_used_codes - DROP CONSTRAINT IF EXISTS totp_used_codes_tenant_id_fkey; - -ALTER TABLE totp_used_codes - ADD CONSTRAINT totp_used_codes_tenant_id_fkey - FOREIGN KEY (app_id, tenant_id) - REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; - -DROP INDEX IF EXISTS totp_used_codes_expiry_time_ms_index; - -CREATE INDEX IF NOT EXISTS totp_used_codes_expiry_time_ms_index ON totp_used_codes (app_id, tenant_id, expiry_time_ms); - -CREATE INDEX IF NOT EXISTS totp_used_codes_user_id_index ON totp_used_codes (app_id, user_id); - -CREATE INDEX IF NOT EXISTS totp_used_codes_tenant_id_index ON totp_used_codes (app_id, tenant_id); - --- ActiveUsers - -ALTER TABLE user_last_active - ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public'; - -ALTER TABLE user_last_active - DROP CONSTRAINT user_last_active_pkey CASCADE; - -ALTER TABLE user_last_active - ADD CONSTRAINT user_last_active_pkey - PRIMARY KEY (app_id, user_id); - -ALTER TABLE user_last_active - DROP CONSTRAINT IF EXISTS user_last_active_app_id_fkey; - -ALTER TABLE user_last_active - ADD CONSTRAINT user_last_active_app_id_fkey - FOREIGN KEY (app_id) - REFERENCES apps (app_id) ON DELETE CASCADE; - -CREATE INDEX IF NOT EXISTS user_last_active_app_id_index ON user_last_active (app_id); -``` - - -### 6.0 to 7.0 -```sql -ALTER TABLE all_auth_recipe_users - ADD COLUMN primary_or_recipe_user_id CHAR(36) NOT NULL DEFAULT ('0'); - -ALTER TABLE all_auth_recipe_users - ADD COLUMN is_linked_or_is_a_primary_user BOOLEAN NOT NULL DEFAULT FALSE; - -ALTER TABLE all_auth_recipe_users - ADD COLUMN primary_or_recipe_user_time_joined BIGINT NOT NULL DEFAULT 0; - -UPDATE all_auth_recipe_users - SET primary_or_recipe_user_id = user_id - WHERE primary_or_recipe_user_id = '0'; - -UPDATE all_auth_recipe_users - SET primary_or_recipe_user_time_joined = time_joined - WHERE primary_or_recipe_user_time_joined = 0; - -ALTER TABLE all_auth_recipe_users - ADD CONSTRAINT all_auth_recipe_users_primary_or_recipe_user_id_fkey - FOREIGN KEY (app_id, primary_or_recipe_user_id) - REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; - -ALTER TABLE all_auth_recipe_users - ALTER primary_or_recipe_user_id DROP DEFAULT; - -ALTER TABLE app_id_to_user_id - ADD COLUMN primary_or_recipe_user_id CHAR(36) NOT NULL DEFAULT ('0'); - -ALTER TABLE app_id_to_user_id - ADD COLUMN is_linked_or_is_a_primary_user BOOLEAN NOT NULL DEFAULT FALSE; - -UPDATE app_id_to_user_id - SET primary_or_recipe_user_id = user_id - WHERE primary_or_recipe_user_id = '0'; - -ALTER TABLE app_id_to_user_id - ADD CONSTRAINT app_id_to_user_id_primary_or_recipe_user_id_fkey - FOREIGN KEY (app_id, primary_or_recipe_user_id) - REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; - -ALTER TABLE app_id_to_user_id - ALTER primary_or_recipe_user_id DROP DEFAULT; - -DROP INDEX all_auth_recipe_users_pagination_index; - -CREATE INDEX all_auth_recipe_users_pagination_index1 ON all_auth_recipe_users ( - app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC); - -CREATE INDEX all_auth_recipe_users_pagination_index2 ON all_auth_recipe_users ( - app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC); - -CREATE INDEX all_auth_recipe_users_pagination_index3 ON all_auth_recipe_users ( - recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC); - -CREATE INDEX all_auth_recipe_users_pagination_index4 ON all_auth_recipe_users ( - recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC); - -CREATE INDEX all_auth_recipe_users_primary_user_id_index ON all_auth_recipe_users (primary_or_recipe_user_id, app_id); - -CREATE INDEX all_auth_recipe_users_recipe_id_index ON all_auth_recipe_users (app_id, recipe_id, tenant_id); - -ALTER TABLE emailpassword_pswd_reset_tokens DROP CONSTRAINT IF EXISTS emailpassword_pswd_reset_tokens_user_id_fkey; - -ALTER TABLE emailpassword_pswd_reset_tokens ADD CONSTRAINT emailpassword_pswd_reset_tokens_user_id_fkey FOREIGN KEY (app_id, user_id) REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; - -ALTER TABLE emailpassword_pswd_reset_tokens ADD COLUMN email VARCHAR(256); -``` - -### 7.0 to 8.0 -```sql -ALTER TABLE user_roles DROP CONSTRAINT IF EXISTS user_roles_role_fkey; -``` - -### 8.0 to 9.0 -```sql -ALTER TABLE totp_user_devices ADD COLUMN IF NOT EXISTS created_at BIGINT default 0; -ALTER TABLE totp_user_devices ALTER COLUMN created_at DROP DEFAULT; -``` - -### 9.0 to 9.1 -When transferring data from older / source master db to newer one, we have to modify the insert query to set `is_first_factors_null` to true when inserting into the `tenant_configs` (in the target master db). +Please visit supertokens-core changelog. \ No newline at end of file diff --git a/v2/emailpassword/custom-ui/init/core/self-hosted-with-aws.mdx b/v2/emailpassword/custom-ui/init/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/emailpassword/custom-ui/init/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/emailpassword/custom-ui/init/database-setup/mysql.mdx b/v2/emailpassword/custom-ui/init/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/emailpassword/custom-ui/init/database-setup/mysql.mdx +++ b/v2/emailpassword/custom-ui/init/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/emailpassword/custom-ui/init/database-setup/postgresql.mdx b/v2/emailpassword/custom-ui/init/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/emailpassword/custom-ui/init/database-setup/postgresql.mdx +++ b/v2/emailpassword/custom-ui/init/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/emailpassword/migration/account-creation/ep-migration-without-password-hash.mdx b/v2/emailpassword/migration/account-creation/ep-migration-without-password-hash.mdx index 7a71670f6..678b00a4c 100644 --- a/v2/emailpassword/migration/account-creation/ep-migration-without-password-hash.mdx +++ b/v2/emailpassword/migration/account-creation/ep-migration-without-password-hash.mdx @@ -36,7 +36,7 @@ We will need to make the following customizations to SuperTokens authentication ## Step 1) Prevent signups from users who exist in the external provider -To implement this change we will override the function that handles email-password login when initializing the `ThirdPartyEmailPassword` recipe on the backend. +To implement this change we will override the api that handles email-password login when initializing the recipe on the backend. @@ -46,18 +46,19 @@ import EmailPassword from "supertokens-node/recipe/emailpassword" EmailPassword.init({ override: { - functions: (originalImplementation) => { + apis: (originalImplementation) => { return { ...originalImplementation, - signUp: async function(input) { + signUpPOST: async function (input) { + let email = input.formFields.find((field) => field.id === "email")!.value; // Check if the user signing in exists in the external provider - if(await doesUserExistInExternalProvider(input.email)){ + if (await doesUserExistInExternalProvider(email)) { // Return status "EMAIL_ALREADY_EXISTS_ERROR" since the user already exists in the external provider return { status: "EMAIL_ALREADY_EXISTS_ERROR" } } - return originalImplementation.signUp(input); + return originalImplementation.signUpPOST!(input); }, } }, @@ -77,22 +78,40 @@ async function doesUserExistInExternalProvider(email: string): Promise ```python from supertokens_python import init, InputAppInfo from supertokens_python.recipe import emailpassword -from supertokens_python.recipe.emailpassword.interfaces import RecipeInterface, SignUpOkResult, SignUpEmailAlreadyExistsError -from typing import Dict, Any, Union +from supertokens_python.recipe.emailpassword.interfaces import ( + APIInterface, + SignUpPostOkResult, + SignUpPostEmailAlreadyExistsError, + APIOptions, +) +from supertokens_python.types import GeneralErrorResponse +from supertokens_python.recipe.emailpassword.types import FormField +from typing import Dict, Any, Union, List -def override_email_password_functions(original_implementation: RecipeInterface): - original_sign_up = original_implementation.sign_up +def override_email_password_apis(original_implementation: APIInterface): + original_sign_up = original_implementation.sign_up_post - async def sign_up(email: str, password: str, tenant_id: str, user_context: Dict[str, Any]) -> Union[SignUpOkResult, SignUpEmailAlreadyExistsError]: + async def sign_up( + form_fields: List[FormField], + tenant_id: str, + api_options: APIOptions, + user_context: Dict[str, Any], + ) -> Union[ + SignUpPostOkResult, SignUpPostEmailAlreadyExistsError, GeneralErrorResponse + ]: + email = "" + for field in form_fields: + if field.id == "email": + email = field.value # check if the user signing in exists in the external provider if await does_user_exist_in_external_provider(email): # Return SignUpEmailAlreadyExistsError since the user exists in the external provider - return SignUpEmailAlreadyExistsError() + return SignUpPostEmailAlreadyExistsError() - return await original_sign_up(email, password, tenant_id, user_context) + return await original_sign_up(form_fields, tenant_id, api_options, user_context) - original_implementation.sign_up = sign_up + original_implementation.sign_up_post = sign_up return original_implementation @@ -102,16 +121,15 @@ async def does_user_exist_in_external_provider(email: str): init( - app_info=InputAppInfo( - api_domain="...", app_name="...", website_domain="..."), - framework='...', # type: ignore + app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."), + framework="...", # type: ignore recipe_list=[ emailpassword.init( override=emailpassword.InputOverrideConfig( - functions=override_email_password_functions, + apis=override_email_password_apis, ) ) - ] + ], ) ``` @@ -131,21 +149,27 @@ func main() { RecipeList: []supertokens.Recipe{ emailpassword.Init(&epmodels.TypeInput{ Override: &epmodels.OverrideStruct{ - Functions: func(originalImplementation epmodels.RecipeInterface) epmodels.RecipeInterface { + APIs: func(originalImplementation epmodels.APIInterface) epmodels.APIInterface { // Copy the original implementation of the signUp function - originalSignUp := *originalImplementation.SignUp + originalSignUp := *originalImplementation.SignUpPOST // Override the signUp function - (*originalImplementation.SignUp) = func(email, password string, tenantId string, userContext supertokens.UserContext) (epmodels.SignUpResponse, error) { + (*originalImplementation.SignUpPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.SignUpPOSTResponse, error) { + email := "" + for _, formField := range formFields { + if formField.ID == "email" { + email = formField.Value + } + } // Check if the user signing in exists in the external provider if doesUserExistInExternalProvider(email) { // Return status "EMAIL_ALREADY_EXISTS_ERROR" since the user already exists in the external provider - return epmodels.SignUpResponse{ + return epmodels.SignUpPOSTResponse{ EmailAlreadyExistsError: &struct{}{}, }, nil } - return originalSignUp(email, password, tenantId, userContext) + return originalSignUp(formFields, tenantId, options, userContext) } return originalImplementation }, @@ -165,11 +189,11 @@ func doesUserExistInExternalProvider(email string) bool { -We modify the `signUp` function to first check if the user signing up has an account with the external provider. If they do we return a `EMAIL_ALREADY_EXISTS_ERROR` +We modify the `signUpPOST` API to first check if the user signing up has an account with the external provider. If they do we return a `EMAIL_ALREADY_EXISTS_ERROR` ## Step 2) Create a SuperTokens account for users trying to sign in if they have an account with the external provider -To implement this flow we will override the function that handles email-password login when initializing the `ThirdPartyEmailPassword` recipe on the backend. +To implement this flow we will override the API that handles email-password login when initializing the recipe on the backend. @@ -182,22 +206,24 @@ import { RecipeUserId } from "supertokens-node"; EmailPassword.init({ override: { - functions: (originalImplementation) => { + apis: (originalImplementation) => { return { ...originalImplementation, - signIn: async function (input) { + signInPOST: async function (input) { // Check if an email-password user with the input email exists in SuperTokens + let email = input.formFields.find((field) => field.id === "email")!.value; + let password = input.formFields.find((field) => field.id === "password")!.value; let supertokensUsersWithSameEmail = await SuperTokens.listUsersByAccountInfo(input.tenantId, { - email: input.email + email: email }, undefined, input.userContext); let emailPasswordUser = supertokensUsersWithSameEmail.find(u => { - return u.loginMethods.find(lM => lM.hasSameEmailAs(input.email) && lM.recipeId === "emailpassword") !== undefined; + return u.loginMethods.find(lM => lM.hasSameEmailAs(email) && lM.recipeId === "emailpassword") !== undefined; }) if (emailPasswordUser === undefined) { // EmailPassword user with the input email does not exist in SuperTokens // Check if the input credentials are valid in the external provider - let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(input.email, input.password) + let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(email, password) if (legacyUserInfo === undefined) { // credentials are incorrect return { @@ -206,14 +232,14 @@ EmailPassword.init({ } // Call the signup function to create a new SuperTokens user. - let signUpResponse = await EmailPassword.signUp(input.tenantId, input.email, input.password, undefined, input.userContext); + let signUpResponse = await EmailPassword.signUp(input.tenantId, email, password, undefined, input.userContext); if (signUpResponse.status !== "OK") { throw new Error("Should never come here") } // Map the external provider's userId to the SuperTokens userId await SuperTokens.createUserIdMapping({ superTokensUserId: signUpResponse.user.id, externalUserId: legacyUserInfo.user_id }) - + // Set the userId in the response to use the provider's userId signUpResponse.user.id = legacyUserInfo.user_id signUpResponse.user.loginMethods[0].recipeUserId = new RecipeUserId(legacyUserInfo.user_id); @@ -221,18 +247,16 @@ EmailPassword.init({ // We will also need to set the email verification status of the user if (legacyUserInfo.isEmailVerified) { // Generate an email verification token for the user - let generateEmailVerificationTokenResponse = await EmailVerification.createEmailVerificationToken(input.tenantId, signUpResponse.recipeUserId, input.email, input.userContext); + let generateEmailVerificationTokenResponse = await EmailVerification.createEmailVerificationToken(input.tenantId, signUpResponse.recipeUserId, email, input.userContext); if (generateEmailVerificationTokenResponse.status === "OK") { // Verify the user's email await EmailVerification.verifyEmailUsingToken("public", generateEmailVerificationTokenResponse.token, undefined, input.userContext); } } - - return signUpResponse; } - return originalImplementation.signIn(input) + return originalImplementation.signInPOST!(input) }, } }, @@ -256,17 +280,48 @@ async function validateAndGetUserInfoFromExternalProvider(email: string, passwor from supertokens_python import init, InputAppInfo from supertokens_python.recipe import emailpassword from supertokens_python.asyncio import create_user_id_mapping -from supertokens_python.recipe.emailverification.asyncio import create_email_verification_token, verify_email_using_token +from supertokens_python.recipe.emailverification.asyncio import ( + create_email_verification_token, + verify_email_using_token, +) from supertokens_python.recipe.emailpassword.asyncio import get_user_by_email, sign_up -from supertokens_python.recipe.emailpassword.interfaces import RecipeInterface, SignInOkResult, SignInWrongCredentialsError, SignUpEmailAlreadyExistsError -from supertokens_python.recipe.emailverification.interfaces import CreateEmailVerificationTokenOkResult -from typing import Dict, Any, Union +from supertokens_python.recipe.emailpassword.interfaces import ( + SignUpEmailAlreadyExistsError, +) +from supertokens_python.recipe.emailverification.interfaces import ( + CreateEmailVerificationTokenOkResult, +) +from supertokens_python import init, InputAppInfo +from supertokens_python.recipe import emailpassword +from supertokens_python.recipe.emailpassword.interfaces import ( + APIInterface, + SignInPostOkResult, + SignInPostWrongCredentialsError, + APIOptions, +) +from supertokens_python.types import GeneralErrorResponse +from supertokens_python.recipe.emailpassword.types import FormField +from typing import Dict, Any, Union, List -def override_emailpassword_functions(original_implementation: RecipeInterface): - original_emailpassword_sign_in = original_implementation.sign_in +def override_emailpassword_apis(original_implementation: APIInterface): + original_emailpassword_sign_in = original_implementation.sign_in_post - async def sign_in(email: str, password: str, tenant_id: str, user_context: Dict[str, Any]) -> Union[SignInOkResult, SignInWrongCredentialsError]: + async def sign_in( + form_fields: List[FormField], + tenant_id: str, + api_options: APIOptions, + user_context: Dict[str, Any], + ) -> Union[ + SignInPostOkResult, SignInPostWrongCredentialsError, GeneralErrorResponse + ]: + email = "" + password = "" + for field in form_fields: + if field.id == "email": + email = field.value + if field.id == "password": + password = field.value # Check if an email-password user with the input email exists in SuperTokens emailpassword_user = await get_user_by_email(tenant_id, email, user_context) @@ -274,10 +329,11 @@ def override_emailpassword_functions(original_implementation: RecipeInterface): # EmailPassword user with the input email does not exist in SuperTokens # Check if the input credentials valid in the external provider legacy_user_info = await validate_and_get_user_info_from_external_provider( - email, password) + email, password + ) if legacy_user_info is None: # Credentials are incorrect - return SignInWrongCredentialsError() + return SignInPostWrongCredentialsError() # Call the sign_up function to create a new SuperTokens user. response = await sign_up(email, password, tenant_id, user_context) @@ -285,32 +341,38 @@ def override_emailpassword_functions(original_implementation: RecipeInterface): raise Exception("Should never come here") # Map the external provider's userId to the SuperTokens userId - await create_user_id_mapping(response.user.user_id, - legacy_user_info.user_id) + await create_user_id_mapping( + response.user.user_id, legacy_user_info.user_id + ) # Set the userId in the response to use the provider's userId response.user.user_id = legacy_user_info.user_id # We will also need to set the email verification status of the user if legacy_user_info.isEmailVerified: # Generate an email verification token for the user - generate_email_verification_response = await create_email_verification_token( - tenant_id, - response.user.user_id, - email, - user_context, + generate_email_verification_response = ( + await create_email_verification_token( + tenant_id, + response.user.user_id, + email, + user_context, + ) ) - if isinstance(generate_email_verification_response, CreateEmailVerificationTokenOkResult): + if isinstance( + generate_email_verification_response, + CreateEmailVerificationTokenOkResult, + ): await verify_email_using_token( tenant_id, - generate_email_verification_response.token, + generate_email_verification_response.token, user_context, ) - return SignInOkResult(response.user) - - return await original_emailpassword_sign_in(email, password, tenant_id, user_context) + return await original_emailpassword_sign_in( + form_fields, tenant_id, api_options, user_context + ) - original_implementation.sign_in = sign_in + original_implementation.sign_in_post = sign_in return original_implementation @@ -320,21 +382,20 @@ class ExternalUserInfo: self.isEmailVerified: bool = isEmailVerified -async def validate_and_get_user_info_from_external_provider(email: str, password: str) -> Union[None, ExternalUserInfo]: +async def validate_and_get_user_info_from_external_provider( + email: str, password: str +) -> Union[None, ExternalUserInfo]: return None init( - app_info=InputAppInfo( - api_domain="...", app_name="...", website_domain="..."), - framework='...', # type: ignore + app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."), + framework="...", # type: ignore recipe_list=[ emailpassword.init( - override=emailpassword.InputOverrideConfig( - functions=override_emailpassword_functions - ) + override=emailpassword.InputOverrideConfig(apis=override_emailpassword_apis) ) - ] + ], ) ``` @@ -357,18 +418,28 @@ func main() { RecipeList: []supertokens.Recipe{ emailpassword.Init(&epmodels.TypeInput{ Override: &epmodels.OverrideStruct{ - Functions: func(originalImplementation epmodels.RecipeInterface) epmodels.RecipeInterface { + APIs: func(originalImplementation epmodels.APIInterface) epmodels.APIInterface { // Copy the original implementation of the signIn function - originalSignIn := *originalImplementation.SignIn + originalSignIn := *originalImplementation.SignInPOST // Override the function - (*originalImplementation.SignIn) = func(email, password, tenantId string, userContext supertokens.UserContext) (epmodels.SignInResponse, error) { + (*originalImplementation.SignInPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.SignInPOSTResponse, error) { + email := "" + password := "" + for _, formField := range formFields { + if formField.ID == "email" { + email = formField.Value + } + if formField.ID == "password" { + password = formField.Value + } + } // Check if an email-password user with the input email exists in SuperTokens emailPasswordUser, err := emailpassword.GetUserByEmail(tenantId, email) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if emailPasswordUser == nil { @@ -377,7 +448,7 @@ func main() { legacyUserInfo := validateAndGetUserInfoFromExternalProvider(email, password) if legacyUserInfo == nil { - return epmodels.SignInResponse{ + return epmodels.SignInPOSTResponse{ WrongCredentialsError: &struct{}{}, }, nil } @@ -385,17 +456,17 @@ func main() { // Call the email-password signup function to create a new SuperTokens user. response, err := emailpassword.SignUp(tenantId, email, password) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if response.OK == nil { - return epmodels.SignInResponse{}, errors.New("Should never come here") + return epmodels.SignInPOSTResponse{}, errors.New("Should never come here") } // Map the external provider's userId to the SuperTokens userId _, err = supertokens.CreateUserIdMapping(response.OK.User.ID, legacyUserInfo.userId, nil, nil) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } // Set the userId in the response to use the provider's userId response.OK.User.ID = legacyUserInfo.userId @@ -405,7 +476,7 @@ func main() { // Generate an email verification token for the user generateEmailVerificationTokenResponse, err := emailverification.CreateEmailVerificationToken(tenantId, response.OK.User.ID, &email) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if generateEmailVerificationTokenResponse.OK != nil { @@ -413,14 +484,9 @@ func main() { emailverification.VerifyEmailUsingToken(tenantId, generateEmailVerificationTokenResponse.OK.Token) } } - - return epmodels.SignInResponse{ - OK: &struct{ User epmodels.User }{response.OK.User}, - }, nil - } - return originalSignIn(email, password, tenantId, userContext) + return originalSignIn(formFields, tenantId, options, userContext) } return originalImplementation @@ -446,7 +512,7 @@ func validateAndGetUserInfoFromExternalProvider(email string, password string) * -The code above overrides the `signIn` function with the following changes to achieve "**just in time**" migration: +The code above overrides the `signInPOST` API with the following changes to achieve "**just in time**" migration: - The first step is to determine if the user signing in needs to be migrated or not. We do this by checking if a user with the input email exists in the external auth provider and SuperTokens. If the user exists in the external auth provider and does not exist SuperTokens, we can determine that this user needs to be migrated. - The next step is to validate the input credentials against the external provider. If the credentials are invalid we will throw a `WRONG_CREDENTIALS_ERROR`. @@ -471,15 +537,10 @@ import UserMetadata from "supertokens-node/recipe/usermetadata" EmailPassword.init({ override: { - functions: (originalImplementation) => { - return { - ...originalImplementation, - // TODO: implementation details in previous step - } - }, apis: (originalImplementation) => { return { ...originalImplementation, + // Add overrides from the previous step generatePasswordResetTokenPOST: async (input) => { // Retrieve the email from the input let email = input.formFields.find(i => i.id === "email")!.value; @@ -828,12 +889,6 @@ import UserMetadata from "supertokens-node/recipe/usermetadata" EmailPassword.init({ override: { - functions: (originalImplementaion) => { - return { - ...originalImplementaion - // TODO: implentation details in previous step - } - }, apis: (originalImplementation) => { return { ...originalImplementation, @@ -1015,22 +1070,24 @@ import { RecipeUserId } from "supertokens-node"; EmailPassword.init({ override: { - functions: (originalImplementation) => { + apis: (originalImplementation) => { return { ...originalImplementation, - signIn: async function (input) { + signInPOST: async function (input) { // Check if an email-password user with the input email exists in SuperTokens + let email = input.formFields.find((field) => field.id === "email")!.value; + let password = input.formFields.find((field) => field.id === "password")!.value; let supertokensUsersWithSameEmail = await SuperTokens.listUsersByAccountInfo(input.tenantId, { - email: input.email + email: email }, undefined, input.userContext); let emailPasswordUser = supertokensUsersWithSameEmail.find(u => { - return u.loginMethods.find(lM => lM.hasSameEmailAs(input.email) && lM.recipeId === "emailpassword") !== undefined; + return u.loginMethods.find(lM => lM.hasSameEmailAs(email) && lM.recipeId === "emailpassword") !== undefined; }) if (emailPasswordUser === undefined) { // EmailPassword user with the input email does not exist in SuperTokens // Check if the input credentials are valid in the external provider - let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(input.email, input.password) + let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(email, password) if (legacyUserInfo === undefined) { // credentials are incorrect return { @@ -1039,7 +1096,7 @@ EmailPassword.init({ } // Call the signup function to create a new SuperTokens user. - let signUpResponse = await EmailPassword.signUp(input.tenantId, input.email, input.password, undefined, input.userContext); + let signUpResponse = await EmailPassword.signUp(input.tenantId, email, password, undefined, input.userContext); if (signUpResponse.status !== "OK") { throw new Error("Should never come here") } @@ -1053,47 +1110,41 @@ EmailPassword.init({ // We will also need to set the email verification status of the user if (legacyUserInfo.isEmailVerified) { // Generate an email verification token for the user - let generateEmailVerificationTokenResponse = await EmailVerification.createEmailVerificationToken(input.tenantId, signUpResponse.recipeUserId, input.email, input.userContext); + let generateEmailVerificationTokenResponse = await EmailVerification.createEmailVerificationToken(input.tenantId, signUpResponse.recipeUserId, email, input.userContext); if (generateEmailVerificationTokenResponse.status === "OK") { // Verify the user's email await EmailVerification.verifyEmailUsingToken("public", generateEmailVerificationTokenResponse.token, undefined, input.userContext); } } - - return signUpResponse; + emailPasswordUser = signUpResponse.user; } // highlight-start // Check if the user signing in has a temporary password let userMetadata = await UserMetadata.getUserMetadata(emailPasswordUser.id, input.userContext) if (userMetadata.status === "OK" && userMetadata.metadata.isUsingTemporaryPassword) { // Check if the input credentials are valid in the external provider - let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(input.email, input.password); + let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(email, password); if (legacyUserInfo) { - let loginMethod = emailPasswordUser.loginMethods.find(lM => lM.recipeId === "emailpassword" && lM.hasSameEmailAs(input.email)); + let loginMethod = emailPasswordUser.loginMethods.find(lM => lM.recipeId === "emailpassword" && lM.hasSameEmailAs(email)); // Update the user's password with the correct password EmailPassword.updateEmailOrPassword({ recipeUserId: loginMethod!.recipeUserId, - password: input.password, + password: password, applyPasswordPolicy: false }) // Update the user's metadata to remove the isUsingTemporaryPassword flag UserMetadata.updateUserMetadata(emailPasswordUser.id, { isUsingTemporaryPassword: null }) - + } else { return { - status: "OK", - user: emailPasswordUser, - recipeUserId: loginMethod!.recipeUserId + status: "WRONG_CREDENTIALS_ERROR" } } - return { - status: "WRONG_CREDENTIALS_ERROR" - } } // highlight-end - return originalImplementation.signIn(input) + return originalImplementation.signInPOST!(input) }, } }, @@ -1116,10 +1167,6 @@ async function validateAndGetUserInfoFromExternalProvider(email: string, passwor from supertokens_python import init, InputAppInfo from supertokens_python.recipe import emailpassword from supertokens_python.asyncio import create_user_id_mapping -from supertokens_python.recipe.usermetadata.asyncio import ( - get_user_metadata, - update_user_metadata, -) from supertokens_python.recipe.emailverification.asyncio import ( create_email_verification_token, verify_email_using_token, @@ -1130,23 +1177,46 @@ from supertokens_python.recipe.emailpassword.asyncio import ( update_email_or_password, ) from supertokens_python.recipe.emailpassword.interfaces import ( - RecipeInterface, - SignInOkResult, - SignInWrongCredentialsError, SignUpEmailAlreadyExistsError, ) from supertokens_python.recipe.emailverification.interfaces import ( CreateEmailVerificationTokenOkResult, ) -from typing import Dict, Any, Union +from supertokens_python import init, InputAppInfo +from supertokens_python.recipe import emailpassword +from supertokens_python.recipe.emailpassword.interfaces import ( + APIInterface, + SignInPostOkResult, + SignInPostWrongCredentialsError, + APIOptions, +) +from supertokens_python.types import GeneralErrorResponse +from supertokens_python.recipe.emailpassword.types import FormField +from typing import Dict, Any, Union, List +from supertokens_python.recipe.usermetadata.asyncio import ( + get_user_metadata, + update_user_metadata, +) -def override_emailpassword_functions(original_implementation: RecipeInterface): - original_emailpassword_sign_in = original_implementation.sign_in +def override_emailpassword_apis(original_implementation: APIInterface): + original_emailpassword_sign_in = original_implementation.sign_in_post - async def emailpassword_sign_in( - email: str, password: str, tenant_id: str, user_context: Dict[str, Any] - ) -> Union[SignInOkResult, SignInWrongCredentialsError]: + async def sign_in( + form_fields: List[FormField], + tenant_id: str, + api_options: APIOptions, + user_context: Dict[str, Any], + ) -> Union[ + SignInPostOkResult, SignInPostWrongCredentialsError, GeneralErrorResponse + ]: + email = "" + password = "" + for field in form_fields: + if field.id == "email": + email = field.value + if field.id == "password": + password = field.value # Check if an email-password user with the input email exists in SuperTokens emailpassword_user = await get_user_by_email(tenant_id, email, user_context) @@ -1158,7 +1228,7 @@ def override_emailpassword_functions(original_implementation: RecipeInterface): ) if legacy_user_info is None: # Credentials are incorrect - return SignInWrongCredentialsError() + return SignInPostWrongCredentialsError() # Call the sign_up function to create a new SuperTokens user. response = await sign_up(email, password, tenant_id, user_context) @@ -1190,8 +1260,7 @@ def override_emailpassword_functions(original_implementation: RecipeInterface): user_context, ) - return SignInOkResult(response.user) - + emailpassword_user = response.user # highlight-start # Check if the user signing in has a temporary password metadata_result = await get_user_metadata(emailpassword_user.user_id) @@ -1217,15 +1286,15 @@ def override_emailpassword_functions(original_implementation: RecipeInterface): await update_user_metadata( emailpassword_user.user_id, {"isUsingTemporaryPassword": None} ) - return SignInOkResult(emailpassword_user) - return SignInWrongCredentialsError() + else: + return SignInPostWrongCredentialsError() # highlight-end return await original_emailpassword_sign_in( - email, password, tenant_id, user_context + form_fields, tenant_id, api_options, user_context ) - original_implementation.sign_in = emailpassword_sign_in + original_implementation.sign_in_post = sign_in return original_implementation @@ -1246,9 +1315,7 @@ init( framework="...", # type: ignore recipe_list=[ emailpassword.init( - override=emailpassword.InputOverrideConfig( - functions=override_emailpassword_functions - ) + override=emailpassword.InputOverrideConfig(apis=override_emailpassword_apis) ) ], ) @@ -1274,18 +1341,28 @@ func main() { RecipeList: []supertokens.Recipe{ emailpassword.Init(&epmodels.TypeInput{ Override: &epmodels.OverrideStruct{ - Functions: func(originalImplementation epmodels.RecipeInterface) epmodels.RecipeInterface { + APIs: func(originalImplementation epmodels.APIInterface) epmodels.APIInterface { // Copy the original implementation of the signIn function - originalSignIn := *originalImplementation.SignIn + originalSignIn := *originalImplementation.SignInPOST // Override the function - (*originalImplementation.SignIn) = func(email, password, tenantId string, userContext supertokens.UserContext) (epmodels.SignInResponse, error) { + (*originalImplementation.SignInPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.SignInPOSTResponse, error) { + email := "" + password := "" + for _, formField := range formFields { + if formField.ID == "email" { + email = formField.Value + } + if formField.ID == "password" { + password = formField.Value + } + } // Check if an email-password user with the input email exists in SuperTokens emailPasswordUser, err := emailpassword.GetUserByEmail(tenantId, email) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if emailPasswordUser == nil { @@ -1294,7 +1371,7 @@ func main() { legacyUserInfo := validateAndGetUserInfoFromExternalProvider(email, password) if legacyUserInfo == nil { - return epmodels.SignInResponse{ + return epmodels.SignInPOSTResponse{ WrongCredentialsError: &struct{}{}, }, nil } @@ -1302,11 +1379,11 @@ func main() { // Call the email-password signup function to create a new SuperTokens user. response, err := emailpassword.SignUp(tenantId, email, password) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if response.OK == nil { - return epmodels.SignInResponse{}, errors.New("Should never come here") + return epmodels.SignInPOSTResponse{}, errors.New("Should never come here") } // Map the external provider's userId to the SuperTokens userId @@ -1319,29 +1396,25 @@ func main() { // Generate an email verification token for the user generateEmailVerificationTokenResponse, err := emailverification.CreateEmailVerificationToken(tenantId, response.OK.User.ID, &email) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if generateEmailVerificationTokenResponse.OK != nil { // Verify the user's email _, err = emailverification.VerifyEmailUsingToken(tenantId, generateEmailVerificationTokenResponse.OK.Token) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } } } - - return epmodels.SignInResponse{ - OK: &struct{ User epmodels.User }{response.OK.User}, - }, nil - + emailPasswordUser = &response.OK.User } // Check if the user signing in has a temporary password metadata, err := usermetadata.GetUserMetadata(emailPasswordUser.ID) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } isUsingTemporaryPassword, ok := metadata["isUsingTemporaryPassword"] @@ -1354,7 +1427,7 @@ func main() { usePasswordPolicy := false _, err = emailpassword.UpdateEmailOrPassword(emailPasswordUser.ID, nil, &password, &usePasswordPolicy, &tenantId) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } // Update the user's metadata to remove the isUsingTemporaryPassword flag @@ -1362,20 +1435,16 @@ func main() { "isUsingTemporaryPassword": nil, }) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } - - return epmodels.SignInResponse{ - OK: &struct{ User epmodels.User }{*emailPasswordUser}, + } else { + return epmodels.SignInPOSTResponse{ + WrongCredentialsError: &struct{}{}, }, nil } - - return epmodels.SignInResponse{ - WrongCredentialsError: &struct{}{}, - }, nil } - return originalSignIn(email, password, tenantId, userContext) + return originalSignIn(formFields, tenantId, options, userContext) } return originalImplementation @@ -1402,7 +1471,7 @@ func validateAndGetUserInfoFromExternalProvider(email string, password string) * -The code above adds the following changes to the `signIn` function: +The code above adds the following changes to the `signInPOST` API: - Adds an additional check where if a user exists in SuperTokens, we check if they have the `isUsingTemporaryPassword` flag set in their metadata. - If the flag exists, we check if the input credentials are valid in the external provider. If they are we update the account with the new password and continue the login flow. diff --git a/v2/emailpassword/nextjs/app-directory/next-steps.mdx b/v2/emailpassword/nextjs/app-directory/next-steps.mdx index 7de2c545f..20b4de6c9 100644 --- a/v2/emailpassword/nextjs/app-directory/next-steps.mdx +++ b/v2/emailpassword/nextjs/app-directory/next-steps.mdx @@ -21,8 +21,8 @@ import {Question, Answer}from "/src/components/question" You need to now setup an instance of the SuperTokens core for your app (that your backend should connect to). You have two options: -- [Managed service](../quick-setup/core/saas-setup) -- Self hosted with your own database ([With Docker](../quick-setup/core/with-docker) or [Without Docker](../quick-setup/core/without-docker)) +- [Managed service](../../pre-built-ui/setup/core/saas-setup) +- Self hosted with your own database ([With Docker](../../pre-built-ui/setup/core/with-docker) or [Without Docker](../../pre-built-ui/setup/core/without-docker)) diff --git a/v2/emailpassword/pre-built-ui/setup/core/self-hosted-with-aws.mdx b/v2/emailpassword/pre-built-ui/setup/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/emailpassword/pre-built-ui/setup/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/emailpassword/pre-built-ui/setup/database-setup/mysql.mdx b/v2/emailpassword/pre-built-ui/setup/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/emailpassword/pre-built-ui/setup/database-setup/mysql.mdx +++ b/v2/emailpassword/pre-built-ui/setup/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/emailpassword/pre-built-ui/setup/database-setup/postgresql.mdx b/v2/emailpassword/pre-built-ui/setup/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/emailpassword/pre-built-ui/setup/database-setup/postgresql.mdx +++ b/v2/emailpassword/pre-built-ui/setup/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/emailpassword/quick-setup/core/self-hosted-with-aws.mdx b/v2/emailpassword/quick-setup/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/emailpassword/quick-setup/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/emailpassword/rate-limits.mdx b/v2/emailpassword/rate-limits.mdx index 10d597656..340538335 100644 --- a/v2/emailpassword/rate-limits.mdx +++ b/v2/emailpassword/rate-limits.mdx @@ -13,7 +13,7 @@ import CustomAdmonition from "/src/components/customAdmonition" ## For managed service -The SuperTokens core is rate limited on a per app and per IP address basis. This means that if query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). +The SuperTokens core is rate limited on a per app and per IP address basis. This means that if you query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). :::note To know more about rps and bursts, please [this nginx document](https://www.nginx.com/blog/rate-limiting-nginx/). diff --git a/v2/emailpassword/sdks.mdx b/v2/emailpassword/sdks.mdx index b155f32f5..a732bdfa0 100644 --- a/v2/emailpassword/sdks.mdx +++ b/v2/emailpassword/sdks.mdx @@ -60,6 +60,10 @@ import GuidesLink from "/src/components/guidesLink" - SuperTokens provides React based pre-built UI components, for other frontend frameworks you will need to build custom UI and use the `supertokens-web-js` SDK to communicate with the APIs exposed by the SuperTokens backend SDK. - For other backend frameworks, you can follow our [guide on how to spin up a separate server configured with the SuperTokens backend SDK](/docs/community/other-frameworks) to authenticate requests and issue session tokens. +## SDK Migration + +See the [updating SuperTokens](./updating-supertokens) page for steps on how to migrate SDKs. + :::info Visit the [API reference page](./apis) to learn more. ::: diff --git a/v2/emailpassword/serverless/with-aws-lambda/setup-api-gateway.mdx b/v2/emailpassword/serverless/with-aws-lambda/setup-api-gateway.mdx index 784e215f1..c875e1d19 100644 --- a/v2/emailpassword/serverless/with-aws-lambda/setup-api-gateway.mdx +++ b/v2/emailpassword/serverless/with-aws-lambda/setup-api-gateway.mdx @@ -34,6 +34,12 @@ Click on the "ANY" method and then "Integration" to configure the lambda functio Configure lambda integration UI +:::important + +Ensure that the **Lambda proxy integration** toggle is turned on. + +::: + ## 4) Enable CORS for the proxy path Click on the `{proxy+}` resource and then "Enable CORS" button to open the CORS configuration page. diff --git a/v2/emailpassword/sidebars.js b/v2/emailpassword/sidebars.js index ea2d0ee93..c4ce51254 100644 --- a/v2/emailpassword/sidebars.js +++ b/v2/emailpassword/sidebars.js @@ -33,7 +33,6 @@ module.exports = { items: [ "pre-built-ui/setup/core/with-docker", "pre-built-ui/setup/core/without-docker", - "pre-built-ui/setup/core/aws-setup-with-stacksnap", { type: "category", label: "Database Setup", @@ -109,7 +108,6 @@ module.exports = { items: [ "custom-ui/init/core/with-docker", "custom-ui/init/core/without-docker", - "custom-ui/init/core/aws-setup-with-stacksnap", { type: "category", label: "Database Setup", @@ -707,8 +705,8 @@ module.exports = { ], }, { - type: "category", - label: "Migration", + type: 'category', + label: 'Migrating to Supertokens', items: [ "migration/about", { @@ -726,6 +724,7 @@ module.exports = { "migration/mfa-migration", ], }, + "updating-supertokens", { type: "category", label: "References", diff --git a/v2/emailpassword/updating-supertokens.mdx b/v2/emailpassword/updating-supertokens.mdx new file mode 100644 index 000000000..b57bab619 --- /dev/null +++ b/v2/emailpassword/updating-supertokens.mdx @@ -0,0 +1,65 @@ +--- +id: updating-supertokens +title: Updating Supertokens core and SDKs +hide_title: true +--- + + + + +# Updating SuperTokens core and SDKs + +:::important +You need to follow these steps in order to properly update supertokens +::: + +In order to maintain compatibility and keep up on new features, we recommend updating your core and SDKs whenever possible. + +## 1. Updating your core + +You will need to shut down your core in order to update it. After it's off, run the migration scripts for all versions inbetween +your starting version and the latest version. You may then bring your core back online. + +In the rare occasion that the supertokens core version you have updated to shows as incompatible with your current front-end and +back-end sdk's in the [compatibility table](./compatibility-table), then refrain from running your back-end and front-end SDKs until after you update them. + +- ### Self-hosted core +See the migration sections in the [supertokens-core changelog](https://github.com/supertokens/supertokens-core/blob/master/CHANGELOG.md). + +- ### Managed core +If you're using the managed core service, please email us at team@supertokens.com from your registered email to request a core update. + +## 2. Update your back-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### NodeJS +See the migration sections in the [supertokens-node changelog](https://github.com/supertokens/supertokens-node/blob/master/CHANGELOG.md). + +- ### GoLang +See the migration sections in the [supertokens-golang changelog](https://github.com/supertokens/supertokens-golang/blob/master/CHANGELOG.md). + +- ### Python +See the migration sections in the [supertokens-python changelog](https://github.com/supertokens/supertokens-python/blob/master/CHANGELOG.md). + +## 3. Update your front-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### ReactJS +See the migration sections in the [supertokens-auth-react changelog](https://github.com/supertokens/supertokens-auth-react/blob/master/CHANGELOG.md). + +- ### Vanilla JS +See the migration sections in the [supertokens-web-js changelog](https://github.com/supertokens/supertokens-web-js/blob/master/CHANGELOG.md). + +- ### React Native +See the migration sections in the [supertokens-react-native changelog](https://github.com/supertokens/supertokens-react-native/blob/master/CHANGELOG.md). + +- ### iOS +See the migration sections in the [supertokens-ios changelog](https://github.com/supertokens/supertokens-ios/blob/master/CHANGELOG.md). + +- ### Flutter +See the migration sections in the [supertokens-flutter changelog](https://github.com/supertokens/supertokens-flutter/blob/master/CHANGELOG.md). + +- ### Android +See the migration sections in the [supertokens-android changelog](https://github.com/supertokens/supertokens-android/blob/master/CHANGELOG.md). diff --git a/v2/mfa/step-up-auth.mdx b/v2/mfa/step-up-auth.mdx index bc97c4f68..cb34597ee 100644 --- a/v2/mfa/step-up-auth.mdx +++ b/v2/mfa/step-up-auth.mdx @@ -542,19 +542,23 @@ To redirect the user to as factor challenge page and then navigate them back to import MultiFactorAuth from 'supertokens-auth-react/recipe/multifactorauth'; async function redirectToTotpSetupScreen() { - MultiFactorAuth.redirectToFactor(MultiFactorAuth.FactorIds.TOTP, false, true) + MultiFactorAuth.redirectToFactor({ + factorId: "totp", + stepUp: true, + redirectBack: true, + }) } ``` -- In the snippet above, we redirect to the [TOTP factor setup screen](https://master--6571be2867f75556541fde98.chromatic.com/?path=/story/totp-mfa--device-setup). The second argument represents a boolean for `forceSetup` which we set to false since we do not want to ask the user to create a new device. The third arg is also `true` since we want to redirect back to the current page after the user has finished setting up the device. -- You can also just redirect the user to `/{websiteBasePath}/mfa/totp?redirectToPath={currentPath}` if you don't want to use the above function. +- In the snippet above, we redirect to the [TOTP factor setup screen](https://master--6571be2867f75556541fde98.chromatic.com/?path=/story/totp-mfa--device-setup). We set the `stepUp` argument to `true` otherwise the MFA screen would detect that the user has already completed basic MFA requirements and would not show the verification screen. The `redirectBack` argument is set to `true` since we want to redirect back to the current page after the user has finished setting up the device. +- You can also just redirect the user to `/{websiteBasePath}/mfa/totp?setup=true&redirectToPath={currentPath}` if you don't want to use the above function. -In order to add a new device, you can redirect the user to `/{websiteBasePath}/mfa/totp?redirectToPath={currentPath}` from your settings page. This will show the [TOTP factor setup screen](https://master--6571be2867f75556541fde98.chromatic.com/?path=/story/totp-mfa--device-setup) to the user. The `redirectToPath` query param will also tell our SDK to redirect the user back to the current page after they have finished creating the device. +In order to add a new device, you can redirect the user to `/{websiteBasePath}/mfa/totp?setup=true&redirectToPath={currentPath}` from your settings page. This will show the [TOTP factor setup screen](https://master--6571be2867f75556541fde98.chromatic.com/?path=/story/totp-mfa--device-setup) to the user. The `redirectToPath` query param will also tell our SDK to redirect the user back to the current page after they have finished creating the device. @@ -613,7 +617,7 @@ function InvalidClaimHandler(props: React.PropsWithChildren) { let totpCompletedTime = claimValue.value?.c[MultiFactorAuth.FactorIds.TOTP] if (totpCompletedTime === undefined || totpCompletedTime < (DateProviderReference.getReferenceOrThrow().dateProvider.now() - 1000 * 60 * 5)) { - return
You need to complete TOTP before seeing this page. Please click here to finish to proceed.
+ return
You need to complete TOTP before seeing this page. Please click here to finish to proceed.
} // the user has finished TOTP, so we can render the children diff --git a/v2/mfa/totp/totp-for-opt-in-users.mdx b/v2/mfa/totp/totp-for-opt-in-users.mdx index 426509d90..80c7db6b0 100644 --- a/v2/mfa/totp/totp-for-opt-in-users.mdx +++ b/v2/mfa/totp/totp-for-opt-in-users.mdx @@ -548,11 +548,15 @@ In order to add a new device, you can call the following function from the front import MultiFactorAuth from 'supertokens-auth-react/recipe/multifactorauth'; async function redirectToTotpSetupScreen() { - MultiFactorAuth.redirectToFactor("totp", true, true) + MultiFactorAuth.redirectToFactor({ + factorId: "totp", + forceSetup: true, + redirectBack: true, + }) } ``` -- In the snippet above, we redirect to the [TOTP factor setup screen](https://6571be2867f75556541fde98-xieqfaxuuo.chromatic.com/?path=/story/totp-mfa--device-setup-with-single-next-option). The second argument represents a boolean for `forceSetup` which we set to true since we want the user to setup a new TOTP device. The third arg is also `true` since we want to redirect back to the current page after the user has finished setting up the device. +- In the snippet above, we redirect to the [TOTP factor setup screen](https://6571be2867f75556541fde98-xieqfaxuuo.chromatic.com/?path=/story/totp-mfa--device-setup-with-single-next-option). We set the `forceSetup` to `true` since we want the user to setup a new TOTP device. The `redirectBack` boolean is also `true` since we want to redirect back to the current page after the user has finished setting up the device. - You can also just redirect the user to `/{websiteBasePath}/mfa/totp?setup=true&redirectToPath={currentPath}` if you don't want to use the above function. diff --git a/v2/passwordless/custom-ui/init/core/self-hosted-with-aws.mdx b/v2/passwordless/custom-ui/init/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/passwordless/custom-ui/init/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/passwordless/custom-ui/init/database-setup/mysql.mdx b/v2/passwordless/custom-ui/init/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/passwordless/custom-ui/init/database-setup/mysql.mdx +++ b/v2/passwordless/custom-ui/init/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/passwordless/custom-ui/init/database-setup/postgresql.mdx b/v2/passwordless/custom-ui/init/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/passwordless/custom-ui/init/database-setup/postgresql.mdx +++ b/v2/passwordless/custom-ui/init/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/passwordless/nextjs/app-directory/next-steps.mdx b/v2/passwordless/nextjs/app-directory/next-steps.mdx index 7de2c545f..20b4de6c9 100644 --- a/v2/passwordless/nextjs/app-directory/next-steps.mdx +++ b/v2/passwordless/nextjs/app-directory/next-steps.mdx @@ -21,8 +21,8 @@ import {Question, Answer}from "/src/components/question" You need to now setup an instance of the SuperTokens core for your app (that your backend should connect to). You have two options: -- [Managed service](../quick-setup/core/saas-setup) -- Self hosted with your own database ([With Docker](../quick-setup/core/with-docker) or [Without Docker](../quick-setup/core/without-docker)) +- [Managed service](../../pre-built-ui/setup/core/saas-setup) +- Self hosted with your own database ([With Docker](../../pre-built-ui/setup/core/with-docker) or [Without Docker](../../pre-built-ui/setup/core/without-docker)) diff --git a/v2/passwordless/pre-built-ui/setup/core/self-hosted-with-aws.mdx b/v2/passwordless/pre-built-ui/setup/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/passwordless/pre-built-ui/setup/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/passwordless/pre-built-ui/setup/database-setup/mysql.mdx b/v2/passwordless/pre-built-ui/setup/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/passwordless/pre-built-ui/setup/database-setup/mysql.mdx +++ b/v2/passwordless/pre-built-ui/setup/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/passwordless/pre-built-ui/setup/database-setup/postgresql.mdx b/v2/passwordless/pre-built-ui/setup/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/passwordless/pre-built-ui/setup/database-setup/postgresql.mdx +++ b/v2/passwordless/pre-built-ui/setup/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/passwordless/rate-limits.mdx b/v2/passwordless/rate-limits.mdx index 8e8d895e2..a9943e7be 100644 --- a/v2/passwordless/rate-limits.mdx +++ b/v2/passwordless/rate-limits.mdx @@ -13,7 +13,7 @@ import CustomAdmonition from "/src/components/customAdmonition" ## For managed service -The SuperTokens core is rate limited on a per app and per IP address basis. This means that if query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). +The SuperTokens core is rate limited on a per app and per IP address basis. This means that if you query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). :::note To know more about rps and bursts, please [this nginx document](https://www.nginx.com/blog/rate-limiting-nginx/). diff --git a/v2/passwordless/sdks.mdx b/v2/passwordless/sdks.mdx index b155f32f5..a732bdfa0 100644 --- a/v2/passwordless/sdks.mdx +++ b/v2/passwordless/sdks.mdx @@ -60,6 +60,10 @@ import GuidesLink from "/src/components/guidesLink" - SuperTokens provides React based pre-built UI components, for other frontend frameworks you will need to build custom UI and use the `supertokens-web-js` SDK to communicate with the APIs exposed by the SuperTokens backend SDK. - For other backend frameworks, you can follow our [guide on how to spin up a separate server configured with the SuperTokens backend SDK](/docs/community/other-frameworks) to authenticate requests and issue session tokens. +## SDK Migration + +See the [updating SuperTokens](./updating-supertokens) page for steps on how to migrate SDKs. + :::info Visit the [API reference page](./apis) to learn more. ::: diff --git a/v2/passwordless/serverless/with-aws-lambda/setup-api-gateway.mdx b/v2/passwordless/serverless/with-aws-lambda/setup-api-gateway.mdx index 979ae839d..2ef50acaa 100644 --- a/v2/passwordless/serverless/with-aws-lambda/setup-api-gateway.mdx +++ b/v2/passwordless/serverless/with-aws-lambda/setup-api-gateway.mdx @@ -34,6 +34,12 @@ Click on the "ANY" method and then "Integration" to configure the lambda functio Configure lambda integration UI +:::important + +Ensure that the **Lambda proxy integration** toggle is turned on. + +::: + ## 4) Enable CORS for the proxy path Click on the `{proxy+}` resource and then "Enable CORS" button to open the CORS configuration page. diff --git a/v2/passwordless/sidebars.js b/v2/passwordless/sidebars.js index 8fb6c3c5c..f878ea8b9 100644 --- a/v2/passwordless/sidebars.js +++ b/v2/passwordless/sidebars.js @@ -33,7 +33,6 @@ module.exports = { items: [ "pre-built-ui/setup/core/with-docker", "pre-built-ui/setup/core/without-docker", - "pre-built-ui/setup/core/aws-setup-with-stacksnap", { type: "category", label: "Database Setup", @@ -108,7 +107,6 @@ module.exports = { items: [ "custom-ui/init/core/with-docker", "custom-ui/init/core/without-docker", - "custom-ui/init/core/aws-setup-with-stacksnap", { type: "category", label: "Database Setup", @@ -685,8 +683,8 @@ module.exports = { ], }, { - type: "category", - label: "Migration", + type: 'category', + label: 'Migrating to Supertokens', items: [ "migration/about", { @@ -703,6 +701,7 @@ module.exports = { "migration/mfa-migration", ], }, + "updating-supertokens", { type: "category", label: "References", diff --git a/v2/passwordless/updating-supertokens.mdx b/v2/passwordless/updating-supertokens.mdx new file mode 100644 index 000000000..b57bab619 --- /dev/null +++ b/v2/passwordless/updating-supertokens.mdx @@ -0,0 +1,65 @@ +--- +id: updating-supertokens +title: Updating Supertokens core and SDKs +hide_title: true +--- + + + + +# Updating SuperTokens core and SDKs + +:::important +You need to follow these steps in order to properly update supertokens +::: + +In order to maintain compatibility and keep up on new features, we recommend updating your core and SDKs whenever possible. + +## 1. Updating your core + +You will need to shut down your core in order to update it. After it's off, run the migration scripts for all versions inbetween +your starting version and the latest version. You may then bring your core back online. + +In the rare occasion that the supertokens core version you have updated to shows as incompatible with your current front-end and +back-end sdk's in the [compatibility table](./compatibility-table), then refrain from running your back-end and front-end SDKs until after you update them. + +- ### Self-hosted core +See the migration sections in the [supertokens-core changelog](https://github.com/supertokens/supertokens-core/blob/master/CHANGELOG.md). + +- ### Managed core +If you're using the managed core service, please email us at team@supertokens.com from your registered email to request a core update. + +## 2. Update your back-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### NodeJS +See the migration sections in the [supertokens-node changelog](https://github.com/supertokens/supertokens-node/blob/master/CHANGELOG.md). + +- ### GoLang +See the migration sections in the [supertokens-golang changelog](https://github.com/supertokens/supertokens-golang/blob/master/CHANGELOG.md). + +- ### Python +See the migration sections in the [supertokens-python changelog](https://github.com/supertokens/supertokens-python/blob/master/CHANGELOG.md). + +## 3. Update your front-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### ReactJS +See the migration sections in the [supertokens-auth-react changelog](https://github.com/supertokens/supertokens-auth-react/blob/master/CHANGELOG.md). + +- ### Vanilla JS +See the migration sections in the [supertokens-web-js changelog](https://github.com/supertokens/supertokens-web-js/blob/master/CHANGELOG.md). + +- ### React Native +See the migration sections in the [supertokens-react-native changelog](https://github.com/supertokens/supertokens-react-native/blob/master/CHANGELOG.md). + +- ### iOS +See the migration sections in the [supertokens-ios changelog](https://github.com/supertokens/supertokens-ios/blob/master/CHANGELOG.md). + +- ### Flutter +See the migration sections in the [supertokens-flutter changelog](https://github.com/supertokens/supertokens-flutter/blob/master/CHANGELOG.md). + +- ### Android +See the migration sections in the [supertokens-android changelog](https://github.com/supertokens/supertokens-android/blob/master/CHANGELOG.md). diff --git a/v2/session/quick-setup/core/self-hosted-with-aws.mdx b/v2/session/quick-setup/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/session/quick-setup/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/session/quick-setup/database-setup/mysql.mdx b/v2/session/quick-setup/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/session/quick-setup/database-setup/mysql.mdx +++ b/v2/session/quick-setup/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/session/quick-setup/database-setup/postgresql.mdx b/v2/session/quick-setup/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/session/quick-setup/database-setup/postgresql.mdx +++ b/v2/session/quick-setup/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/session/rate-limits.mdx b/v2/session/rate-limits.mdx index 8e8d895e2..a9943e7be 100644 --- a/v2/session/rate-limits.mdx +++ b/v2/session/rate-limits.mdx @@ -13,7 +13,7 @@ import CustomAdmonition from "/src/components/customAdmonition" ## For managed service -The SuperTokens core is rate limited on a per app and per IP address basis. This means that if query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). +The SuperTokens core is rate limited on a per app and per IP address basis. This means that if you query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). :::note To know more about rps and bursts, please [this nginx document](https://www.nginx.com/blog/rate-limiting-nginx/). diff --git a/v2/session/sdks.mdx b/v2/session/sdks.mdx index b155f32f5..a732bdfa0 100644 --- a/v2/session/sdks.mdx +++ b/v2/session/sdks.mdx @@ -60,6 +60,10 @@ import GuidesLink from "/src/components/guidesLink" - SuperTokens provides React based pre-built UI components, for other frontend frameworks you will need to build custom UI and use the `supertokens-web-js` SDK to communicate with the APIs exposed by the SuperTokens backend SDK. - For other backend frameworks, you can follow our [guide on how to spin up a separate server configured with the SuperTokens backend SDK](/docs/community/other-frameworks) to authenticate requests and issue session tokens. +## SDK Migration + +See the [updating SuperTokens](./updating-supertokens) page for steps on how to migrate SDKs. + :::info Visit the [API reference page](./apis) to learn more. ::: diff --git a/v2/session/serverless/with-aws-lambda/setup-api-gateway.mdx b/v2/session/serverless/with-aws-lambda/setup-api-gateway.mdx index 979ae839d..2ef50acaa 100644 --- a/v2/session/serverless/with-aws-lambda/setup-api-gateway.mdx +++ b/v2/session/serverless/with-aws-lambda/setup-api-gateway.mdx @@ -34,6 +34,12 @@ Click on the "ANY" method and then "Integration" to configure the lambda functio Configure lambda integration UI +:::important + +Ensure that the **Lambda proxy integration** toggle is turned on. + +::: + ## 4) Enable CORS for the proxy path Click on the `{proxy+}` resource and then "Enable CORS" button to open the CORS configuration page. diff --git a/v2/session/sidebars.js b/v2/session/sidebars.js index 196ffc7ea..795c274d1 100644 --- a/v2/session/sidebars.js +++ b/v2/session/sidebars.js @@ -25,7 +25,6 @@ module.exports = { items: [ "quick-setup/core/with-docker", "quick-setup/core/without-docker", - "quick-setup/core/aws-setup-with-stacksnap", { type: 'category', label: 'Database Setup', @@ -315,11 +314,12 @@ module.exports = { }, { type: 'category', - label: 'Migration', + label: 'Migrating to SuperTokens', items: [ "migration/session-migration", ], }, + "updating-supertokens", { type: "category", label: "References", diff --git a/v2/session/updating-supertokens.mdx b/v2/session/updating-supertokens.mdx new file mode 100644 index 000000000..b57bab619 --- /dev/null +++ b/v2/session/updating-supertokens.mdx @@ -0,0 +1,65 @@ +--- +id: updating-supertokens +title: Updating Supertokens core and SDKs +hide_title: true +--- + + + + +# Updating SuperTokens core and SDKs + +:::important +You need to follow these steps in order to properly update supertokens +::: + +In order to maintain compatibility and keep up on new features, we recommend updating your core and SDKs whenever possible. + +## 1. Updating your core + +You will need to shut down your core in order to update it. After it's off, run the migration scripts for all versions inbetween +your starting version and the latest version. You may then bring your core back online. + +In the rare occasion that the supertokens core version you have updated to shows as incompatible with your current front-end and +back-end sdk's in the [compatibility table](./compatibility-table), then refrain from running your back-end and front-end SDKs until after you update them. + +- ### Self-hosted core +See the migration sections in the [supertokens-core changelog](https://github.com/supertokens/supertokens-core/blob/master/CHANGELOG.md). + +- ### Managed core +If you're using the managed core service, please email us at team@supertokens.com from your registered email to request a core update. + +## 2. Update your back-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### NodeJS +See the migration sections in the [supertokens-node changelog](https://github.com/supertokens/supertokens-node/blob/master/CHANGELOG.md). + +- ### GoLang +See the migration sections in the [supertokens-golang changelog](https://github.com/supertokens/supertokens-golang/blob/master/CHANGELOG.md). + +- ### Python +See the migration sections in the [supertokens-python changelog](https://github.com/supertokens/supertokens-python/blob/master/CHANGELOG.md). + +## 3. Update your front-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### ReactJS +See the migration sections in the [supertokens-auth-react changelog](https://github.com/supertokens/supertokens-auth-react/blob/master/CHANGELOG.md). + +- ### Vanilla JS +See the migration sections in the [supertokens-web-js changelog](https://github.com/supertokens/supertokens-web-js/blob/master/CHANGELOG.md). + +- ### React Native +See the migration sections in the [supertokens-react-native changelog](https://github.com/supertokens/supertokens-react-native/blob/master/CHANGELOG.md). + +- ### iOS +See the migration sections in the [supertokens-ios changelog](https://github.com/supertokens/supertokens-ios/blob/master/CHANGELOG.md). + +- ### Flutter +See the migration sections in the [supertokens-flutter changelog](https://github.com/supertokens/supertokens-flutter/blob/master/CHANGELOG.md). + +- ### Android +See the migration sections in the [supertokens-android changelog](https://github.com/supertokens/supertokens-android/blob/master/CHANGELOG.md). diff --git a/v2/src/plugins/codeTypeChecking/jsEnv/package.json b/v2/src/plugins/codeTypeChecking/jsEnv/package.json index f1fa9be0b..2c0ce4097 100644 --- a/v2/src/plugins/codeTypeChecking/jsEnv/package.json +++ b/v2/src/plugins/codeTypeChecking/jsEnv/package.json @@ -56,13 +56,13 @@ "react-router-dom5": "npm:react-router-dom@^5.3.0", "socket.io": "^4.6.1", "socketio": "^1.0.0", - "supertokens-auth-react": "^0.44.0", - "supertokens-auth-react-script": "github:supertokens/supertokens-auth-react#0.44", + "supertokens-auth-react": "^0.46.0", + "supertokens-auth-react-script": "github:supertokens/supertokens-auth-react#0.46", "supertokens-node": "^20.0.0", "supertokens-node7": "npm:supertokens-node@7.3", "supertokens-react-native": "^5.0.0", - "supertokens-web-js": "^0.12.0", - "supertokens-web-js-script": "github:supertokens/supertokens-web-js#0.12", + "supertokens-web-js": "^0.13.0", + "supertokens-web-js-script": "github:supertokens/supertokens-web-js#0.13", "supertokens-website": "^20.0.1", "supertokens-website-script": "github:supertokens/supertokens-website#20.0", "typescript": "^4.9.5", diff --git a/v2/thirdparty/custom-ui/init/core/self-hosted-with-aws.mdx b/v2/thirdparty/custom-ui/init/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/thirdparty/custom-ui/init/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/thirdparty/custom-ui/init/database-setup/mysql.mdx b/v2/thirdparty/custom-ui/init/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/thirdparty/custom-ui/init/database-setup/mysql.mdx +++ b/v2/thirdparty/custom-ui/init/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/thirdparty/custom-ui/init/database-setup/postgresql.mdx b/v2/thirdparty/custom-ui/init/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/thirdparty/custom-ui/init/database-setup/postgresql.mdx +++ b/v2/thirdparty/custom-ui/init/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/thirdparty/nextjs/app-directory/next-steps.mdx b/v2/thirdparty/nextjs/app-directory/next-steps.mdx index 7de2c545f..20b4de6c9 100644 --- a/v2/thirdparty/nextjs/app-directory/next-steps.mdx +++ b/v2/thirdparty/nextjs/app-directory/next-steps.mdx @@ -21,8 +21,8 @@ import {Question, Answer}from "/src/components/question" You need to now setup an instance of the SuperTokens core for your app (that your backend should connect to). You have two options: -- [Managed service](../quick-setup/core/saas-setup) -- Self hosted with your own database ([With Docker](../quick-setup/core/with-docker) or [Without Docker](../quick-setup/core/without-docker)) +- [Managed service](../../pre-built-ui/setup/core/saas-setup) +- Self hosted with your own database ([With Docker](../../pre-built-ui/setup/core/with-docker) or [Without Docker](../../pre-built-ui/setup/core/without-docker)) diff --git a/v2/thirdparty/pre-built-ui/setup/core/self-hosted-with-aws.mdx b/v2/thirdparty/pre-built-ui/setup/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/thirdparty/pre-built-ui/setup/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/thirdparty/pre-built-ui/setup/database-setup/mysql.mdx b/v2/thirdparty/pre-built-ui/setup/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/thirdparty/pre-built-ui/setup/database-setup/mysql.mdx +++ b/v2/thirdparty/pre-built-ui/setup/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/thirdparty/pre-built-ui/setup/database-setup/postgresql.mdx b/v2/thirdparty/pre-built-ui/setup/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/thirdparty/pre-built-ui/setup/database-setup/postgresql.mdx +++ b/v2/thirdparty/pre-built-ui/setup/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/thirdparty/rate-limits.mdx b/v2/thirdparty/rate-limits.mdx index 8e8d895e2..a9943e7be 100644 --- a/v2/thirdparty/rate-limits.mdx +++ b/v2/thirdparty/rate-limits.mdx @@ -13,7 +13,7 @@ import CustomAdmonition from "/src/components/customAdmonition" ## For managed service -The SuperTokens core is rate limited on a per app and per IP address basis. This means that if query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). +The SuperTokens core is rate limited on a per app and per IP address basis. This means that if you query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). :::note To know more about rps and bursts, please [this nginx document](https://www.nginx.com/blog/rate-limiting-nginx/). diff --git a/v2/thirdparty/sdks.mdx b/v2/thirdparty/sdks.mdx index b155f32f5..a732bdfa0 100644 --- a/v2/thirdparty/sdks.mdx +++ b/v2/thirdparty/sdks.mdx @@ -60,6 +60,10 @@ import GuidesLink from "/src/components/guidesLink" - SuperTokens provides React based pre-built UI components, for other frontend frameworks you will need to build custom UI and use the `supertokens-web-js` SDK to communicate with the APIs exposed by the SuperTokens backend SDK. - For other backend frameworks, you can follow our [guide on how to spin up a separate server configured with the SuperTokens backend SDK](/docs/community/other-frameworks) to authenticate requests and issue session tokens. +## SDK Migration + +See the [updating SuperTokens](./updating-supertokens) page for steps on how to migrate SDKs. + :::info Visit the [API reference page](./apis) to learn more. ::: diff --git a/v2/thirdparty/serverless/with-aws-lambda/setup-api-gateway.mdx b/v2/thirdparty/serverless/with-aws-lambda/setup-api-gateway.mdx index 979ae839d..2ef50acaa 100644 --- a/v2/thirdparty/serverless/with-aws-lambda/setup-api-gateway.mdx +++ b/v2/thirdparty/serverless/with-aws-lambda/setup-api-gateway.mdx @@ -34,6 +34,12 @@ Click on the "ANY" method and then "Integration" to configure the lambda functio Configure lambda integration UI +:::important + +Ensure that the **Lambda proxy integration** toggle is turned on. + +::: + ## 4) Enable CORS for the proxy path Click on the `{proxy+}` resource and then "Enable CORS" button to open the CORS configuration page. diff --git a/v2/thirdparty/sidebars.js b/v2/thirdparty/sidebars.js index 8416b04d4..37b2f2c04 100644 --- a/v2/thirdparty/sidebars.js +++ b/v2/thirdparty/sidebars.js @@ -33,7 +33,6 @@ module.exports = { items: [ "pre-built-ui/setup/core/with-docker", "pre-built-ui/setup/core/without-docker", - "pre-built-ui/setup/core/aws-setup-with-stacksnap", { type: "category", label: "Database Setup", @@ -108,7 +107,6 @@ module.exports = { items: [ "custom-ui/init/core/with-docker", "custom-ui/init/core/without-docker", - "custom-ui/init/core/aws-setup-with-stacksnap", { type: "category", label: "Database Setup", @@ -697,8 +695,8 @@ module.exports = { ], }, { - type: "category", - label: "Migration", + type: 'category', + label: 'Migrating to Supertokens', items: [ "migration/about", { @@ -715,6 +713,7 @@ module.exports = { "migration/mfa-migration", ], }, + "updating-supertokens", { type: "category", label: "References", diff --git a/v2/thirdparty/updating-supertokens.mdx b/v2/thirdparty/updating-supertokens.mdx new file mode 100644 index 000000000..b57bab619 --- /dev/null +++ b/v2/thirdparty/updating-supertokens.mdx @@ -0,0 +1,65 @@ +--- +id: updating-supertokens +title: Updating Supertokens core and SDKs +hide_title: true +--- + + + + +# Updating SuperTokens core and SDKs + +:::important +You need to follow these steps in order to properly update supertokens +::: + +In order to maintain compatibility and keep up on new features, we recommend updating your core and SDKs whenever possible. + +## 1. Updating your core + +You will need to shut down your core in order to update it. After it's off, run the migration scripts for all versions inbetween +your starting version and the latest version. You may then bring your core back online. + +In the rare occasion that the supertokens core version you have updated to shows as incompatible with your current front-end and +back-end sdk's in the [compatibility table](./compatibility-table), then refrain from running your back-end and front-end SDKs until after you update them. + +- ### Self-hosted core +See the migration sections in the [supertokens-core changelog](https://github.com/supertokens/supertokens-core/blob/master/CHANGELOG.md). + +- ### Managed core +If you're using the managed core service, please email us at team@supertokens.com from your registered email to request a core update. + +## 2. Update your back-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### NodeJS +See the migration sections in the [supertokens-node changelog](https://github.com/supertokens/supertokens-node/blob/master/CHANGELOG.md). + +- ### GoLang +See the migration sections in the [supertokens-golang changelog](https://github.com/supertokens/supertokens-golang/blob/master/CHANGELOG.md). + +- ### Python +See the migration sections in the [supertokens-python changelog](https://github.com/supertokens/supertokens-python/blob/master/CHANGELOG.md). + +## 3. Update your front-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### ReactJS +See the migration sections in the [supertokens-auth-react changelog](https://github.com/supertokens/supertokens-auth-react/blob/master/CHANGELOG.md). + +- ### Vanilla JS +See the migration sections in the [supertokens-web-js changelog](https://github.com/supertokens/supertokens-web-js/blob/master/CHANGELOG.md). + +- ### React Native +See the migration sections in the [supertokens-react-native changelog](https://github.com/supertokens/supertokens-react-native/blob/master/CHANGELOG.md). + +- ### iOS +See the migration sections in the [supertokens-ios changelog](https://github.com/supertokens/supertokens-ios/blob/master/CHANGELOG.md). + +- ### Flutter +See the migration sections in the [supertokens-flutter changelog](https://github.com/supertokens/supertokens-flutter/blob/master/CHANGELOG.md). + +- ### Android +See the migration sections in the [supertokens-android changelog](https://github.com/supertokens/supertokens-android/blob/master/CHANGELOG.md). diff --git a/v2/thirdpartyemailpassword/custom-ui/init/core/self-hosted-with-aws.mdx b/v2/thirdpartyemailpassword/custom-ui/init/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/thirdpartyemailpassword/custom-ui/init/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/thirdpartyemailpassword/custom-ui/init/database-setup/mysql.mdx b/v2/thirdpartyemailpassword/custom-ui/init/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/thirdpartyemailpassword/custom-ui/init/database-setup/mysql.mdx +++ b/v2/thirdpartyemailpassword/custom-ui/init/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/thirdpartyemailpassword/custom-ui/init/database-setup/postgresql.mdx b/v2/thirdpartyemailpassword/custom-ui/init/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/thirdpartyemailpassword/custom-ui/init/database-setup/postgresql.mdx +++ b/v2/thirdpartyemailpassword/custom-ui/init/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/thirdpartyemailpassword/migration/account-creation/ep-migration-without-password-hash.mdx b/v2/thirdpartyemailpassword/migration/account-creation/ep-migration-without-password-hash.mdx index 1c20f5f40..8e555693d 100644 --- a/v2/thirdpartyemailpassword/migration/account-creation/ep-migration-without-password-hash.mdx +++ b/v2/thirdpartyemailpassword/migration/account-creation/ep-migration-without-password-hash.mdx @@ -36,7 +36,7 @@ We will need to make the following customizations to SuperTokens authentication ## Step 1) Prevent signups from users who exist in the external provider -To implement this change we will override the function that handles email-password login when initializing the `ThirdPartyEmailPassword` recipe on the backend. +To implement this change we will override the api that handles email-password login when initializing the recipe on the backend. @@ -46,18 +46,19 @@ import EmailPassword from "supertokens-node/recipe/emailpassword" EmailPassword.init({ override: { - functions: (originalImplementation) => { + apis: (originalImplementation) => { return { ...originalImplementation, - signUp: async function(input) { + signUpPOST: async function (input) { + let email = input.formFields.find((field) => field.id === "email")!.value; // Check if the user signing in exists in the external provider - if(await doesUserExistInExternalProvider(input.email)){ + if (await doesUserExistInExternalProvider(email)) { // Return status "EMAIL_ALREADY_EXISTS_ERROR" since the user already exists in the external provider return { status: "EMAIL_ALREADY_EXISTS_ERROR" } } - return originalImplementation.signUp(input); + return originalImplementation.signUpPOST!(input); }, } }, @@ -77,22 +78,40 @@ async function doesUserExistInExternalProvider(email: string): Promise ```python from supertokens_python import init, InputAppInfo from supertokens_python.recipe import emailpassword -from supertokens_python.recipe.emailpassword.interfaces import RecipeInterface, SignUpOkResult, SignUpEmailAlreadyExistsError -from typing import Dict, Any, Union +from supertokens_python.recipe.emailpassword.interfaces import ( + APIInterface, + SignUpPostOkResult, + SignUpPostEmailAlreadyExistsError, + APIOptions, +) +from supertokens_python.types import GeneralErrorResponse +from supertokens_python.recipe.emailpassword.types import FormField +from typing import Dict, Any, Union, List -def override_email_password_functions(original_implementation: RecipeInterface): - original_sign_up = original_implementation.sign_up +def override_email_password_apis(original_implementation: APIInterface): + original_sign_up = original_implementation.sign_up_post - async def sign_up(email: str, password: str, tenant_id: str, user_context: Dict[str, Any]) -> Union[SignUpOkResult, SignUpEmailAlreadyExistsError]: + async def sign_up( + form_fields: List[FormField], + tenant_id: str, + api_options: APIOptions, + user_context: Dict[str, Any], + ) -> Union[ + SignUpPostOkResult, SignUpPostEmailAlreadyExistsError, GeneralErrorResponse + ]: + email = "" + for field in form_fields: + if field.id == "email": + email = field.value # check if the user signing in exists in the external provider if await does_user_exist_in_external_provider(email): # Return SignUpEmailAlreadyExistsError since the user exists in the external provider - return SignUpEmailAlreadyExistsError() + return SignUpPostEmailAlreadyExistsError() - return await original_sign_up(email, password, tenant_id, user_context) + return await original_sign_up(form_fields, tenant_id, api_options, user_context) - original_implementation.sign_up = sign_up + original_implementation.sign_up_post = sign_up return original_implementation @@ -102,16 +121,15 @@ async def does_user_exist_in_external_provider(email: str): init( - app_info=InputAppInfo( - api_domain="...", app_name="...", website_domain="..."), - framework='...', # type: ignore + app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."), + framework="...", # type: ignore recipe_list=[ emailpassword.init( override=emailpassword.InputOverrideConfig( - functions=override_email_password_functions, + apis=override_email_password_apis, ) ) - ] + ], ) ``` @@ -131,21 +149,27 @@ func main() { RecipeList: []supertokens.Recipe{ emailpassword.Init(&epmodels.TypeInput{ Override: &epmodels.OverrideStruct{ - Functions: func(originalImplementation epmodels.RecipeInterface) epmodels.RecipeInterface { + APIs: func(originalImplementation epmodels.APIInterface) epmodels.APIInterface { // Copy the original implementation of the signUp function - originalSignUp := *originalImplementation.SignUp + originalSignUp := *originalImplementation.SignUpPOST // Override the signUp function - (*originalImplementation.SignUp) = func(email, password string, tenantId string, userContext supertokens.UserContext) (epmodels.SignUpResponse, error) { + (*originalImplementation.SignUpPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.SignUpPOSTResponse, error) { + email := "" + for _, formField := range formFields { + if formField.ID == "email" { + email = formField.Value + } + } // Check if the user signing in exists in the external provider if doesUserExistInExternalProvider(email) { // Return status "EMAIL_ALREADY_EXISTS_ERROR" since the user already exists in the external provider - return epmodels.SignUpResponse{ + return epmodels.SignUpPOSTResponse{ EmailAlreadyExistsError: &struct{}{}, }, nil } - return originalSignUp(email, password, tenantId, userContext) + return originalSignUp(formFields, tenantId, options, userContext) } return originalImplementation }, @@ -165,11 +189,11 @@ func doesUserExistInExternalProvider(email string) bool { -We modify the `signUp` function to first check if the user signing up has an account with the external provider. If they do we return a `EMAIL_ALREADY_EXISTS_ERROR` +We modify the `signUpPOST` API to first check if the user signing up has an account with the external provider. If they do we return a `EMAIL_ALREADY_EXISTS_ERROR` ## Step 2) Create a SuperTokens account for users trying to sign in if they have an account with the external provider -To implement this flow we will override the function that handles email-password login when initializing the `ThirdPartyEmailPassword` recipe on the backend. +To implement this flow we will override the API that handles email-password login when initializing the recipe on the backend. @@ -182,22 +206,24 @@ import { RecipeUserId } from "supertokens-node"; EmailPassword.init({ override: { - functions: (originalImplementation) => { + apis: (originalImplementation) => { return { ...originalImplementation, - signIn: async function (input) { + signInPOST: async function (input) { // Check if an email-password user with the input email exists in SuperTokens + let email = input.formFields.find((field) => field.id === "email")!.value; + let password = input.formFields.find((field) => field.id === "password")!.value; let supertokensUsersWithSameEmail = await SuperTokens.listUsersByAccountInfo(input.tenantId, { - email: input.email + email: email }, undefined, input.userContext); let emailPasswordUser = supertokensUsersWithSameEmail.find(u => { - return u.loginMethods.find(lM => lM.hasSameEmailAs(input.email) && lM.recipeId === "emailpassword") !== undefined; + return u.loginMethods.find(lM => lM.hasSameEmailAs(email) && lM.recipeId === "emailpassword") !== undefined; }) if (emailPasswordUser === undefined) { // EmailPassword user with the input email does not exist in SuperTokens // Check if the input credentials are valid in the external provider - let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(input.email, input.password) + let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(email, password) if (legacyUserInfo === undefined) { // credentials are incorrect return { @@ -206,14 +232,14 @@ EmailPassword.init({ } // Call the signup function to create a new SuperTokens user. - let signUpResponse = await EmailPassword.signUp(input.tenantId, input.email, input.password, undefined, input.userContext); + let signUpResponse = await EmailPassword.signUp(input.tenantId, email, password, undefined, input.userContext); if (signUpResponse.status !== "OK") { throw new Error("Should never come here") } // Map the external provider's userId to the SuperTokens userId await SuperTokens.createUserIdMapping({ superTokensUserId: signUpResponse.user.id, externalUserId: legacyUserInfo.user_id }) - + // Set the userId in the response to use the provider's userId signUpResponse.user.id = legacyUserInfo.user_id signUpResponse.user.loginMethods[0].recipeUserId = new RecipeUserId(legacyUserInfo.user_id); @@ -221,18 +247,16 @@ EmailPassword.init({ // We will also need to set the email verification status of the user if (legacyUserInfo.isEmailVerified) { // Generate an email verification token for the user - let generateEmailVerificationTokenResponse = await EmailVerification.createEmailVerificationToken(input.tenantId, signUpResponse.recipeUserId, input.email, input.userContext); + let generateEmailVerificationTokenResponse = await EmailVerification.createEmailVerificationToken(input.tenantId, signUpResponse.recipeUserId, email, input.userContext); if (generateEmailVerificationTokenResponse.status === "OK") { // Verify the user's email await EmailVerification.verifyEmailUsingToken("public", generateEmailVerificationTokenResponse.token, undefined, input.userContext); } } - - return signUpResponse; } - return originalImplementation.signIn(input) + return originalImplementation.signInPOST!(input) }, } }, @@ -256,17 +280,48 @@ async function validateAndGetUserInfoFromExternalProvider(email: string, passwor from supertokens_python import init, InputAppInfo from supertokens_python.recipe import emailpassword from supertokens_python.asyncio import create_user_id_mapping -from supertokens_python.recipe.emailverification.asyncio import create_email_verification_token, verify_email_using_token +from supertokens_python.recipe.emailverification.asyncio import ( + create_email_verification_token, + verify_email_using_token, +) from supertokens_python.recipe.emailpassword.asyncio import get_user_by_email, sign_up -from supertokens_python.recipe.emailpassword.interfaces import RecipeInterface, SignInOkResult, SignInWrongCredentialsError, SignUpEmailAlreadyExistsError -from supertokens_python.recipe.emailverification.interfaces import CreateEmailVerificationTokenOkResult -from typing import Dict, Any, Union +from supertokens_python.recipe.emailpassword.interfaces import ( + SignUpEmailAlreadyExistsError, +) +from supertokens_python.recipe.emailverification.interfaces import ( + CreateEmailVerificationTokenOkResult, +) +from supertokens_python import init, InputAppInfo +from supertokens_python.recipe import emailpassword +from supertokens_python.recipe.emailpassword.interfaces import ( + APIInterface, + SignInPostOkResult, + SignInPostWrongCredentialsError, + APIOptions, +) +from supertokens_python.types import GeneralErrorResponse +from supertokens_python.recipe.emailpassword.types import FormField +from typing import Dict, Any, Union, List -def override_emailpassword_functions(original_implementation: RecipeInterface): - original_emailpassword_sign_in = original_implementation.sign_in +def override_emailpassword_apis(original_implementation: APIInterface): + original_emailpassword_sign_in = original_implementation.sign_in_post - async def sign_in(email: str, password: str, tenant_id: str, user_context: Dict[str, Any]) -> Union[SignInOkResult, SignInWrongCredentialsError]: + async def sign_in( + form_fields: List[FormField], + tenant_id: str, + api_options: APIOptions, + user_context: Dict[str, Any], + ) -> Union[ + SignInPostOkResult, SignInPostWrongCredentialsError, GeneralErrorResponse + ]: + email = "" + password = "" + for field in form_fields: + if field.id == "email": + email = field.value + if field.id == "password": + password = field.value # Check if an email-password user with the input email exists in SuperTokens emailpassword_user = await get_user_by_email(tenant_id, email, user_context) @@ -274,10 +329,11 @@ def override_emailpassword_functions(original_implementation: RecipeInterface): # EmailPassword user with the input email does not exist in SuperTokens # Check if the input credentials valid in the external provider legacy_user_info = await validate_and_get_user_info_from_external_provider( - email, password) + email, password + ) if legacy_user_info is None: # Credentials are incorrect - return SignInWrongCredentialsError() + return SignInPostWrongCredentialsError() # Call the sign_up function to create a new SuperTokens user. response = await sign_up(email, password, tenant_id, user_context) @@ -285,32 +341,38 @@ def override_emailpassword_functions(original_implementation: RecipeInterface): raise Exception("Should never come here") # Map the external provider's userId to the SuperTokens userId - await create_user_id_mapping(response.user.user_id, - legacy_user_info.user_id) + await create_user_id_mapping( + response.user.user_id, legacy_user_info.user_id + ) # Set the userId in the response to use the provider's userId response.user.user_id = legacy_user_info.user_id # We will also need to set the email verification status of the user if legacy_user_info.isEmailVerified: # Generate an email verification token for the user - generate_email_verification_response = await create_email_verification_token( - tenant_id, - response.user.user_id, - email, - user_context, + generate_email_verification_response = ( + await create_email_verification_token( + tenant_id, + response.user.user_id, + email, + user_context, + ) ) - if isinstance(generate_email_verification_response, CreateEmailVerificationTokenOkResult): + if isinstance( + generate_email_verification_response, + CreateEmailVerificationTokenOkResult, + ): await verify_email_using_token( tenant_id, - generate_email_verification_response.token, + generate_email_verification_response.token, user_context, ) - return SignInOkResult(response.user) - - return await original_emailpassword_sign_in(email, password, tenant_id, user_context) + return await original_emailpassword_sign_in( + form_fields, tenant_id, api_options, user_context + ) - original_implementation.sign_in = sign_in + original_implementation.sign_in_post = sign_in return original_implementation @@ -320,21 +382,20 @@ class ExternalUserInfo: self.isEmailVerified: bool = isEmailVerified -async def validate_and_get_user_info_from_external_provider(email: str, password: str) -> Union[None, ExternalUserInfo]: +async def validate_and_get_user_info_from_external_provider( + email: str, password: str +) -> Union[None, ExternalUserInfo]: return None init( - app_info=InputAppInfo( - api_domain="...", app_name="...", website_domain="..."), - framework='...', # type: ignore + app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."), + framework="...", # type: ignore recipe_list=[ emailpassword.init( - override=emailpassword.InputOverrideConfig( - functions=override_emailpassword_functions - ) + override=emailpassword.InputOverrideConfig(apis=override_emailpassword_apis) ) - ] + ], ) ``` @@ -357,18 +418,28 @@ func main() { RecipeList: []supertokens.Recipe{ emailpassword.Init(&epmodels.TypeInput{ Override: &epmodels.OverrideStruct{ - Functions: func(originalImplementation epmodels.RecipeInterface) epmodels.RecipeInterface { + APIs: func(originalImplementation epmodels.APIInterface) epmodels.APIInterface { // Copy the original implementation of the signIn function - originalSignIn := *originalImplementation.SignIn + originalSignIn := *originalImplementation.SignInPOST // Override the function - (*originalImplementation.SignIn) = func(email, password, tenantId string, userContext supertokens.UserContext) (epmodels.SignInResponse, error) { + (*originalImplementation.SignInPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.SignInPOSTResponse, error) { + email := "" + password := "" + for _, formField := range formFields { + if formField.ID == "email" { + email = formField.Value + } + if formField.ID == "password" { + password = formField.Value + } + } // Check if an email-password user with the input email exists in SuperTokens emailPasswordUser, err := emailpassword.GetUserByEmail(tenantId, email) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if emailPasswordUser == nil { @@ -377,7 +448,7 @@ func main() { legacyUserInfo := validateAndGetUserInfoFromExternalProvider(email, password) if legacyUserInfo == nil { - return epmodels.SignInResponse{ + return epmodels.SignInPOSTResponse{ WrongCredentialsError: &struct{}{}, }, nil } @@ -385,17 +456,17 @@ func main() { // Call the email-password signup function to create a new SuperTokens user. response, err := emailpassword.SignUp(tenantId, email, password) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if response.OK == nil { - return epmodels.SignInResponse{}, errors.New("Should never come here") + return epmodels.SignInPOSTResponse{}, errors.New("Should never come here") } // Map the external provider's userId to the SuperTokens userId _, err = supertokens.CreateUserIdMapping(response.OK.User.ID, legacyUserInfo.userId, nil, nil) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } // Set the userId in the response to use the provider's userId response.OK.User.ID = legacyUserInfo.userId @@ -405,7 +476,7 @@ func main() { // Generate an email verification token for the user generateEmailVerificationTokenResponse, err := emailverification.CreateEmailVerificationToken(tenantId, response.OK.User.ID, &email) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if generateEmailVerificationTokenResponse.OK != nil { @@ -413,14 +484,9 @@ func main() { emailverification.VerifyEmailUsingToken(tenantId, generateEmailVerificationTokenResponse.OK.Token) } } - - return epmodels.SignInResponse{ - OK: &struct{ User epmodels.User }{response.OK.User}, - }, nil - } - return originalSignIn(email, password, tenantId, userContext) + return originalSignIn(formFields, tenantId, options, userContext) } return originalImplementation @@ -446,7 +512,7 @@ func validateAndGetUserInfoFromExternalProvider(email string, password string) * -The code above overrides the `signIn` function with the following changes to achieve "**just in time**" migration: +The code above overrides the `signInPOST` API with the following changes to achieve "**just in time**" migration: - The first step is to determine if the user signing in needs to be migrated or not. We do this by checking if a user with the input email exists in the external auth provider and SuperTokens. If the user exists in the external auth provider and does not exist SuperTokens, we can determine that this user needs to be migrated. - The next step is to validate the input credentials against the external provider. If the credentials are invalid we will throw a `WRONG_CREDENTIALS_ERROR`. @@ -471,15 +537,10 @@ import UserMetadata from "supertokens-node/recipe/usermetadata" EmailPassword.init({ override: { - functions: (originalImplementation) => { - return { - ...originalImplementation, - // TODO: implementation details in previous step - } - }, apis: (originalImplementation) => { return { ...originalImplementation, + // Add overrides from the previous step generatePasswordResetTokenPOST: async (input) => { // Retrieve the email from the input let email = input.formFields.find(i => i.id === "email")!.value; @@ -828,12 +889,6 @@ import UserMetadata from "supertokens-node/recipe/usermetadata" EmailPassword.init({ override: { - functions: (originalImplementaion) => { - return { - ...originalImplementaion - // TODO: implentation details in previous step - } - }, apis: (originalImplementation) => { return { ...originalImplementation, @@ -1015,22 +1070,24 @@ import { RecipeUserId } from "supertokens-node"; EmailPassword.init({ override: { - functions: (originalImplementation) => { + apis: (originalImplementation) => { return { ...originalImplementation, - signIn: async function (input) { + signInPOST: async function (input) { // Check if an email-password user with the input email exists in SuperTokens + let email = input.formFields.find((field) => field.id === "email")!.value; + let password = input.formFields.find((field) => field.id === "password")!.value; let supertokensUsersWithSameEmail = await SuperTokens.listUsersByAccountInfo(input.tenantId, { - email: input.email + email: email }, undefined, input.userContext); let emailPasswordUser = supertokensUsersWithSameEmail.find(u => { - return u.loginMethods.find(lM => lM.hasSameEmailAs(input.email) && lM.recipeId === "emailpassword") !== undefined; + return u.loginMethods.find(lM => lM.hasSameEmailAs(email) && lM.recipeId === "emailpassword") !== undefined; }) if (emailPasswordUser === undefined) { // EmailPassword user with the input email does not exist in SuperTokens // Check if the input credentials are valid in the external provider - let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(input.email, input.password) + let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(email, password) if (legacyUserInfo === undefined) { // credentials are incorrect return { @@ -1039,7 +1096,7 @@ EmailPassword.init({ } // Call the signup function to create a new SuperTokens user. - let signUpResponse = await EmailPassword.signUp(input.tenantId, input.email, input.password, undefined, input.userContext); + let signUpResponse = await EmailPassword.signUp(input.tenantId, email, password, undefined, input.userContext); if (signUpResponse.status !== "OK") { throw new Error("Should never come here") } @@ -1053,47 +1110,41 @@ EmailPassword.init({ // We will also need to set the email verification status of the user if (legacyUserInfo.isEmailVerified) { // Generate an email verification token for the user - let generateEmailVerificationTokenResponse = await EmailVerification.createEmailVerificationToken(input.tenantId, signUpResponse.recipeUserId, input.email, input.userContext); + let generateEmailVerificationTokenResponse = await EmailVerification.createEmailVerificationToken(input.tenantId, signUpResponse.recipeUserId, email, input.userContext); if (generateEmailVerificationTokenResponse.status === "OK") { // Verify the user's email await EmailVerification.verifyEmailUsingToken("public", generateEmailVerificationTokenResponse.token, undefined, input.userContext); } } - - return signUpResponse; + emailPasswordUser = signUpResponse.user; } // highlight-start // Check if the user signing in has a temporary password let userMetadata = await UserMetadata.getUserMetadata(emailPasswordUser.id, input.userContext) if (userMetadata.status === "OK" && userMetadata.metadata.isUsingTemporaryPassword) { // Check if the input credentials are valid in the external provider - let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(input.email, input.password); + let legacyUserInfo = await validateAndGetUserInfoFromExternalProvider(email, password); if (legacyUserInfo) { - let loginMethod = emailPasswordUser.loginMethods.find(lM => lM.recipeId === "emailpassword" && lM.hasSameEmailAs(input.email)); + let loginMethod = emailPasswordUser.loginMethods.find(lM => lM.recipeId === "emailpassword" && lM.hasSameEmailAs(email)); // Update the user's password with the correct password EmailPassword.updateEmailOrPassword({ recipeUserId: loginMethod!.recipeUserId, - password: input.password, + password: password, applyPasswordPolicy: false }) // Update the user's metadata to remove the isUsingTemporaryPassword flag UserMetadata.updateUserMetadata(emailPasswordUser.id, { isUsingTemporaryPassword: null }) - + } else { return { - status: "OK", - user: emailPasswordUser, - recipeUserId: loginMethod!.recipeUserId + status: "WRONG_CREDENTIALS_ERROR" } } - return { - status: "WRONG_CREDENTIALS_ERROR" - } } // highlight-end - return originalImplementation.signIn(input) + return originalImplementation.signInPOST!(input) }, } }, @@ -1116,10 +1167,6 @@ async function validateAndGetUserInfoFromExternalProvider(email: string, passwor from supertokens_python import init, InputAppInfo from supertokens_python.recipe import emailpassword from supertokens_python.asyncio import create_user_id_mapping -from supertokens_python.recipe.usermetadata.asyncio import ( - get_user_metadata, - update_user_metadata, -) from supertokens_python.recipe.emailverification.asyncio import ( create_email_verification_token, verify_email_using_token, @@ -1130,23 +1177,46 @@ from supertokens_python.recipe.emailpassword.asyncio import ( update_email_or_password, ) from supertokens_python.recipe.emailpassword.interfaces import ( - RecipeInterface, - SignInOkResult, - SignInWrongCredentialsError, SignUpEmailAlreadyExistsError, ) from supertokens_python.recipe.emailverification.interfaces import ( CreateEmailVerificationTokenOkResult, ) -from typing import Dict, Any, Union +from supertokens_python import init, InputAppInfo +from supertokens_python.recipe import emailpassword +from supertokens_python.recipe.emailpassword.interfaces import ( + APIInterface, + SignInPostOkResult, + SignInPostWrongCredentialsError, + APIOptions, +) +from supertokens_python.types import GeneralErrorResponse +from supertokens_python.recipe.emailpassword.types import FormField +from typing import Dict, Any, Union, List +from supertokens_python.recipe.usermetadata.asyncio import ( + get_user_metadata, + update_user_metadata, +) -def override_emailpassword_functions(original_implementation: RecipeInterface): - original_emailpassword_sign_in = original_implementation.sign_in +def override_emailpassword_apis(original_implementation: APIInterface): + original_emailpassword_sign_in = original_implementation.sign_in_post - async def emailpassword_sign_in( - email: str, password: str, tenant_id: str, user_context: Dict[str, Any] - ) -> Union[SignInOkResult, SignInWrongCredentialsError]: + async def sign_in( + form_fields: List[FormField], + tenant_id: str, + api_options: APIOptions, + user_context: Dict[str, Any], + ) -> Union[ + SignInPostOkResult, SignInPostWrongCredentialsError, GeneralErrorResponse + ]: + email = "" + password = "" + for field in form_fields: + if field.id == "email": + email = field.value + if field.id == "password": + password = field.value # Check if an email-password user with the input email exists in SuperTokens emailpassword_user = await get_user_by_email(tenant_id, email, user_context) @@ -1158,7 +1228,7 @@ def override_emailpassword_functions(original_implementation: RecipeInterface): ) if legacy_user_info is None: # Credentials are incorrect - return SignInWrongCredentialsError() + return SignInPostWrongCredentialsError() # Call the sign_up function to create a new SuperTokens user. response = await sign_up(email, password, tenant_id, user_context) @@ -1190,8 +1260,7 @@ def override_emailpassword_functions(original_implementation: RecipeInterface): user_context, ) - return SignInOkResult(response.user) - + emailpassword_user = response.user # highlight-start # Check if the user signing in has a temporary password metadata_result = await get_user_metadata(emailpassword_user.user_id) @@ -1217,15 +1286,15 @@ def override_emailpassword_functions(original_implementation: RecipeInterface): await update_user_metadata( emailpassword_user.user_id, {"isUsingTemporaryPassword": None} ) - return SignInOkResult(emailpassword_user) - return SignInWrongCredentialsError() + else: + return SignInPostWrongCredentialsError() # highlight-end return await original_emailpassword_sign_in( - email, password, tenant_id, user_context + form_fields, tenant_id, api_options, user_context ) - original_implementation.sign_in = emailpassword_sign_in + original_implementation.sign_in_post = sign_in return original_implementation @@ -1246,9 +1315,7 @@ init( framework="...", # type: ignore recipe_list=[ emailpassword.init( - override=emailpassword.InputOverrideConfig( - functions=override_emailpassword_functions - ) + override=emailpassword.InputOverrideConfig(apis=override_emailpassword_apis) ) ], ) @@ -1274,18 +1341,28 @@ func main() { RecipeList: []supertokens.Recipe{ emailpassword.Init(&epmodels.TypeInput{ Override: &epmodels.OverrideStruct{ - Functions: func(originalImplementation epmodels.RecipeInterface) epmodels.RecipeInterface { + APIs: func(originalImplementation epmodels.APIInterface) epmodels.APIInterface { // Copy the original implementation of the signIn function - originalSignIn := *originalImplementation.SignIn + originalSignIn := *originalImplementation.SignInPOST // Override the function - (*originalImplementation.SignIn) = func(email, password, tenantId string, userContext supertokens.UserContext) (epmodels.SignInResponse, error) { + (*originalImplementation.SignInPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.SignInPOSTResponse, error) { + email := "" + password := "" + for _, formField := range formFields { + if formField.ID == "email" { + email = formField.Value + } + if formField.ID == "password" { + password = formField.Value + } + } // Check if an email-password user with the input email exists in SuperTokens emailPasswordUser, err := emailpassword.GetUserByEmail(tenantId, email) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if emailPasswordUser == nil { @@ -1294,7 +1371,7 @@ func main() { legacyUserInfo := validateAndGetUserInfoFromExternalProvider(email, password) if legacyUserInfo == nil { - return epmodels.SignInResponse{ + return epmodels.SignInPOSTResponse{ WrongCredentialsError: &struct{}{}, }, nil } @@ -1302,11 +1379,11 @@ func main() { // Call the email-password signup function to create a new SuperTokens user. response, err := emailpassword.SignUp(tenantId, email, password) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if response.OK == nil { - return epmodels.SignInResponse{}, errors.New("Should never come here") + return epmodels.SignInPOSTResponse{}, errors.New("Should never come here") } // Map the external provider's userId to the SuperTokens userId @@ -1319,29 +1396,25 @@ func main() { // Generate an email verification token for the user generateEmailVerificationTokenResponse, err := emailverification.CreateEmailVerificationToken(tenantId, response.OK.User.ID, &email) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } if generateEmailVerificationTokenResponse.OK != nil { // Verify the user's email _, err = emailverification.VerifyEmailUsingToken(tenantId, generateEmailVerificationTokenResponse.OK.Token) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } } } - - return epmodels.SignInResponse{ - OK: &struct{ User epmodels.User }{response.OK.User}, - }, nil - + emailPasswordUser = &response.OK.User } // Check if the user signing in has a temporary password metadata, err := usermetadata.GetUserMetadata(emailPasswordUser.ID) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } isUsingTemporaryPassword, ok := metadata["isUsingTemporaryPassword"] @@ -1354,7 +1427,7 @@ func main() { usePasswordPolicy := false _, err = emailpassword.UpdateEmailOrPassword(emailPasswordUser.ID, nil, &password, &usePasswordPolicy, &tenantId) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } // Update the user's metadata to remove the isUsingTemporaryPassword flag @@ -1362,20 +1435,16 @@ func main() { "isUsingTemporaryPassword": nil, }) if err != nil { - return epmodels.SignInResponse{}, err + return epmodels.SignInPOSTResponse{}, err } - - return epmodels.SignInResponse{ - OK: &struct{ User epmodels.User }{*emailPasswordUser}, + } else { + return epmodels.SignInPOSTResponse{ + WrongCredentialsError: &struct{}{}, }, nil } - - return epmodels.SignInResponse{ - WrongCredentialsError: &struct{}{}, - }, nil } - return originalSignIn(email, password, tenantId, userContext) + return originalSignIn(formFields, tenantId, options, userContext) } return originalImplementation @@ -1402,7 +1471,7 @@ func validateAndGetUserInfoFromExternalProvider(email string, password string) * -The code above adds the following changes to the `signIn` function: +The code above adds the following changes to the `signInPOST` API: - Adds an additional check where if a user exists in SuperTokens, we check if they have the `isUsingTemporaryPassword` flag set in their metadata. - If the flag exists, we check if the input credentials are valid in the external provider. If they are we update the account with the new password and continue the login flow. diff --git a/v2/thirdpartyemailpassword/nextjs/app-directory/next-steps.mdx b/v2/thirdpartyemailpassword/nextjs/app-directory/next-steps.mdx index 7de2c545f..20b4de6c9 100644 --- a/v2/thirdpartyemailpassword/nextjs/app-directory/next-steps.mdx +++ b/v2/thirdpartyemailpassword/nextjs/app-directory/next-steps.mdx @@ -21,8 +21,8 @@ import {Question, Answer}from "/src/components/question" You need to now setup an instance of the SuperTokens core for your app (that your backend should connect to). You have two options: -- [Managed service](../quick-setup/core/saas-setup) -- Self hosted with your own database ([With Docker](../quick-setup/core/with-docker) or [Without Docker](../quick-setup/core/without-docker)) +- [Managed service](../../pre-built-ui/setup/core/saas-setup) +- Self hosted with your own database ([With Docker](../../pre-built-ui/setup/core/with-docker) or [Without Docker](../../pre-built-ui/setup/core/without-docker)) diff --git a/v2/thirdpartyemailpassword/pre-built-ui/setup/core/self-hosted-with-aws.mdx b/v2/thirdpartyemailpassword/pre-built-ui/setup/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/thirdpartyemailpassword/pre-built-ui/setup/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/thirdpartyemailpassword/pre-built-ui/setup/database-setup/mysql.mdx b/v2/thirdpartyemailpassword/pre-built-ui/setup/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/thirdpartyemailpassword/pre-built-ui/setup/database-setup/mysql.mdx +++ b/v2/thirdpartyemailpassword/pre-built-ui/setup/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/thirdpartyemailpassword/pre-built-ui/setup/database-setup/postgresql.mdx b/v2/thirdpartyemailpassword/pre-built-ui/setup/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/thirdpartyemailpassword/pre-built-ui/setup/database-setup/postgresql.mdx +++ b/v2/thirdpartyemailpassword/pre-built-ui/setup/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/thirdpartyemailpassword/rate-limits.mdx b/v2/thirdpartyemailpassword/rate-limits.mdx index 8e8d895e2..a9943e7be 100644 --- a/v2/thirdpartyemailpassword/rate-limits.mdx +++ b/v2/thirdpartyemailpassword/rate-limits.mdx @@ -13,7 +13,7 @@ import CustomAdmonition from "/src/components/customAdmonition" ## For managed service -The SuperTokens core is rate limited on a per app and per IP address basis. This means that if query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). +The SuperTokens core is rate limited on a per app and per IP address basis. This means that if you query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). :::note To know more about rps and bursts, please [this nginx document](https://www.nginx.com/blog/rate-limiting-nginx/). diff --git a/v2/thirdpartyemailpassword/sdks.mdx b/v2/thirdpartyemailpassword/sdks.mdx index b155f32f5..a732bdfa0 100644 --- a/v2/thirdpartyemailpassword/sdks.mdx +++ b/v2/thirdpartyemailpassword/sdks.mdx @@ -60,6 +60,10 @@ import GuidesLink from "/src/components/guidesLink" - SuperTokens provides React based pre-built UI components, for other frontend frameworks you will need to build custom UI and use the `supertokens-web-js` SDK to communicate with the APIs exposed by the SuperTokens backend SDK. - For other backend frameworks, you can follow our [guide on how to spin up a separate server configured with the SuperTokens backend SDK](/docs/community/other-frameworks) to authenticate requests and issue session tokens. +## SDK Migration + +See the [updating SuperTokens](./updating-supertokens) page for steps on how to migrate SDKs. + :::info Visit the [API reference page](./apis) to learn more. ::: diff --git a/v2/thirdpartyemailpassword/serverless/with-aws-lambda/setup-api-gateway.mdx b/v2/thirdpartyemailpassword/serverless/with-aws-lambda/setup-api-gateway.mdx index 979ae839d..2ef50acaa 100644 --- a/v2/thirdpartyemailpassword/serverless/with-aws-lambda/setup-api-gateway.mdx +++ b/v2/thirdpartyemailpassword/serverless/with-aws-lambda/setup-api-gateway.mdx @@ -34,6 +34,12 @@ Click on the "ANY" method and then "Integration" to configure the lambda functio Configure lambda integration UI +:::important + +Ensure that the **Lambda proxy integration** toggle is turned on. + +::: + ## 4) Enable CORS for the proxy path Click on the `{proxy+}` resource and then "Enable CORS" button to open the CORS configuration page. diff --git a/v2/thirdpartyemailpassword/sidebars.js b/v2/thirdpartyemailpassword/sidebars.js index d152f3063..d3e5dbd88 100644 --- a/v2/thirdpartyemailpassword/sidebars.js +++ b/v2/thirdpartyemailpassword/sidebars.js @@ -33,7 +33,6 @@ module.exports = { items: [ "pre-built-ui/setup/core/with-docker", "pre-built-ui/setup/core/without-docker", - "pre-built-ui/setup/core/aws-setup-with-stacksnap", { type: "category", label: "Database Setup", @@ -111,7 +110,6 @@ module.exports = { items: [ "custom-ui/init/core/with-docker", "custom-ui/init/core/without-docker", - "custom-ui/init/core/aws-setup-with-stacksnap", { type: "category", label: "Database Setup", @@ -746,8 +744,8 @@ module.exports = { ], }, { - type: "category", - label: "Migration", + type: 'category', + label: 'Migrating to Supertokens', items: [ "migration/about", { @@ -765,6 +763,7 @@ module.exports = { "migration/mfa-migration", ], }, + "updating-supertokens", { type: "category", label: "References", diff --git a/v2/thirdpartyemailpassword/updating-supertokens.mdx b/v2/thirdpartyemailpassword/updating-supertokens.mdx new file mode 100644 index 000000000..b57bab619 --- /dev/null +++ b/v2/thirdpartyemailpassword/updating-supertokens.mdx @@ -0,0 +1,65 @@ +--- +id: updating-supertokens +title: Updating Supertokens core and SDKs +hide_title: true +--- + + + + +# Updating SuperTokens core and SDKs + +:::important +You need to follow these steps in order to properly update supertokens +::: + +In order to maintain compatibility and keep up on new features, we recommend updating your core and SDKs whenever possible. + +## 1. Updating your core + +You will need to shut down your core in order to update it. After it's off, run the migration scripts for all versions inbetween +your starting version and the latest version. You may then bring your core back online. + +In the rare occasion that the supertokens core version you have updated to shows as incompatible with your current front-end and +back-end sdk's in the [compatibility table](./compatibility-table), then refrain from running your back-end and front-end SDKs until after you update them. + +- ### Self-hosted core +See the migration sections in the [supertokens-core changelog](https://github.com/supertokens/supertokens-core/blob/master/CHANGELOG.md). + +- ### Managed core +If you're using the managed core service, please email us at team@supertokens.com from your registered email to request a core update. + +## 2. Update your back-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### NodeJS +See the migration sections in the [supertokens-node changelog](https://github.com/supertokens/supertokens-node/blob/master/CHANGELOG.md). + +- ### GoLang +See the migration sections in the [supertokens-golang changelog](https://github.com/supertokens/supertokens-golang/blob/master/CHANGELOG.md). + +- ### Python +See the migration sections in the [supertokens-python changelog](https://github.com/supertokens/supertokens-python/blob/master/CHANGELOG.md). + +## 3. Update your front-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### ReactJS +See the migration sections in the [supertokens-auth-react changelog](https://github.com/supertokens/supertokens-auth-react/blob/master/CHANGELOG.md). + +- ### Vanilla JS +See the migration sections in the [supertokens-web-js changelog](https://github.com/supertokens/supertokens-web-js/blob/master/CHANGELOG.md). + +- ### React Native +See the migration sections in the [supertokens-react-native changelog](https://github.com/supertokens/supertokens-react-native/blob/master/CHANGELOG.md). + +- ### iOS +See the migration sections in the [supertokens-ios changelog](https://github.com/supertokens/supertokens-ios/blob/master/CHANGELOG.md). + +- ### Flutter +See the migration sections in the [supertokens-flutter changelog](https://github.com/supertokens/supertokens-flutter/blob/master/CHANGELOG.md). + +- ### Android +See the migration sections in the [supertokens-android changelog](https://github.com/supertokens/supertokens-android/blob/master/CHANGELOG.md). diff --git a/v2/thirdpartypasswordless/custom-ui/init/core/self-hosted-with-aws.mdx b/v2/thirdpartypasswordless/custom-ui/init/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/thirdpartypasswordless/custom-ui/init/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/thirdpartypasswordless/custom-ui/init/database-setup/mysql.mdx b/v2/thirdpartypasswordless/custom-ui/init/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/thirdpartypasswordless/custom-ui/init/database-setup/mysql.mdx +++ b/v2/thirdpartypasswordless/custom-ui/init/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/thirdpartypasswordless/custom-ui/init/database-setup/postgresql.mdx b/v2/thirdpartypasswordless/custom-ui/init/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/thirdpartypasswordless/custom-ui/init/database-setup/postgresql.mdx +++ b/v2/thirdpartypasswordless/custom-ui/init/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/thirdpartypasswordless/nextjs/app-directory/next-steps.mdx b/v2/thirdpartypasswordless/nextjs/app-directory/next-steps.mdx index 7de2c545f..20b4de6c9 100644 --- a/v2/thirdpartypasswordless/nextjs/app-directory/next-steps.mdx +++ b/v2/thirdpartypasswordless/nextjs/app-directory/next-steps.mdx @@ -21,8 +21,8 @@ import {Question, Answer}from "/src/components/question" You need to now setup an instance of the SuperTokens core for your app (that your backend should connect to). You have two options: -- [Managed service](../quick-setup/core/saas-setup) -- Self hosted with your own database ([With Docker](../quick-setup/core/with-docker) or [Without Docker](../quick-setup/core/without-docker)) +- [Managed service](../../pre-built-ui/setup/core/saas-setup) +- Self hosted with your own database ([With Docker](../../pre-built-ui/setup/core/with-docker) or [Without Docker](../../pre-built-ui/setup/core/without-docker)) diff --git a/v2/thirdpartypasswordless/pre-built-ui/setup/core/self-hosted-with-aws.mdx b/v2/thirdpartypasswordless/pre-built-ui/setup/core/self-hosted-with-aws.mdx deleted file mode 100644 index 27a527b4a..000000000 --- a/v2/thirdpartypasswordless/pre-built-ui/setup/core/self-hosted-with-aws.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: aws-setup-with-stacksnap -title: AWS Setup with Stacksnap -hide_title: true ---- - -import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; -import TabItem from '@theme/TabItem'; - -# AWS Setup with Stacksnap - -Stacksnap is a community supported AWS installer with unofficial SuperTokens support. You can use it to quickly deploy a solid starter deployment of SuperTokens on AWS. - -## Deploying SuperTokens on AWS using Stacksnap ✨ - -- Visit the [SuperTokens Stacksnap page](https://klo.dev/stacksnap/apps/supertokens/) -- Click on the "Deploy to AWS" button - -The 1-click installer automatically sets up an ECS task running SuperTokens, a Postgres DB on RDS for data storage, and an HTTPS url load balanced with a CloudFront distribution. - diff --git a/v2/thirdpartypasswordless/pre-built-ui/setup/database-setup/mysql.mdx b/v2/thirdpartypasswordless/pre-built-ui/setup/database-setup/mysql.mdx index 035ff52db..eb37456b2 100644 --- a/v2/thirdpartypasswordless/pre-built-ui/setup/database-setup/mysql.mdx +++ b/v2/thirdpartypasswordless/pre-built-ui/setup/database-setup/mysql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **MySQL 5.7**. ::: :::tip blog diff --git a/v2/thirdpartypasswordless/pre-built-ui/setup/database-setup/postgresql.mdx b/v2/thirdpartypasswordless/pre-built-ui/setup/database-setup/postgresql.mdx index cd75aeb43..abaea10fc 100644 --- a/v2/thirdpartypasswordless/pre-built-ui/setup/database-setup/postgresql.mdx +++ b/v2/thirdpartypasswordless/pre-built-ui/setup/database-setup/postgresql.mdx @@ -14,6 +14,8 @@ import TabItem from '@theme/TabItem'; :::important This is needed only if you are running the SuperTokens core yourself. + +The minimum required version is **PostgreSQL 9.6**. ::: :::tip blog @@ -21,6 +23,7 @@ We also have [a blog post writeup](https://supertokens.com/blog/connect-supertok ::: ## 1) Create a database 🛠️ + ```sql CREATE DATABASE supertokens; ``` diff --git a/v2/thirdpartypasswordless/rate-limits.mdx b/v2/thirdpartypasswordless/rate-limits.mdx index 8e8d895e2..a9943e7be 100644 --- a/v2/thirdpartypasswordless/rate-limits.mdx +++ b/v2/thirdpartypasswordless/rate-limits.mdx @@ -13,7 +13,7 @@ import CustomAdmonition from "/src/components/customAdmonition" ## For managed service -The SuperTokens core is rate limited on a per app and per IP address basis. This means that if query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). +The SuperTokens core is rate limited on a per app and per IP address basis. This means that if you query the core for app1 using the same IP address very quickly, the rate limit will kick in and you will get a `429` status code back from the core. However, if you query the core using different IP addresses or for a different app, the rate limit of that won't interfere with the previous requests (that had another IP or was for another app). :::note To know more about rps and bursts, please [this nginx document](https://www.nginx.com/blog/rate-limiting-nginx/). diff --git a/v2/thirdpartypasswordless/sdks.mdx b/v2/thirdpartypasswordless/sdks.mdx index b155f32f5..a732bdfa0 100644 --- a/v2/thirdpartypasswordless/sdks.mdx +++ b/v2/thirdpartypasswordless/sdks.mdx @@ -60,6 +60,10 @@ import GuidesLink from "/src/components/guidesLink" - SuperTokens provides React based pre-built UI components, for other frontend frameworks you will need to build custom UI and use the `supertokens-web-js` SDK to communicate with the APIs exposed by the SuperTokens backend SDK. - For other backend frameworks, you can follow our [guide on how to spin up a separate server configured with the SuperTokens backend SDK](/docs/community/other-frameworks) to authenticate requests and issue session tokens. +## SDK Migration + +See the [updating SuperTokens](./updating-supertokens) page for steps on how to migrate SDKs. + :::info Visit the [API reference page](./apis) to learn more. ::: diff --git a/v2/thirdpartypasswordless/serverless/with-aws-lambda/setup-api-gateway.mdx b/v2/thirdpartypasswordless/serverless/with-aws-lambda/setup-api-gateway.mdx index 979ae839d..2ef50acaa 100644 --- a/v2/thirdpartypasswordless/serverless/with-aws-lambda/setup-api-gateway.mdx +++ b/v2/thirdpartypasswordless/serverless/with-aws-lambda/setup-api-gateway.mdx @@ -34,6 +34,12 @@ Click on the "ANY" method and then "Integration" to configure the lambda functio Configure lambda integration UI +:::important + +Ensure that the **Lambda proxy integration** toggle is turned on. + +::: + ## 4) Enable CORS for the proxy path Click on the `{proxy+}` resource and then "Enable CORS" button to open the CORS configuration page. diff --git a/v2/thirdpartypasswordless/sidebars.js b/v2/thirdpartypasswordless/sidebars.js index f59b29cc9..a5fa79dce 100644 --- a/v2/thirdpartypasswordless/sidebars.js +++ b/v2/thirdpartypasswordless/sidebars.js @@ -33,7 +33,6 @@ module.exports = { items: [ "pre-built-ui/setup/core/with-docker", "pre-built-ui/setup/core/without-docker", - "pre-built-ui/setup/core/aws-setup-with-stacksnap", { type: "category", label: "Database Setup", @@ -110,7 +109,6 @@ module.exports = { items: [ "custom-ui/init/core/with-docker", "custom-ui/init/core/without-docker", - "custom-ui/init/core/aws-setup-with-stacksnap", { type: "category", label: "Database Setup", @@ -738,8 +736,8 @@ module.exports = { ], }, { - type: "category", - label: "Migration", + type: 'category', + label: 'Migrating to Supertokens', items: [ "migration/about", { @@ -756,6 +754,7 @@ module.exports = { "migration/mfa-migration", ], }, + "updating-supertokens", { type: "category", label: "References", diff --git a/v2/thirdpartypasswordless/updating-supertokens.mdx b/v2/thirdpartypasswordless/updating-supertokens.mdx new file mode 100644 index 000000000..b57bab619 --- /dev/null +++ b/v2/thirdpartypasswordless/updating-supertokens.mdx @@ -0,0 +1,65 @@ +--- +id: updating-supertokens +title: Updating Supertokens core and SDKs +hide_title: true +--- + + + + +# Updating SuperTokens core and SDKs + +:::important +You need to follow these steps in order to properly update supertokens +::: + +In order to maintain compatibility and keep up on new features, we recommend updating your core and SDKs whenever possible. + +## 1. Updating your core + +You will need to shut down your core in order to update it. After it's off, run the migration scripts for all versions inbetween +your starting version and the latest version. You may then bring your core back online. + +In the rare occasion that the supertokens core version you have updated to shows as incompatible with your current front-end and +back-end sdk's in the [compatibility table](./compatibility-table), then refrain from running your back-end and front-end SDKs until after you update them. + +- ### Self-hosted core +See the migration sections in the [supertokens-core changelog](https://github.com/supertokens/supertokens-core/blob/master/CHANGELOG.md). + +- ### Managed core +If you're using the managed core service, please email us at team@supertokens.com from your registered email to request a core update. + +## 2. Update your back-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### NodeJS +See the migration sections in the [supertokens-node changelog](https://github.com/supertokens/supertokens-node/blob/master/CHANGELOG.md). + +- ### GoLang +See the migration sections in the [supertokens-golang changelog](https://github.com/supertokens/supertokens-golang/blob/master/CHANGELOG.md). + +- ### Python +See the migration sections in the [supertokens-python changelog](https://github.com/supertokens/supertokens-python/blob/master/CHANGELOG.md). + +## 3. Update your front-end SDK + +Follow the steps in the migration sections of the linked changelog from your current version up to the latest version. + +- ### ReactJS +See the migration sections in the [supertokens-auth-react changelog](https://github.com/supertokens/supertokens-auth-react/blob/master/CHANGELOG.md). + +- ### Vanilla JS +See the migration sections in the [supertokens-web-js changelog](https://github.com/supertokens/supertokens-web-js/blob/master/CHANGELOG.md). + +- ### React Native +See the migration sections in the [supertokens-react-native changelog](https://github.com/supertokens/supertokens-react-native/blob/master/CHANGELOG.md). + +- ### iOS +See the migration sections in the [supertokens-ios changelog](https://github.com/supertokens/supertokens-ios/blob/master/CHANGELOG.md). + +- ### Flutter +See the migration sections in the [supertokens-flutter changelog](https://github.com/supertokens/supertokens-flutter/blob/master/CHANGELOG.md). + +- ### Android +See the migration sections in the [supertokens-android changelog](https://github.com/supertokens/supertokens-android/blob/master/CHANGELOG.md).