Skip to content

Commit

Permalink
feat: OAuth provider support (#1010)
Browse files Browse the repository at this point in the history
* fix: tenant config

* fix: api permissions and telemetry update

* fix: totp length validation

* fix: accept api key via authorization header

* fix: cache control header for jwks endpoint

* fix: tests

* fix: for dashboard

* fix: remove unused import

* fix: remove unused import

* fix: providers non null

* fix: tests

* fix: pr comments

* fix: pr comments

* fix: pr comments

* fix: pr comments

* fix: improve core config normalisation

* fix: more tests

* fix: more tests

* fix: clean up core config

* fix: pr comments

* fix: more test

* adds config in config.yaml

* reformates code

* reformats code

* modifies changelog

* small changes

* adds one more config for admin vs public service

* starts working on authorization endpoint

* removes unnecesssary files

* Oauth - WIP (#1018)

* fix/change annotations for configs

* feat: oauth2 auth API - WIP

* fix: hidefromdashboard to oauth_provider service url configs

* feat: OAuthAPI input parsing, basic flow

* feat: first test in progress

* fix: review fixes

* feat: tables for oauth in sqlite

* fix: remove unnecessary tables

* fix: store only the necessary data in the client table

* feat: oauth client - app exists check in db, a few tests

* fix: review fixes

* fix: review fixes

* feat: new configs for handling errors from hydra

* feat: using the new configs for oauth provider

* fix: CHANGELOG

* fix: tests for the new Util method

* fix: changelog changes

* fix: changelog migration section fix

* fix: fixing repeated header handling in HttpRequest#sendGETRequestWithResponseHeaders

* fix: more tests for oauth auth

* fix: review fix - more checks for the oauth config validity

* fix: review fix - throwing expection if there is no location header in response from hydra

* fix: review fix - renamed exception

* feat: oauth2 register client API

* feat: oauth2 get clients API

* feat: OAuth2 DELETE clients API

* fix: following the already existing response pattern with the oauth2 apis

* fix: renaming exception to be more expressive

* fix: review fixes

* fix: using BadRequestException instead of custom format for hydra invalid input errors

* Feature: oauth update client api (#1020)

* fix/change annotations for configs

* feat: oauth2 auth API - WIP

* fix: hidefromdashboard to oauth_provider service url configs

* feat: OAuthAPI input parsing, basic flow

* feat: first test in progress

* fix: review fixes

* feat: tables for oauth in sqlite

* fix: remove unnecessary tables

* fix: store only the necessary data in the client table

* feat: oauth client - app exists check in db, a few tests

* fix: review fixes

* fix: review fixes

* feat: new configs for handling errors from hydra

* feat: using the new configs for oauth provider

* fix: CHANGELOG

* fix: tests for the new Util method

* fix: changelog changes

* fix: changelog migration section fix

* fix: fixing repeated header handling in HttpRequest#sendGETRequestWithResponseHeaders

* fix: more tests for oauth auth

* fix: review fix - more checks for the oauth config validity

* fix: review fix - throwing expection if there is no location header in response from hydra

* fix: review fix - renamed exception

* feat: oauth2 register client API

* feat: oauth2 get clients API

* feat: OAuth2 DELETE clients API

* fix: following the already existing response pattern with the oauth2 apis

* fix: renaming exception to be more expressive

* fix: review fixes

* feat: oauth2 client update support

* fix: using BadRequestException instead of custom format for hydra invalid input errors

* fix: renaming method

* fix: remove unused constant

* fix: returning 500 when oauth update client goes wrong

* fix: fixing test after changing error response

* chore: removing TODO from code

* fix: merge with latest (#1028)

* fix: pathrouter for tenant id stop words (#1022)

* fix: pathrouter for tenant id stop words

* fix: pathrouter for tenant id stop words

* fix: changelog

* adding dev-v9.1.2 tag to this commit to ensure building

* fix: 500 error to return actual message (#1023)

* adding dev-v9.1.2 tag to this commit to ensure building

* fix: tests (#1024)

* adding dev-v9.1.2 tag to this commit to ensure building

* fix: cicd tests (#1025)

* adding dev-v9.1.2 tag to this commit to ensure building

* Update release.md

* feat: add security feature (#1026)

* adding dev-v9.2.0 tag to this commit to ensure building

* fix: feature test fix (#1027)

* adding dev-v9.2.0 tag to this commit to ensure building

---------

Co-authored-by: Rishabh Poddar <[email protected]>

* feat: hydra integration for auth, token and few more endpoints (#1032)

* fix: auth and token api

* fix: cookie and code transformations

* fix: token re-signing

* fix: token endpoint

* fix: license check and jwks caching

* fix: exceptions

* fix: refactor

* fix: refactor

* fix: refactor and client crud APIs

* fix: token type enum

* fix: process ext only on access token

* fix: refactor

* fix: bugs and refactor

* fix: oauth clients list api

* fix: consent get accept and reject

* fix: login request

* fix: query param transformation

* fix: logout request

* fix: refactor

* fix: remove error debug and hint

* fix: introspect api

* fix: pr comments

* fix: pr comments

* fix: pr comment

* fix: pr comment

* fix: pr comments and refactor

* fix: pr comments

* fix: pr comments

* fix: revert original http request

* fix: pr comment refactor

* fix: pr comment

* fix: pr comment

* fix: pr comment

* fix: pr comments

* fix: owner and pagination

* fix: pr comment

* fix: client id check

* fix: ext related

* fix: pr comment

* fix: revoke APIs (#1041)

* fix: revoke consent sessions

* fix: revoke token

* fix: revoke impl

* fix: revoke session

* fix: introspect impl after revoke

* fix: revoke by client_id

* fix: refresh token check in token exchange

* fix: at hash

* fix: sqlite impl

* fix: client props whitelist

* fix: status and query null check

* fix: plugin interface update

* fix: logout api

* fix: ext

* fix: accept consent

* fix: accept consent

* fix: introspect in token api

* fix: keep fragment while updating query params

* fix: count creds and pr comment

* fix: oauth stats

* fix: oauth cleanup cron task

* fix: gid in refresh token

* fix: inememory impl

* feat: add initial payload fields to accept consent

* fix: revoke cleanup

* fix: stats

* fix: client credentials basic

* fix: authorization header

* fix: authorizaion header in revoke

* fix: missing table

---------

Co-authored-by: Mihaly Lengyel <[email protected]>

---------

Co-authored-by: Mihaly Lengyel <[email protected]>

* fix: logout apis (#1047)

* fix: logout apis

* fix: session revoke in logout

* fix: tests

* feat: update logout logic to make BE integration easier

* refactor: minor fixes for consistency

---------

Co-authored-by: Mihaly Lengyel <[email protected]>

* fix: tests (#1051)

* fix: logout apis

* fix: session revoke in logout

* fix: tests

* fix: tests

* fix: tests

* fix: tests

* fix: versioning and cleanup

* fix: http revert

* fix: http revert

* fix: rename / refactor

* revert

* revert

* fix: test, cleanup and changelog

* revert

* fix: constraints

* fix: constraints

* fix: constraints

* fix: constraints

---------

Co-authored-by: Sattvik Chakravarthy <[email protected]>
Co-authored-by: Tamas Soltesz <[email protected]>
Co-authored-by: Sattvik Chakravarthy <[email protected]>
Co-authored-by: Mihaly Lengyel <[email protected]>
  • Loading branch information
5 people authored Oct 4, 2024
1 parent 6f9568a commit e83c9b4
Show file tree
Hide file tree
Showing 55 changed files with 4,632 additions and 51 deletions.
53 changes: 44 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,40 @@ 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`

## [9.2.2] - 2024-09-04

Expand Down Expand Up @@ -160,17 +193,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;
```
Expand Down Expand Up @@ -222,8 +257,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
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ compileTestJava { options.encoding = "UTF-8" }
// }
//}

version = "9.2.2"
version = "9.3.0"


repositories {
Expand Down
16 changes: 16 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,19 @@ core_config_version: 0
# (OPTIONAL | Default: null) string value. If specified, the supertokens service will only load the specified CUD even
# if there are more CUDs in the database and block all other CUDs from being used from this instance.
# supertokens_saas_load_only_cud:

# (OPTIONAL | Default: null) string value. If specified, the core uses this URL to connect to the OAuth provider
# public service.
# oauth_provider_public_service_url:

# (OPTIONAL | Default: null) string value. If specified, the core uses this URL to connect to the OAuth provider admin
# service.
# oauth_provider_admin_service_url:

# (OPTIONAL | Default: null) string value. If specified, the core uses this URL to replace the default
# consent and login URLs to {apiDomain}.
# oauth_provider_consent_login_base_url:

# (OPTIONAL | Default: oauth_provider_public_service_url) If specified, the core uses this URL to parse responses from
# the oauth provider when the oauth provider's internal address differs from the known public provider address.
# oauth_provider_url_configured_in_oauth_provider:
3 changes: 2 additions & 1 deletion coreDriverInterfaceSupported.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"3.1",
"4.0",
"5.0",
"5.1"
"5.1",
"5.2"
]
}
16 changes: 16 additions & 0 deletions devConfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,19 @@ disable_telemetry: true
# (OPTIONAL | Default: null) string value. If specified, the supertokens service will only load the specified CUD even
# if there are more CUDs in the database and block all other CUDs from being used from this instance.
# supertokens_saas_load_only_cud:

# (OPTIONAL | Default: null) string value. If specified, the core uses this URL to connect to the OAuth provider
# public service.
# oauth_provider_public_service_url:

# (OPTIONAL | Default: null) string value. If specified, the core uses this URL to connect to the OAuth provider admin
# service.
# oauth_provider_admin_service_url:

# (OPTIONAL | Default: null) string value. If specified, the core uses this URL to replace the default
# consent and login URLs to {apiDomain}.
# oauth_provider_consent_login_base_url:

# (OPTIONAL | Default: oauth_provider_public_service_url) If specified, the core uses this URL to parse responses from
# the oauth provider when the oauth provider's internal address differs from the known public provider address.
# oauth_provider_url_configured_in_oauth_provider:
28 changes: 28 additions & 0 deletions ee/src/main/java/io/supertokens/ee/EEFeatureFlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.supertokens.pluginInterface.KeyValueInfo;
import io.supertokens.pluginInterface.STORAGE_TYPE;
import io.supertokens.pluginInterface.Storage;
import io.supertokens.pluginInterface.StorageUtils;
import io.supertokens.pluginInterface.authRecipe.AuthRecipeStorage;
import io.supertokens.pluginInterface.dashboard.sqlStorage.DashboardSQLStorage;
import io.supertokens.pluginInterface.exceptions.StorageQueryException;
Expand All @@ -32,6 +33,7 @@
import io.supertokens.pluginInterface.multitenancy.TenantIdentifier;
import io.supertokens.pluginInterface.multitenancy.ThirdPartyConfig;
import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException;
import io.supertokens.pluginInterface.oauth.OAuthStorage;
import io.supertokens.pluginInterface.session.sqlStorage.SessionSQLStorage;
import io.supertokens.storageLayer.StorageLayer;
import io.supertokens.utils.Utils;
Expand Down Expand Up @@ -348,6 +350,28 @@ private JsonObject getAccountLinkingStats() throws StorageQueryException, Tenant
return result;
}

private JsonObject getOAuthStats() throws StorageQueryException, TenantOrAppNotFoundException {
JsonObject result = new JsonObject();

OAuthStorage oAuthStorage = StorageUtils.getOAuthStorage(StorageLayer.getStorage(
this.appIdentifier.getAsPublicTenantIdentifier(), main));

result.addProperty("totalNumberOfClients", oAuthStorage.countTotalNumberOfOAuthClients(appIdentifier));
result.addProperty("numberOfClientCredentialsOnlyClients", oAuthStorage.countTotalNumberOfClientCredentialsOnlyOAuthClients(appIdentifier));
result.addProperty("numberOfM2MTokensAlive", oAuthStorage.countTotalNumberOfOAuthM2MTokensAlive(appIdentifier));

long now = System.currentTimeMillis();
JsonArray tokensCreatedArray = new JsonArray();
for (int i = 1; i <= 31; i++) {
long timestamp = now - (i * 24 * 60 * 60 * 1000L);
int numberOfTokensCreated = oAuthStorage.countTotalNumberOfOAuthM2MTokensCreatedSince(this.appIdentifier, timestamp);
tokensCreatedArray.add(new JsonPrimitive(numberOfTokensCreated));
}
result.add("numberOfM2MTokensCreated", tokensCreatedArray);

return result;
}

private JsonArray getMAUs() throws StorageQueryException, TenantOrAppNotFoundException {
JsonArray mauArr = new JsonArray();
long now = System.currentTimeMillis();
Expand Down Expand Up @@ -405,6 +429,10 @@ public JsonObject getPaidFeatureStats() throws StorageQueryException, TenantOrAp
if (feature == EE_FEATURES.SECURITY) {
usageStats.add(EE_FEATURES.SECURITY.toString(), new JsonObject());
}

if (feature == EE_FEATURES.OAUTH) {
usageStats.add(EE_FEATURES.OAUTH.toString(), getOAuthStats());
}
}

usageStats.add("maus", getMAUs());
Expand Down
2 changes: 1 addition & 1 deletion pluginInterfaceSupported.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"_comment": "contains a list of plugin interfaces branch names that this core supports",
"versions": [
"6.2"
"6.3"
]
}
3 changes: 3 additions & 0 deletions src/main/java/io/supertokens/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.supertokens.config.Config;
import io.supertokens.config.CoreConfig;
import io.supertokens.cronjobs.Cronjobs;
import io.supertokens.cronjobs.cleanupOAuthRevokeListAndChallenges.CleanupOAuthRevokeListAndChallenges;
import io.supertokens.cronjobs.deleteExpiredAccessTokenSigningKeys.DeleteExpiredAccessTokenSigningKeys;
import io.supertokens.cronjobs.deleteExpiredDashboardSessions.DeleteExpiredDashboardSessions;
import io.supertokens.cronjobs.deleteExpiredEmailVerificationTokens.DeleteExpiredEmailVerificationTokens;
Expand Down Expand Up @@ -256,6 +257,8 @@ private void init() throws IOException, StorageQueryException {
// starts DeleteExpiredAccessTokenSigningKeys cronjob if the access token signing keys can change
Cronjobs.addCronjob(this, DeleteExpiredAccessTokenSigningKeys.init(this, uniqueUserPoolIdsTenants));

Cronjobs.addCronjob(this, CleanupOAuthRevokeListAndChallenges.init(this, uniqueUserPoolIdsTenants));

// this is to ensure tenantInfos are in sync for the new cron job as well
MultitenancyHelper.getInstance(this).refreshCronjobs();

Expand Down
1 change: 0 additions & 1 deletion src/main/java/io/supertokens/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import io.supertokens.Main;
Expand Down
Loading

0 comments on commit e83c9b4

Please sign in to comment.