diff --git a/.circleci/config.yml b/.circleci/config.yml index c877d35d5..280919e1f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,22 +5,27 @@ jobs: test: docker: - image: rishabhpoddar/supertokens_core_testing + - image: rishabhpoddar/oauth-server-cicd - image: mongo environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: root resource_class: large + parallelism: 4 parameters: plugin: type: string steps: - checkout + - run: mkdir ~/junit - run: echo $'\n[mysqld]\ncharacter_set_server=utf8mb4\nmax_connections=10000' >> /etc/mysql/mysql.cnf - run: apt-get update && apt-get -y -q install postgresql-9.5 postgresql-client-9.5 postgresql-contrib-9.5 sudo - run: echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/9.5/main/pg_hba.conf - run: echo "listen_addresses='*'" >> /etc/postgresql/9.5/main/postgresql.conf - run: sed -i 's/^#*\s*max_connections\s*=.*/max_connections = 10000/' /etc/postgresql/9.5/main/postgresql.conf - run: (cd .circleci/ && ./doTests.sh << parameters.plugin >>) + - store_test_results: + path: ~/junit - slack/status mark-passed: @@ -44,7 +49,7 @@ workflows: tags: only: /dev-v[0-9]+(\.[0-9]+)*/ branches: - ignore: /.*/ + only: /test-cicd\/.*/ - test: plugin: mongodb name: test-mongodb @@ -54,7 +59,7 @@ workflows: tags: only: /dev-v[0-9]+(\.[0-9]+)*/ branches: - ignore: /.*/ + only: /test-cicd\/.*/ - test: plugin: postgresql name: test-postgresql @@ -64,7 +69,7 @@ workflows: tags: only: /dev-v[0-9]+(\.[0-9]+)*/ branches: - ignore: /.*/ + only: /test-cicd\/.*/ - test: plugin: mysql name: test-mysql @@ -74,7 +79,7 @@ workflows: tags: only: /dev-v[0-9]+(\.[0-9]+)*/ branches: - ignore: /.*/ + only: /test-cicd\/.*/ - mark-passed: context: - slack-notification diff --git a/.circleci/doTests.sh b/.circleci/doTests.sh index 3fb117cc5..3cc3df115 100755 --- a/.circleci/doTests.sh +++ b/.circleci/doTests.sh @@ -65,6 +65,8 @@ then exit 1 fi +mkdir -p ~/junit + someTestsRan=false while read -u 10 line do @@ -162,9 +164,24 @@ do fi cd ../ echo $SUPERTOKENS_API_KEY > apiPassword + ./startTestingEnv --cicd - if [[ $? -ne 0 ]] + TEST_EXIT_CODE=$? + + if [ -d ~/junit ] + then + echo "Copying output from core" + cp ~/supertokens-root/supertokens-core/build/test-results/test/*.xml ~/junit/ + + if [[ $pluginToTest != "sqlite" ]] + then + echo "Copying output from plugin" + cp ~/supertokens-root/supertokens-$pluginToTest-plugin/build/test-results/test/*.xml ~/junit/ + fi + fi + + if [[ $TEST_EXIT_CODE -ne 0 ]] then echo "" echo "" @@ -196,7 +213,7 @@ do echo "" echo "" - cd ../ + cd .. rm -rf supertokens-root if [[ $currPinnedDb == "sqlite" ]] diff --git a/CHANGELOG.md b/CHANGELOG.md index b5a31052f..0e05b6d60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,156 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## [Unreleased] + +## [9.3.0] + +### Changes + +- Adds support for OAuth2 + - Added new feature in license key: `OAUTH` + - Adds new core config: + - `oauth_provider_public_service_url` + - `oauth_provider_admin_service_url` + - `oauth_provider_consent_login_base_url` + - `oauth_provider_url_configured_in_oauth_provider` + - Adds following APIs: + - POST `/recipe/oauth/clients` + - PUT `/recipe/oauth/clients` + - GET `/recipe/oauth/clients` + - GET `/recipe/oauth/clients/list` + - POST `/recipe/oauth/clients/remove` + - GET `/recipe/oauth/auth/requests/consent` + - PUT `/recipe/oauth/auth/requests/consent/accept` + - PUT `/recipe/oauth/auth/requests/consent/reject` + - GET `/recipe/oauth/auth/requests/login` + - PUT `/recipe/oauth/auth/requests/login/accept` + - PUT `/recipe/oauth/auth/requests/login/reject` + - GET `/recipe/oauth/auth/requests/logout` + - PUT `/recipe/oauth/auth/requests/logout/accept` + - PUT `/recipe/oauth/auth/requests/logout/reject` + - POST `/recipe/oauth/auth` + - POST `/recipe/oauth/token` + - POST `/recipe/oauth/introspect` + - POST `/recipe/oauth/session/revoke` + - POST `/recipe/oauth/token/revoke` + - POST `/recipe/oauth/tokens/revoke` + +### Migration + +If using PostgreSQL, run the following SQL script: + +```sql +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 IF NOT EXISTS oauth_session_exp_index ON oauth_sessions(exp DESC); +CREATE INDEX IF NOT EXISTS oauth_session_external_refresh_token_index ON oauth_sessions(app_id, external_refresh_token DESC); + +CREATE TABLE IF NOT EXISTS oauth_m2m_tokens ( + app_id VARCHAR(64) DEFAULT 'public', + client_id VARCHAR(255) NOT NULL, + iat BIGINT NOT NULL, + exp BIGINT 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 IF NOT EXISTS oauth_m2m_token_iat_index ON oauth_m2m_tokens(iat DESC, app_id DESC); +CREATE INDEX IF NOT EXISTS 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 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 IF NOT EXISTS oauth_logout_challenges_time_created_index ON oauth_logout_challenges(time_created DESC); +``` + +If using MySQL, run the following SQL script: + +```sql +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); +``` + +## [9.2.3] - 2024-10-09 + +- Adds support for `--with-temp-dir` in CLI and `tempDirLocation=` in Core +- Adds validation to firstFactors and requiredSecondaryFactors names while creating tenants/apps/etc. to not allow + special chars. ### Added @@ -168,17 +317,19 @@ Make sure the core is already upgraded to version 8.0.0 before migrating If using PostgreSQL ```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; +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; ``` If using MySQL ```sql -ALTER TABLE totp_user_devices ADD COLUMN created_at BIGINT UNSIGNED default 0; -ALTER TABLE totp_user_devices - ALTER COLUMN created_at DROP DEFAULT; +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; ``` @@ -230,8 +381,8 @@ For MySQL: 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; + ADD FOREIGN KEY (app_id, tenant_id) + REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE; ``` ## [7.0.18] - 2024-02-19 diff --git a/build.gradle b/build.gradle index 00afc8e7c..c4779d56c 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ compileTestJava { options.encoding = "UTF-8" } // } //} -version = "9.2.2" +version = "9.3.0" repositories { mavenCentral() diff --git a/cli/jar/cli.jar b/cli/jar/cli.jar index 4ff950e18..cf2cc1208 100644 Binary files a/cli/jar/cli.jar and b/cli/jar/cli.jar differ diff --git a/cli/src/main/java/io/supertokens/cli/commandHandler/start/StartHandler.java b/cli/src/main/java/io/supertokens/cli/commandHandler/start/StartHandler.java index 645608dd6..5bf579567 100644 --- a/cli/src/main/java/io/supertokens/cli/commandHandler/start/StartHandler.java +++ b/cli/src/main/java/io/supertokens/cli/commandHandler/start/StartHandler.java @@ -35,6 +35,7 @@ public class StartHandler extends CommandHandler { public void doCommand(String installationDir, boolean viaInstaller, String[] args) { String space = CLIOptionsParser.parseOption("--with-space", args); String configPath = CLIOptionsParser.parseOption("--with-config", args); + String tempDirLocation = CLIOptionsParser.parseOption("--with-temp-dir", args); if (configPath != null) { configPath = new File(configPath).getAbsolutePath(); } @@ -67,6 +68,9 @@ public void doCommand(String installationDir, boolean viaInstaller, String[] arg if (forceNoInMemDB) { commands.add("forceNoInMemDB=true"); } + if(tempDirLocation != null && !tempDirLocation.isEmpty()) { + commands.add("tempDirLocation=" + tempDirLocation); + } } else { commands.add(installationDir + "jre/bin/java"); commands.add("-Djava.security.egd=file:/dev/urandom"); @@ -90,6 +94,9 @@ public void doCommand(String installationDir, boolean viaInstaller, String[] arg if (forceNoInMemDB) { commands.add("forceNoInMemDB=true"); } + if(tempDirLocation != null && !tempDirLocation.isEmpty()) { + commands.add("tempDirLocation=" + tempDirLocation); + } } if (!foreground) { try { @@ -172,6 +179,8 @@ protected List