All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Compatible with plugin interface version 6.3
- Adds support for OAuthStorage
CREATE TABLE IF NOT EXISTS oauth_clients (
app_id VARCHAR(64),
client_id VARCHAR(255) NOT NULL,
is_client_credentials_only BOOLEAN NOT NULL,
PRIMARY KEY (app_id, client_id),
FOREIGN KEY(app_id) REFERENCES apps(app_id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS oauth_sessions (
gid VARCHAR(255),
app_id VARCHAR(64) DEFAULT 'public',
client_id VARCHAR(255) NOT NULL,
session_handle VARCHAR(128),
external_refresh_token VARCHAR(255) UNIQUE,
internal_refresh_token VARCHAR(255) UNIQUE,
jti TEXT NOT NULL,
exp BIGINT NOT NULL,
PRIMARY KEY (gid),
FOREIGN KEY(app_id, client_id) REFERENCES oauth_clients(app_id, client_id) ON DELETE CASCADE
);
CREATE INDEX oauth_session_exp_index ON oauth_sessions(exp DESC);
CREATE INDEX oauth_session_external_refresh_token_index ON oauth_sessions(app_id, external_refresh_token DESC);
CREATE TABLE oauth_m2m_tokens (
app_id VARCHAR(64) DEFAULT 'public',
client_id VARCHAR(255) NOT NULL,
iat BIGINT UNSIGNED NOT NULL,
exp BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (app_id, client_id, iat),
FOREIGN KEY(app_id, client_id) REFERENCES oauth_clients(app_id, client_id) ON DELETE CASCADE
);
CREATE INDEX oauth_m2m_token_iat_index ON oauth_m2m_tokens(iat DESC, app_id DESC);
CREATE INDEX oauth_m2m_token_exp_index ON oauth_m2m_tokens(exp DESC);
CREATE TABLE IF NOT EXISTS oauth_logout_challenges (
app_id VARCHAR(64) DEFAULT 'public',
challenge VARCHAR(128) NOT NULL,
client_id VARCHAR(255) NOT NULL,
post_logout_redirect_uri VARCHAR(1024),
session_handle VARCHAR(128),
state VARCHAR(128),
time_created BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (app_id, challenge),
FOREIGN KEY(app_id, client_id) REFERENCES oauth_clients(app_id, client_id) ON DELETE CASCADE
);
CREATE INDEX oauth_logout_challenges_time_created_index ON oauth_logout_challenges(time_created ASC, app_id ASC);
- Adds index on
last_active_time
foruser_last_active
table to improve the performance of MAU computation.
CREATE INDEX user_last_active_last_active_time_index ON user_last_active (last_active_time DESC, app_id DESC);
- Fixes tests that check for
Internal Error
in 500 status responses
- Fixes issue where
is_third_party_providers_null
is added to thetenant_configs
table.
ALTER TABLE tenant_configs DROP COLUMN is_third_party_providers_null;
- Compatible with plugin interface version 6.2
- Adds implementation for a new method
getConfigFieldsInfo
to fetch the plugin config fields. - Adds
DashboardInfo
annotations to the config properties inPostgreSQLConfig
- Adds
null
state forfirstFactors
by addingis_first_factors_null
field intenant_configs
table. The value of this column is only applicable when there are no entries in thetenant_first_factors
table for the tenant.
ALTER TABLE tenant_configs ADD COLUMN is_first_factors_null BOOLEAN DEFAULT TRUE;
ALTER TABLE tenant_configs ADD COLUMN is_third_party_providers_null BOOLEAN DEFAULT TRUE;
ALTER TABLE tenant_configs ALTER COLUMN is_first_factors_null DROP DEFAULT;
ALTER TABLE tenant_configs ALTER COLUMN is_third_party_providers_null DROP DEFAULT;
- Fixes issues with partial failures during tenant creation
- Replace
TotpNotEnabledError
withUnknownUserIdTotpError
. - Support for MFA recipe
- Adds
firstFactors
andrequiredSecondaryFactors
for tenant config. - Adds a new
useStaticKey
param toupdateSessionInfo_Transaction
- This enables smooth switching between
useDynamicAccessTokenSigningKey
settings by allowing refresh calls to change the signing key type of a session
- This enables smooth switching between
- Fixes performance issue with user pagination
Make sure the core is already upgraded to version 8.0.0 before migrating
ALTER TABLE totp_user_devices ADD COLUMN created_at BIGINT UNSIGNED default 0;
ALTER TABLE totp_user_devices
ALTER COLUMN created_at DROP DEFAULT;
DROP INDEX all_auth_recipe_users_pagination_index2 ON all_auth_recipe_users;
DROP INDEX all_auth_recipe_users_pagination_index4 ON all_auth_recipe_users;
- Implements
deleteAllUserRoleAssociationsForRole
- Drops
(app_id, role)
foreign key constraint onuser_roles
table
ALTER TABLE user_roles DROP FOREIGN KEY user_roles_ibfk_1;
ALTER TABLE user_roles DROP FOREIGN KEY user_roles_ibfk_2;
ALTER TABLE user_roles
ADD FOREIGN KEY (app_id, tenant_id)
REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
- Fixes vulnerabilities in dependencies
- Fixes the issue where passwords were inadvertently logged in the logs.
- Adds tests to check connection pool behaviour.
- Adds
mysql_idle_connection_timeout
andmysql_minimum_idle_connections
configs to control active connections to the database.
- Validates db config types in
canBeUsed
function
- Adds index on
app_id_to_user_id
table to improve performance of get user by id queries - Fixes call to
getPrimaryUserInfoForUserIds_Transaction
inlistPrimaryUsersByThirdPartyInfo_Transaction
Run the following SQL script:
CREATE INDEX app_id_to_user_id_primary_user_id_index ON app_id_to_user_id (primary_or_recipe_user_id);
CREATE INDEX app_id_to_user_id_user_id_index ON app_id_to_user_id (user_id);
- Fixes issue with email verification with user id mapping
- Fixes
verified
inloginMethods
for users with userId mapping
- Fixes user info from primary user id query
- Fixes
deviceIdHash
issue
- Support for Account Linking
- Adds columns
primary_or_recipe_user_id
,is_linked_or_is_a_primary_user
andprimary_or_recipe_user_time_joined
toall_auth_recipe_users
table - Adds columns
primary_or_recipe_user_id
andis_linked_or_is_a_primary_user
toapp_id_to_user_id
table - Removes index
all_auth_recipe_users_pagination_index
and addesall_auth_recipe_users_pagination_index1
,all_auth_recipe_users_pagination_index2
,all_auth_recipe_users_pagination_index3
andall_auth_recipe_users_pagination_index4
indexes instead onall_auth_recipe_users
table - Adds
all_auth_recipe_users_recipe_id_index
onall_auth_recipe_users
table - Adds
all_auth_recipe_users_primary_user_id_index
onall_auth_recipe_users
table - Adds
email
column toemailpassword_pswd_reset_tokens
table - Changes
user_id
foreign key constraint onemailpassword_pswd_reset_tokens
toapp_id_to_user_id
table
- Adds columns
- Ensure that the core is already upgraded to the version 6.0.13 (CDI version 3.0)
- Stop the core instance(s)
- Run the migration script
ALTER TABLE all_auth_recipe_users ADD primary_or_recipe_user_id CHAR(36) NOT NULL DEFAULT ('0'); ALTER TABLE all_auth_recipe_users ADD is_linked_or_is_a_primary_user BOOLEAN NOT NULL DEFAULT FALSE; ALTER TABLE all_auth_recipe_users ADD primary_or_recipe_user_time_joined BIGINT UNSIGNED 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 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 primary_or_recipe_user_id CHAR(36) NOT NULL DEFAULT ('0'); ALTER TABLE app_id_to_user_id ADD 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 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 ON all_auth_recipe_users; 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 FOREIGN KEY emailpassword_pswd_reset_tokens_ibfk_1; ALTER TABLE emailpassword_pswd_reset_tokens ADD 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 email VARCHAR(256);
- Run the new instance(s) of the core (version 7.0.0)
- Fixes null pointer issue when user belongs to no tenant.
- Fixes duplicate users in users search queries when user is associated to multiple tenants
- Support for multitenancy
- New tables
apps
andtenants
have been added. - Schema of tables have been changed, adding
app_id
andtenant_id
columns in tables and constraints & indexes have been modified to include this columns. - New user tables have been added to map users to apps and tenants.
- New tables for multitenancy have been added.
- New tables
- Increased transaction retry count to 50 from 20.
-
Ensure that the core is already upgraded to version 5.0.0 (CDI version 2.21)
-
Stop the core instance(s)
-
Run the migration script
-- helper stored procedures DELIMITER // CREATE PROCEDURE st_drop_all_fkeys() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE dropCommand VARCHAR(255); DECLARE dropCur CURSOR for SELECT concat('ALTER TABLE ', table_schema,'.',table_name,' DROP FOREIGN KEY ', constraint_name, ';') FROM information_schema.table_constraints WHERE constraint_type='FOREIGN KEY' AND table_schema = DATABASE() AND table_name in ( 'all_auth_recipe_users', 'dashboard_user_sessions', 'dashboard_users', 'emailpassword_pswd_reset_tokens', 'emailpassword_users', 'emailverification_tokens', 'emailverification_verified_emails', 'jwt_signing_keys', 'key_value', 'passwordless_codes', 'passwordless_devices', 'passwordless_users', 'role_permissions', 'roles', 'session_access_token_signing_keys', 'session_info', 'thirdparty_users', 'totp_used_codes', 'totp_user_devices', 'totp_users', 'user_last_active', 'user_metadata', 'user_roles', 'userid_mapping' ); DECLARE CONTINUE handler for NOT found SET done = true; OPEN dropCur; read_loop: LOOP FETCH dropCur INTO dropCommand; IF done THEN leave read_loop; END IF; SET @sdropCommand = dropCommand; PREPARE dropClientUpdateKeyStmt FROM @sdropCommand; EXECUTE dropClientUpdateKeyStmt; DEALLOCATE prepare dropClientUpdateKeyStmt; END LOOP; CLOSE dropCur; END // -- CREATE PROCEDURE st_drop_all_pkeys() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE dropCommand VARCHAR(255); DECLARE dropCur CURSOR for SELECT concat('ALTER TABLE ', table_schema,'.',table_name,' DROP PRIMARY KEY ', ';') FROM information_schema.table_constraints WHERE constraint_type='PRIMARY KEY' AND table_schema = DATABASE() AND table_name in ( 'all_auth_recipe_users', 'dashboard_user_sessions', 'dashboard_users', 'emailpassword_pswd_reset_tokens', 'emailpassword_users', 'emailverification_tokens', 'emailverification_verified_emails', 'jwt_signing_keys', 'key_value', 'passwordless_codes', 'passwordless_devices', 'passwordless_users', 'role_permissions', 'roles', 'session_access_token_signing_keys', 'session_info', 'thirdparty_users', 'totp_used_codes', 'totp_user_devices', 'totp_users', 'user_last_active', 'user_metadata', 'user_roles', 'userid_mapping' ); DECLARE CONTINUE handler for NOT found SET done = true; OPEN dropCur; read_loop: LOOP FETCH dropCur INTO dropCommand; IF done THEN leave read_loop; END IF; SET @sdropCommand = dropCommand; PREPARE dropClientUpdateKeyStmt FROM @sdropCommand; EXECUTE dropClientUpdateKeyStmt; DEALLOCATE prepare dropClientUpdateKeyStmt; END LOOP; CLOSE dropCur; END // -- CREATE PROCEDURE st_drop_all_keys() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE dropCommand VARCHAR(255); DECLARE dropCur CURSOR for SELECT concat('ALTER TABLE ', table_schema,'.',table_name,' DROP INDEX ', constraint_name, ';') FROM information_schema.table_constraints WHERE constraint_type='UNIQUE' AND table_schema = DATABASE() AND table_name in ( 'all_auth_recipe_users', 'dashboard_user_sessions', 'dashboard_users', 'emailpassword_pswd_reset_tokens', 'emailpassword_users', 'emailverification_tokens', 'emailverification_verified_emails', 'jwt_signing_keys', 'key_value', 'passwordless_codes', 'passwordless_devices', 'passwordless_users', 'role_permissions', 'roles', 'session_access_token_signing_keys', 'session_info', 'thirdparty_users', 'totp_used_codes', 'totp_user_devices', 'totp_users', 'user_last_active', 'user_metadata', 'user_roles', 'userid_mapping' ); DECLARE CONTINUE handler for NOT found SET done = true; OPEN dropCur; read_loop: LOOP FETCH dropCur INTO dropCommand; IF done THEN leave read_loop; END IF; SET @sdropCommand = dropCommand; PREPARE dropClientUpdateKeyStmt FROM @sdropCommand; EXECUTE dropClientUpdateKeyStmt; DEALLOCATE prepare dropClientUpdateKeyStmt; END LOOP; CLOSE dropCur; END // -- CREATE PROCEDURE st_drop_all_indexes() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE dropCommand VARCHAR(255); DECLARE dropCur CURSOR for SELECT DISTINCT concat('ALTER TABLE ', table_schema, '.', table_name, ' DROP INDEX ', index_name, ';') FROM information_schema.statistics WHERE NON_UNIQUE = 1 AND table_schema = database() AND table_name in ( 'all_auth_recipe_users', 'dashboard_user_sessions', 'dashboard_users', 'emailpassword_pswd_reset_tokens', 'emailpassword_users', 'emailverification_tokens', 'emailverification_verified_emails', 'jwt_signing_keys', 'key_value', 'passwordless_codes', 'passwordless_devices', 'passwordless_users', 'role_permissions', 'roles', 'session_access_token_signing_keys', 'session_info', 'thirdparty_users', 'totp_used_codes', 'totp_user_devices', 'totp_users', 'user_last_active', 'user_metadata', 'user_roles', 'userid_mapping' ); DECLARE CONTINUE handler for NOT found SET done = true; OPEN dropCur; read_loop: LOOP FETCH dropCur INTO dropCommand; IF done THEN leave read_loop; END IF; SET @sdropCommand = dropCommand; PREPARE dropClientUpdateKeyStmt FROM @sdropCommand; EXECUTE dropClientUpdateKeyStmt; DEALLOCATE prepare dropClientUpdateKeyStmt; END LOOP; CLOSE dropCur; END // -- CREATE PROCEDURE st_add_column_if_not_exists( IN p_table_name varchar(50), IN p_column_name varchar(50), IN p_column_type varchar(50), IN p_additional varchar(100), OUT p_status_message varchar(100)) READS SQL DATA BEGIN DECLARE v_count INT; # Check wether column exist or not SELECT count(*) INTO v_count FROM information_schema.columns WHERE table_schema = database() AND table_name = p_table_name AND column_name = p_column_name; IF v_count > 0 THEN # Return column already exists message SELECT 'Column already Exists' INTO p_status_message; ELSE # Add Column and return success message set @ddl_addcolumn=CONCAT('ALTER TABLE ',database(),'.',p_table_name, ' ADD COLUMN ',p_column_name,' ',p_column_type,' ',p_additional); prepare add_column_sql from @ddl_addcolumn; execute add_column_sql; SELECT 'Column Successfully Created!' INTO p_status_message; END IF; END // DELIMITER ; -- Drop constraints and indexes CALL st_drop_all_fkeys(); CALL st_drop_all_keys(); CALL st_drop_all_pkeys(); CALL st_drop_all_indexes(); -- General Tables CREATE TABLE IF NOT EXISTS apps ( app_id VARCHAR(64) NOT NULL DEFAULT 'public', created_at_time BIGINT UNSIGNED ); ALTER TABLE apps ADD PRIMARY KEY(app_id); INSERT IGNORE INTO apps (app_id, created_at_time) VALUES ('public', 0); -- 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 UNSIGNED ); ALTER TABLE tenants ADD PRIMARY KEY(app_id, tenant_id); ALTER TABLE tenants ADD FOREIGN KEY (app_id) REFERENCES apps (app_id) ON DELETE CASCADE; INSERT IGNORE INTO tenants (app_id, tenant_id, created_at_time) VALUES ('public', 'public', 0); -- CALL st_add_column_if_not_exists('key_value', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); CALL st_add_column_if_not_exists('key_value', 'tenant_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE key_value ADD PRIMARY KEY (app_id, tenant_id, name); ALTER TABLE key_value ADD FOREIGN KEY (app_id, tenant_id) REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; -- 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 ); ALTER TABLE app_id_to_user_id ADD PRIMARY KEY (app_id, user_id); ALTER TABLE app_id_to_user_id ADD FOREIGN KEY (app_id) REFERENCES apps (app_id) ON DELETE CASCADE; INSERT IGNORE INTO app_id_to_user_id (user_id, recipe_id) SELECT user_id, recipe_id FROM all_auth_recipe_users; -- CALL st_add_column_if_not_exists('all_auth_recipe_users', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); CALL st_add_column_if_not_exists('all_auth_recipe_users', 'tenant_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE all_auth_recipe_users ADD PRIMARY KEY (app_id, tenant_id, user_id); ALTER TABLE all_auth_recipe_users ADD FOREIGN KEY (app_id, tenant_id) REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; ALTER TABLE all_auth_recipe_users ADD FOREIGN KEY (app_id, user_id) REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; 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); -- 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 ); ALTER TABLE tenant_configs ADD 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) ); ALTER TABLE tenant_thirdparty_providers ADD PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id); ALTER TABLE tenant_thirdparty_providers ADD FOREIGN KEY (connection_uri_domain, app_id, tenant_id) REFERENCES tenant_configs (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE; -- 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 TEXT, force_pkce BOOLEAN, additional_config TEXT ); ALTER TABLE tenant_thirdparty_provider_clients ADD PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id, client_type); ALTER TABLE tenant_thirdparty_provider_clients ADD 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; -- Session CALL st_add_column_if_not_exists('session_info', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); CALL st_add_column_if_not_exists('session_info', 'tenant_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE session_info ADD PRIMARY KEY (app_id, tenant_id, session_handle); ALTER TABLE session_info ADD FOREIGN KEY (app_id, tenant_id) REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; CREATE INDEX session_expiry_index ON session_info (expires_at); -- CALL st_add_column_if_not_exists('session_access_token_signing_keys', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE session_access_token_signing_keys ADD PRIMARY KEY (app_id, created_at_time); ALTER TABLE session_access_token_signing_keys ADD FOREIGN KEY (app_id) REFERENCES apps (app_id) ON DELETE CASCADE; -- JWT CALL st_add_column_if_not_exists('jwt_signing_keys', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE jwt_signing_keys ADD PRIMARY KEY (app_id, key_id); ALTER TABLE jwt_signing_keys ADD FOREIGN KEY (app_id) REFERENCES apps (app_id) ON DELETE CASCADE; -- EmailVerification CALL st_add_column_if_not_exists('emailverification_verified_emails', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE emailverification_verified_emails ADD PRIMARY KEY (app_id, user_id, email); ALTER TABLE emailverification_verified_emails ADD FOREIGN KEY (app_id) REFERENCES apps (app_id) ON DELETE CASCADE; -- CALL st_add_column_if_not_exists('emailverification_tokens', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); CALL st_add_column_if_not_exists('emailverification_tokens', 'tenant_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE emailverification_tokens ADD PRIMARY KEY (app_id, tenant_id, user_id, email, token); ALTER TABLE emailverification_tokens ADD FOREIGN KEY (app_id, tenant_id) REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; ALTER TABLE emailverification_tokens ADD CONSTRAINT token UNIQUE (token); CREATE INDEX emailverification_tokens_index ON emailverification_tokens(token_expiry); -- EmailPassword CALL st_add_column_if_not_exists('emailpassword_users', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE emailpassword_users ADD PRIMARY KEY (app_id, user_id); ALTER TABLE emailpassword_users ADD 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 ); ALTER TABLE emailpassword_user_to_tenant ADD PRIMARY KEY (app_id, tenant_id, user_id); ALTER TABLE emailpassword_user_to_tenant ADD CONSTRAINT email UNIQUE (app_id, tenant_id, email); ALTER TABLE emailpassword_user_to_tenant ADD CONSTRAINT FOREIGN KEY (app_id, tenant_id, user_id) REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE; INSERT IGNORE INTO emailpassword_user_to_tenant (user_id, email) SELECT user_id, email FROM emailpassword_users; -- CALL st_add_column_if_not_exists('emailpassword_pswd_reset_tokens', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE emailpassword_pswd_reset_tokens ADD PRIMARY KEY (app_id, user_id, token); ALTER TABLE emailpassword_pswd_reset_tokens ADD FOREIGN KEY (app_id, user_id) REFERENCES emailpassword_users (app_id, user_id) ON DELETE CASCADE; ALTER TABLE emailpassword_pswd_reset_tokens ADD CONSTRAINT token UNIQUE (token); CREATE INDEX emailpassword_password_reset_token_expiry_index ON emailpassword_pswd_reset_tokens (token_expiry); -- Passwordless CALL st_add_column_if_not_exists('passwordless_users', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE passwordless_users ADD PRIMARY KEY (app_id, user_id); ALTER TABLE passwordless_users ADD 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) ); ALTER TABLE passwordless_user_to_tenant ADD PRIMARY KEY (app_id, tenant_id, user_id); ALTER TABLE passwordless_user_to_tenant ADD CONSTRAINT email UNIQUE (app_id, tenant_id, email); ALTER TABLE passwordless_user_to_tenant ADD CONSTRAINT phone_number UNIQUE (app_id, tenant_id, phone_number); ALTER TABLE passwordless_user_to_tenant ADD FOREIGN KEY (app_id, tenant_id, user_id) REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE; INSERT IGNORE INTO passwordless_user_to_tenant (user_id, email, phone_number) SELECT user_id, email, phone_number FROM passwordless_users; -- CALL st_add_column_if_not_exists('passwordless_devices', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); CALL st_add_column_if_not_exists('passwordless_devices', 'tenant_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE passwordless_devices ADD PRIMARY KEY (app_id, tenant_id, device_id_hash); ALTER TABLE passwordless_devices ADD FOREIGN KEY (app_id, tenant_id) REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; CREATE INDEX passwordless_devices_email_index ON passwordless_devices (app_id, tenant_id, email); CREATE INDEX passwordless_devices_phone_number_index ON passwordless_devices (app_id, tenant_id, phone_number); -- CALL st_add_column_if_not_exists('passwordless_codes', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); CALL st_add_column_if_not_exists('passwordless_codes', 'tenant_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE passwordless_codes ADD PRIMARY KEY (app_id, tenant_id, code_id); ALTER TABLE passwordless_codes ADD 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 ADD CONSTRAINT link_code_hash UNIQUE (app_id, tenant_id, link_code_hash); CREATE INDEX passwordless_codes_created_at_index ON passwordless_codes (app_id, tenant_id, created_at); -- ThirdParty CALL st_add_column_if_not_exists('thirdparty_users', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE thirdparty_users ADD PRIMARY KEY (app_id, user_id); ALTER TABLE thirdparty_users ADD FOREIGN KEY (app_id, user_id) REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; CREATE INDEX thirdparty_users_thirdparty_user_id_index ON thirdparty_users (app_id, third_party_id, third_party_user_id); CREATE INDEX 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 ); ALTER TABLE thirdparty_user_to_tenant ADD PRIMARY KEY (app_id, tenant_id, user_id); ALTER TABLE thirdparty_user_to_tenant ADD CONSTRAINT third_party_user_id UNIQUE (app_id, tenant_id, third_party_id, third_party_user_id); ALTER TABLE thirdparty_user_to_tenant ADD FOREIGN KEY (app_id, tenant_id, user_id) REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE; INSERT IGNORE 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; -- UserIdMapping CALL st_add_column_if_not_exists('userid_mapping', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE userid_mapping ADD PRIMARY KEY (app_id, supertokens_user_id, external_user_id); ALTER TABLE userid_mapping ADD CONSTRAINT supertokens_user_id UNIQUE (app_id, supertokens_user_id); ALTER TABLE userid_mapping ADD CONSTRAINT external_user_id UNIQUE (app_id, external_user_id); ALTER TABLE userid_mapping ADD FOREIGN KEY (app_id, supertokens_user_id) REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE; -- UserRoles CALL st_add_column_if_not_exists('roles', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE roles ADD PRIMARY KEY (app_id, role); ALTER TABLE roles ADD FOREIGN KEY (app_id) REFERENCES apps (app_id) ON DELETE CASCADE; -- CALL st_add_column_if_not_exists('role_permissions', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE role_permissions ADD PRIMARY KEY (app_id, role, permission); ALTER TABLE role_permissions ADD FOREIGN KEY (app_id, role) REFERENCES roles (app_id, role) ON DELETE CASCADE; CREATE INDEX role_permissions_permission_index ON role_permissions (app_id, permission); -- CALL st_add_column_if_not_exists('user_roles', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); CALL st_add_column_if_not_exists('user_roles', 'tenant_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE user_roles ADD PRIMARY KEY (app_id, tenant_id, user_id, role); ALTER TABLE user_roles ADD FOREIGN KEY (app_id, role) REFERENCES roles (app_id, role) ON DELETE CASCADE; ALTER TABLE user_roles ADD FOREIGN KEY (app_id, tenant_id) REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; CREATE INDEX user_roles_role_index ON user_roles (app_id, tenant_id, role); -- UserMetadata CALL st_add_column_if_not_exists('user_metadata', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE user_metadata ADD PRIMARY KEY (app_id, user_id); ALTER TABLE user_metadata ADD FOREIGN KEY (app_id) REFERENCES apps (app_id) ON DELETE CASCADE; -- Dashboard CALL st_add_column_if_not_exists('dashboard_users', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE dashboard_users ADD PRIMARY KEY (app_id, user_id); ALTER TABLE dashboard_users ADD CONSTRAINT email UNIQUE (app_id, email); ALTER TABLE dashboard_users ADD FOREIGN KEY (app_id) REFERENCES apps (app_id) ON DELETE CASCADE; -- CALL st_add_column_if_not_exists('dashboard_user_sessions', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE dashboard_user_sessions ADD PRIMARY KEY (app_id, session_id); ALTER TABLE dashboard_user_sessions ADD FOREIGN KEY (app_id, user_id) REFERENCES dashboard_users (app_id, user_id) ON DELETE CASCADE; CREATE INDEX dashboard_user_sessions_expiry_index ON dashboard_user_sessions (expiry); -- TOTP CALL st_add_column_if_not_exists('totp_users', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE totp_users ADD PRIMARY KEY (app_id, user_id); ALTER TABLE totp_users ADD FOREIGN KEY (app_id) REFERENCES apps (app_id) ON DELETE CASCADE; -- CALL st_add_column_if_not_exists('totp_user_devices', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE totp_user_devices ADD PRIMARY KEY (app_id, user_id, device_name); ALTER TABLE totp_user_devices ADD FOREIGN KEY (app_id, user_id) REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE; -- CALL st_add_column_if_not_exists('totp_used_codes', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); CALL st_add_column_if_not_exists('totp_used_codes', 'tenant_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE totp_used_codes ADD PRIMARY KEY (app_id, tenant_id, user_id, created_time_ms); ALTER TABLE totp_used_codes ADD FOREIGN KEY (app_id, user_id) REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE; ALTER TABLE totp_used_codes ADD FOREIGN KEY (app_id, tenant_id) REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; CREATE INDEX totp_used_codes_expiry_time_ms_index ON totp_used_codes (app_id, tenant_id, expiry_time_ms); -- ActiveUsers CALL st_add_column_if_not_exists('user_last_active', 'app_id', 'VARCHAR(64)', 'NOT NULL DEFAULT \'public\'', @status_message); ALTER TABLE user_last_active ADD PRIMARY KEY (app_id, user_id); ALTER TABLE user_last_active ADD FOREIGN KEY (app_id) REFERENCES apps (app_id) ON DELETE CASCADE; -- Drop procedures DROP PROCEDURE st_drop_all_fkeys; DROP PROCEDURE st_drop_all_keys; DROP PROCEDURE st_drop_all_pkeys; DROP PROCEDURE st_drop_all_indexes; DROP PROCEDURE st_add_column_if_not_exists;
-
Start the new instance(s) of the core (version 6.0.0)
- Adds
use_static_key
BOOLEAN
column intosession_info
- Adds support for plugin inteface version 2.23
- If using
access_token_signing_key_dynamic
false in the core:- ```sql 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 using
access_token_signing_key_dynamic
true (or not set) in the core: -
- Support for Dashboard Search
- Support for TOTP recipe
- Support for active users
- Add new tables for TOTP recipe:
totp_users
that stores the users that have enabled TOTPtotp_user_devices
that stores devices (each device has its own secret) for each usertotp_used_codes
that stores used codes for each user. This is to implement rate limiting and prevent replay attacks.
- Add
user_last_active
table to store the last active time of a user.
- Support for Dashboard Recipe
- Updates dependencies as per: supertokens/supertokens-core#525
-
Updates the
third_party_user_id
column in thethirdparty_users
table fromVARCHAR(128)
toVARCHAR(256)
to resolve supertokens/supertokens-core#306 -
Adds support for user migration
- Updates the
password_hash
column in theemailpassword_users
table fromVARCHAR(128)
toVARCHAR(256)
to support more types of password hashes.
- Updates the
-
For legacy users who are self hosting the SuperTokens core run the following command to update your database with the changes:
ALTER TABLE thirdparty_users MODIFY third_party_user_id VARCHAR(256); ALTER TABLE emailpassword_users MODIFY password_hash VARCHAR(256);
- Adds log level feature and compatibility with plugin interface 2.18
- Adds compatibility with plugin interface 2.17
- Support for UserIdMapping
- Compatibility with plugin interface 2.15 - returns only non expired session handles for a user
- Support for User Roles
- Support for usermetadata
- Fixes issue #31
- Using lower transaction isolation level while creating passwordless device with code
- Fixed ResultSet instances to avoid Memory Leaks
- Fixed supertokens/supertokens-core#373: Catching
StorageTransactionLogicException
in transaction helper function for retries - add workflow to verify if pr title follows conventional commits
- passwordless support
- Delete user functionality
- Updated to match 2.9 plugin interface to support multiple access token signing keys: supertokens/supertokens-core#305
- Added functions and other changes for the JWT recipe
- Changes for pagination and count queries: supertokens/supertokens-core#259
- Add GetThirdPartyUsersByEmail query: supertokens/supertokens-core#277
- Update user's email via transaction for emailpassword: supertokens/supertokens-core#275
- Added emailverification functions: supertokens/supertokens-core#270
- Fixes issue: supertokens/supertokens-core#258
- Fixes detecting of thirdparty sign up duplicate error.
- Added ability to set table name prefix (supertokens/supertokens-core#220)
- Added connection URI support (supertokens/supertokens-core#221)
- Extracted email verification as its own recipe
- ThirdParty queries
- Used rowmapper ineterface
- Adds email verificaiton queries and tables
- Adds user pagination queries
- Support for emailpassword recipe
- Refactoring of queries to put them per recipe
- Changes base interface as per plugin interface 2.4
- Adds check to know if in memory db should be used.
- Updated MariaDB driver to support other authentication types