diff --git a/authentik/api/authentication.py b/authentik/api/authentication.py index 098de8e3e..88680244c 100644 --- a/authentik/api/authentication.py +++ b/authentik/api/authentication.py @@ -33,7 +33,7 @@ def bearer_auth(raw_header: bytes) -> Optional[User]: raise AuthenticationFailed("Malformed header") # Accept credentials with username and without if ":" in auth_credentials: - _, password = auth_credentials.split(":") + _, _, password = auth_credentials.partition(":") else: password = auth_credentials if password == "": # nosec diff --git a/authentik/core/models.py b/authentik/core/models.py index de64221b4..b1c0b3ec0 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -28,6 +28,7 @@ from authentik.core.signals import password_changed from authentik.core.types import UILoginButton, UserSettingSerializer from authentik.flows.models import Flow from authentik.lib.config import CONFIG +from authentik.lib.generators import generate_id from authentik.lib.models import CreatedUpdatedModel, SerializerModel from authentik.lib.utils.http import get_client_ip from authentik.managed.models import ManagedModel @@ -54,7 +55,9 @@ def default_token_duration(): def default_token_key(): """Default token key""" - return uuid4().hex + # We use generate_id since the chars in the key should be easy + # to use in Emails (for verification) and URLs (for recovery) + return generate_id(128) class Group(models.Model): diff --git a/authentik/core/tests/test_source_flow_manager.py b/authentik/core/tests/test_source_flow_manager.py index 02f3cf8d4..94ab52ba0 100644 --- a/authentik/core/tests/test_source_flow_manager.py +++ b/authentik/core/tests/test_source_flow_manager.py @@ -6,8 +6,8 @@ from guardian.utils import get_anonymous_user from authentik.core.models import SourceUserMatchingModes, User from authentik.core.sources.flow_manager import Action +from authentik.lib.generators import generate_id from authentik.lib.tests.utils import get_request -from authentik.providers.oauth2.generators import generate_client_id from authentik.sources.oauth.models import OAuthSource, UserOAuthSourceConnection from authentik.sources.oauth.views.callback import OAuthSourceFlowManager @@ -19,7 +19,7 @@ class TestSourceFlowManager(TestCase): super().setUp() self.source = OAuthSource.objects.create(name="test") self.factory = RequestFactory() - self.identifier = generate_client_id() + self.identifier = generate_id() def test_unauthenticated_enroll(self): """Test un-authenticated user enrolling""" diff --git a/authentik/crypto/tests.py b/authentik/crypto/tests.py index 22d800651..6e9fa7798 100644 --- a/authentik/crypto/tests.py +++ b/authentik/crypto/tests.py @@ -10,7 +10,7 @@ from authentik.crypto.api import CertificateKeyPairSerializer from authentik.crypto.builder import CertificateBuilder from authentik.crypto.models import CertificateKeyPair from authentik.flows.models import Flow -from authentik.providers.oauth2.generators import generate_client_secret +from authentik.lib.generators import generate_key from authentik.providers.oauth2.models import OAuth2Provider @@ -103,7 +103,7 @@ class TestCrypto(TestCase): provider = OAuth2Provider.objects.create( name="test", client_id="test", - client_secret=generate_client_secret(), + client_secret=generate_key(), authorization_flow=Flow.objects.first(), redirect_uris="http://localhost", rsa_key=CertificateKeyPair.objects.first(), diff --git a/authentik/flows/tests/test_transfer.py b/authentik/flows/tests/test_transfer.py index ca98920ea..bf5d7efa8 100644 --- a/authentik/flows/tests/test_transfer.py +++ b/authentik/flows/tests/test_transfer.py @@ -7,9 +7,9 @@ from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding from authentik.flows.transfer.common import DataclassEncoder from authentik.flows.transfer.exporter import FlowExporter from authentik.flows.transfer.importer import FlowImporter, transaction_rollback +from authentik.lib.generators import generate_id from authentik.policies.expression.models import ExpressionPolicy from authentik.policies.models import PolicyBinding -from authentik.providers.oauth2.generators import generate_client_id from authentik.stages.prompt.models import FieldTypes, Prompt, PromptStage from authentik.stages.user_login.models import UserLoginStage @@ -31,15 +31,15 @@ class TestFlowTransfer(TransactionTestCase): def test_export_validate_import(self): """Test export and validate it""" - flow_slug = generate_client_id() + flow_slug = generate_id() with transaction_rollback(): - login_stage = UserLoginStage.objects.create(name=generate_client_id()) + login_stage = UserLoginStage.objects.create(name=generate_id()) flow = Flow.objects.create( slug=flow_slug, designation=FlowDesignation.AUTHENTICATION, - name=generate_client_id(), - title=generate_client_id(), + name=generate_id(), + title=generate_id(), ) FlowStageBinding.objects.update_or_create( target=flow, @@ -60,18 +60,18 @@ class TestFlowTransfer(TransactionTestCase): def test_export_validate_import_policies(self): """Test export and validate it""" - flow_slug = generate_client_id() - stage_name = generate_client_id() + flow_slug = generate_id() + stage_name = generate_id() with transaction_rollback(): flow_policy = ExpressionPolicy.objects.create( - name=generate_client_id(), + name=generate_id(), expression="return True", ) flow = Flow.objects.create( slug=flow_slug, designation=FlowDesignation.AUTHENTICATION, - name=generate_client_id(), - title=generate_client_id(), + name=generate_id(), + title=generate_id(), ) PolicyBinding.objects.create(policy=flow_policy, target=flow, order=0) @@ -111,15 +111,15 @@ class TestFlowTransfer(TransactionTestCase): ) # Stages - first_stage = PromptStage.objects.create(name=generate_client_id()) + first_stage = PromptStage.objects.create(name=generate_id()) first_stage.fields.set([username_prompt, password, password_repeat]) first_stage.save() flow = Flow.objects.create( - name=generate_client_id(), - slug=generate_client_id(), + name=generate_id(), + slug=generate_id(), designation=FlowDesignation.ENROLLMENT, - title=generate_client_id(), + title=generate_id(), ) FlowStageBinding.objects.create(target=flow, stage=first_stage, order=0) diff --git a/authentik/lib/generators.py b/authentik/lib/generators.py new file mode 100644 index 000000000..b0f1303d0 --- /dev/null +++ b/authentik/lib/generators.py @@ -0,0 +1,18 @@ +"""ID/Secret Generators""" +import string +from random import SystemRandom + + +def generate_id(length=40): + """Generate a random client ID""" + rand = SystemRandom() + return "".join(rand.choice(string.ascii_letters + string.digits) for x in range(length)) + + +def generate_key(length=128): + """Generate a suitable client secret""" + rand = SystemRandom() + return "".join( + rand.choice(string.ascii_letters + string.digits + string.punctuation) + for x in range(length) + ) diff --git a/authentik/policies/hibp/tests.py b/authentik/policies/hibp/tests.py index a93076406..778779ab2 100644 --- a/authentik/policies/hibp/tests.py +++ b/authentik/policies/hibp/tests.py @@ -2,9 +2,9 @@ from django.test import TestCase from guardian.shortcuts import get_anonymous_user +from authentik.lib.generators import generate_key from authentik.policies.hibp.models import HaveIBeenPwendPolicy from authentik.policies.types import PolicyRequest, PolicyResult -from authentik.providers.oauth2.generators import generate_client_secret class TestHIBPPolicy(TestCase): @@ -37,7 +37,7 @@ class TestHIBPPolicy(TestCase): name="test_true", ) request = PolicyRequest(get_anonymous_user()) - request.context["password"] = generate_client_secret() + request.context["password"] = generate_key() result: PolicyResult = policy.passes(request) self.assertTrue(result.passing) self.assertEqual(result.messages, tuple()) diff --git a/authentik/providers/oauth2/generators.py b/authentik/providers/oauth2/generators.py deleted file mode 100644 index 0df19d51d..000000000 --- a/authentik/providers/oauth2/generators.py +++ /dev/null @@ -1,15 +0,0 @@ -"""OAuth2 Client ID/Secret Generators""" -import string -from random import SystemRandom - - -def generate_client_id(): - """Generate a random client ID""" - rand = SystemRandom() - return "".join(rand.choice(string.ascii_letters + string.digits) for x in range(40)) - - -def generate_client_secret(): - """Generate a suitable client secret""" - rand = SystemRandom() - return "".join(rand.choice(string.ascii_letters + string.digits) for x in range(128)) diff --git a/authentik/providers/oauth2/migrations/0001_initial.py b/authentik/providers/oauth2/migrations/0001_initial.py index 9a531742d..01fae0762 100644 --- a/authentik/providers/oauth2/migrations/0001_initial.py +++ b/authentik/providers/oauth2/migrations/0001_initial.py @@ -7,8 +7,8 @@ from django.db import migrations, models from django.db.backends.base.schema import BaseDatabaseSchemaEditor import authentik.core.models +import authentik.lib.generators import authentik.lib.utils.time -import authentik.providers.oauth2.generators class Migration(migrations.Migration): @@ -55,7 +55,7 @@ class Migration(migrations.Migration): ( "client_id", models.CharField( - default=authentik.providers.oauth2.generators.generate_client_id, + default=authentik.lib.generators.generate_id, max_length=255, unique=True, verbose_name="Client ID", @@ -65,7 +65,7 @@ class Migration(migrations.Migration): "client_secret", models.CharField( blank=True, - default=authentik.providers.oauth2.generators.generate_client_secret, + default=authentik.lib.generators.generate_key, max_length=255, verbose_name="Client Secret", ), diff --git a/authentik/providers/oauth2/models.py b/authentik/providers/oauth2/models.py index 11b6eb960..72f101c0d 100644 --- a/authentik/providers/oauth2/models.py +++ b/authentik/providers/oauth2/models.py @@ -22,10 +22,10 @@ from authentik.core.models import ExpiringModel, PropertyMapping, Provider, User from authentik.crypto.models import CertificateKeyPair from authentik.events.models import Event, EventAction from authentik.events.utils import get_user +from authentik.lib.generators import generate_id, generate_key from authentik.lib.utils.time import timedelta_from_string, timedelta_string_validator from authentik.providers.oauth2.apps import AuthentikProviderOAuth2Config from authentik.providers.oauth2.constants import ACR_AUTHENTIK_DEFAULT -from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret class ClientTypes(models.TextChoices): @@ -138,13 +138,13 @@ class OAuth2Provider(Provider): max_length=255, unique=True, verbose_name=_("Client ID"), - default=generate_client_id, + default=generate_id, ) client_secret = models.CharField( max_length=255, blank=True, verbose_name=_("Client Secret"), - default=generate_client_secret, + default=generate_key, ) jwt_alg = models.CharField( max_length=10, diff --git a/authentik/providers/oauth2/tests/test_authorize.py b/authentik/providers/oauth2/tests/test_authorize.py index 603549968..68008aeeb 100644 --- a/authentik/providers/oauth2/tests/test_authorize.py +++ b/authentik/providers/oauth2/tests/test_authorize.py @@ -7,8 +7,8 @@ from authentik.core.models import Application, User from authentik.crypto.models import CertificateKeyPair from authentik.flows.challenge import ChallengeTypes from authentik.flows.models import Flow +from authentik.lib.generators import generate_id, generate_key from authentik.providers.oauth2.errors import AuthorizeError, ClientIdError, RedirectUriError -from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret from authentik.providers.oauth2.models import ( AuthorizationCode, GrantTypes, @@ -183,7 +183,7 @@ class TestAuthorize(OAuthTestCase): redirect_uris="foo://localhost", ) Application.objects.create(name="app", slug="app", provider=provider) - state = generate_client_id() + state = generate_id() user = User.objects.get(username="akadmin") self.client.force_login(user) # Step 1, initiate params and get redirect to flow @@ -215,13 +215,13 @@ class TestAuthorize(OAuthTestCase): provider = OAuth2Provider.objects.create( name="test", client_id="test", - client_secret=generate_client_secret(), + client_secret=generate_key(), authorization_flow=flow, redirect_uris="http://localhost", rsa_key=CertificateKeyPair.objects.first(), ) Application.objects.create(name="app", slug="app", provider=provider) - state = generate_client_id() + state = generate_id() user = User.objects.get(username="akadmin") self.client.force_login(user) # Step 1, initiate params and get redirect to flow diff --git a/authentik/providers/oauth2/tests/test_token.py b/authentik/providers/oauth2/tests/test_token.py index 49067e5e3..97a0b220e 100644 --- a/authentik/providers/oauth2/tests/test_token.py +++ b/authentik/providers/oauth2/tests/test_token.py @@ -9,12 +9,12 @@ from authentik.core.models import Application, User from authentik.crypto.models import CertificateKeyPair from authentik.events.models import Event, EventAction from authentik.flows.models import Flow +from authentik.lib.generators import generate_id, generate_key from authentik.providers.oauth2.constants import ( GRANT_TYPE_AUTHORIZATION_CODE, GRANT_TYPE_REFRESH_TOKEN, ) from authentik.providers.oauth2.errors import TokenError -from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret from authentik.providers.oauth2.models import AuthorizationCode, OAuth2Provider, RefreshToken from authentik.providers.oauth2.tests.utils import OAuthTestCase from authentik.providers.oauth2.views.token import TokenParams @@ -32,8 +32,8 @@ class TestToken(OAuthTestCase): """test request param""" provider = OAuth2Provider.objects.create( name="test", - client_id=generate_client_id(), - client_secret=generate_client_secret(), + client_id=generate_id(), + client_secret=generate_key(), authorization_flow=Flow.objects.first(), redirect_uris="http://testserver", rsa_key=CertificateKeyPair.objects.first(), @@ -53,14 +53,14 @@ class TestToken(OAuthTestCase): params = TokenParams.parse(request, provider, provider.client_id, provider.client_secret) self.assertEqual(params.provider, provider) with self.assertRaises(TokenError): - TokenParams.parse(request, provider, provider.client_id, generate_client_secret()) + TokenParams.parse(request, provider, provider.client_id, generate_key()) def test_request_auth_code_invalid(self): """test request param""" provider = OAuth2Provider.objects.create( name="test", - client_id=generate_client_id(), - client_secret=generate_client_secret(), + client_id=generate_id(), + client_secret=generate_key(), authorization_flow=Flow.objects.first(), redirect_uris="http://testserver", rsa_key=CertificateKeyPair.objects.first(), @@ -82,8 +82,8 @@ class TestToken(OAuthTestCase): """test request param""" provider = OAuth2Provider.objects.create( name="test", - client_id=generate_client_id(), - client_secret=generate_client_secret(), + client_id=generate_id(), + client_secret=generate_key(), authorization_flow=Flow.objects.first(), redirect_uris="http://local.invalid", rsa_key=CertificateKeyPair.objects.first(), @@ -93,7 +93,7 @@ class TestToken(OAuthTestCase): token: RefreshToken = RefreshToken.objects.create( provider=provider, user=user, - refresh_token=generate_client_id(), + refresh_token=generate_id(), ) request = self.factory.post( "/", @@ -111,8 +111,8 @@ class TestToken(OAuthTestCase): """test request param""" provider = OAuth2Provider.objects.create( name="test", - client_id=generate_client_id(), - client_secret=generate_client_secret(), + client_id=generate_id(), + client_secret=generate_key(), authorization_flow=Flow.objects.first(), redirect_uris="http://local.invalid", rsa_key=CertificateKeyPair.objects.first(), @@ -153,8 +153,8 @@ class TestToken(OAuthTestCase): """test request param""" provider = OAuth2Provider.objects.create( name="test", - client_id=generate_client_id(), - client_secret=generate_client_secret(), + client_id=generate_id(), + client_secret=generate_key(), authorization_flow=Flow.objects.first(), redirect_uris="http://local.invalid", rsa_key=CertificateKeyPair.objects.first(), @@ -167,7 +167,7 @@ class TestToken(OAuthTestCase): token: RefreshToken = RefreshToken.objects.create( provider=provider, user=user, - refresh_token=generate_client_id(), + refresh_token=generate_id(), ) response = self.client.post( reverse("authentik_providers_oauth2:token"), @@ -202,8 +202,8 @@ class TestToken(OAuthTestCase): """test request param""" provider = OAuth2Provider.objects.create( name="test", - client_id=generate_client_id(), - client_secret=generate_client_secret(), + client_id=generate_id(), + client_secret=generate_key(), authorization_flow=Flow.objects.first(), redirect_uris="http://local.invalid", rsa_key=CertificateKeyPair.objects.first(), @@ -213,7 +213,7 @@ class TestToken(OAuthTestCase): token: RefreshToken = RefreshToken.objects.create( provider=provider, user=user, - refresh_token=generate_client_id(), + refresh_token=generate_id(), ) response = self.client.post( reverse("authentik_providers_oauth2:token"), @@ -247,8 +247,8 @@ class TestToken(OAuthTestCase): """test request param""" provider = OAuth2Provider.objects.create( name="test", - client_id=generate_client_id(), - client_secret=generate_client_secret(), + client_id=generate_id(), + client_secret=generate_key(), authorization_flow=Flow.objects.first(), redirect_uris="http://testserver", rsa_key=CertificateKeyPair.objects.first(), @@ -261,7 +261,7 @@ class TestToken(OAuthTestCase): token: RefreshToken = RefreshToken.objects.create( provider=provider, user=user, - refresh_token=generate_client_id(), + refresh_token=generate_id(), ) # Create initial refresh token response = self.client.post( diff --git a/authentik/providers/oauth2/tests/test_userinfo.py b/authentik/providers/oauth2/tests/test_userinfo.py index fbe66383c..97cb33871 100644 --- a/authentik/providers/oauth2/tests/test_userinfo.py +++ b/authentik/providers/oauth2/tests/test_userinfo.py @@ -9,8 +9,8 @@ from authentik.core.models import Application, User from authentik.crypto.models import CertificateKeyPair from authentik.events.models import Event, EventAction from authentik.flows.models import Flow +from authentik.lib.generators import generate_id, generate_key from authentik.managed.manager import ObjectManager -from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret from authentik.providers.oauth2.models import IDToken, OAuth2Provider, RefreshToken, ScopeMapping from authentik.providers.oauth2.tests.utils import OAuthTestCase @@ -24,8 +24,8 @@ class TestUserinfo(OAuthTestCase): self.app = Application.objects.create(name="test", slug="test") self.provider: OAuth2Provider = OAuth2Provider.objects.create( name="test", - client_id=generate_client_id(), - client_secret=generate_client_secret(), + client_id=generate_id(), + client_secret=generate_key(), authorization_flow=Flow.objects.first(), redirect_uris="", rsa_key=CertificateKeyPair.objects.first(), @@ -38,8 +38,8 @@ class TestUserinfo(OAuthTestCase): self.token: RefreshToken = RefreshToken.objects.create( provider=self.provider, user=self.user, - access_token=generate_client_id(), - refresh_token=generate_client_id(), + access_token=generate_id(), + refresh_token=generate_id(), _scope="openid user profile", _id_token=json.dumps( asdict( diff --git a/authentik/providers/oauth2/utils.py b/authentik/providers/oauth2/utils.py index 3baf0e94b..b49a1f7ba 100644 --- a/authentik/providers/oauth2/utils.py +++ b/authentik/providers/oauth2/utils.py @@ -103,8 +103,8 @@ def extract_client_auth(request: HttpRequest) -> tuple[str, str]: if re.compile(r"^Basic\s{1}.+$").match(auth_header): b64_user_pass = auth_header.split()[1] try: - user_pass = b64decode(b64_user_pass).decode("utf-8").split(":") - client_id, client_secret = user_pass + user_pass = b64decode(b64_user_pass).decode("utf-8").partition(":") + client_id, _, client_secret = user_pass except (ValueError, Error): client_id = client_secret = "" # nosec else: diff --git a/authentik/sources/ldap/tests/test_api.py b/authentik/sources/ldap/tests/test_api.py index 5419a6df8..9618fa6ae 100644 --- a/authentik/sources/ldap/tests/test_api.py +++ b/authentik/sources/ldap/tests/test_api.py @@ -1,11 +1,11 @@ """LDAP Source API tests""" from rest_framework.test import APITestCase -from authentik.providers.oauth2.generators import generate_client_secret +from authentik.lib.generators import generate_key from authentik.sources.ldap.api import LDAPSourceSerializer from authentik.sources.ldap.models import LDAPSource -LDAP_PASSWORD = generate_client_secret() +LDAP_PASSWORD = generate_key() class LDAPAPITests(APITestCase): diff --git a/authentik/sources/ldap/tests/test_auth.py b/authentik/sources/ldap/tests/test_auth.py index 2c5c9893f..86e382a84 100644 --- a/authentik/sources/ldap/tests/test_auth.py +++ b/authentik/sources/ldap/tests/test_auth.py @@ -5,15 +5,15 @@ from django.db.models import Q from django.test import TestCase from authentik.core.models import User +from authentik.lib.generators import generate_key from authentik.managed.manager import ObjectManager -from authentik.providers.oauth2.generators import generate_client_secret from authentik.sources.ldap.auth import LDAPBackend from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource from authentik.sources.ldap.sync.users import UserLDAPSynchronizer from authentik.sources.ldap.tests.mock_ad import mock_ad_connection from authentik.sources.ldap.tests.mock_slapd import mock_slapd_connection -LDAP_PASSWORD = generate_client_secret() +LDAP_PASSWORD = generate_key() class LDAPSyncTests(TestCase): diff --git a/authentik/sources/ldap/tests/test_password.py b/authentik/sources/ldap/tests/test_password.py index fa308c6c7..3b126a6be 100644 --- a/authentik/sources/ldap/tests/test_password.py +++ b/authentik/sources/ldap/tests/test_password.py @@ -4,12 +4,12 @@ from unittest.mock import PropertyMock, patch from django.test import TestCase from authentik.core.models import User -from authentik.providers.oauth2.generators import generate_client_secret +from authentik.lib.generators import generate_key from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource from authentik.sources.ldap.password import LDAPPasswordChanger from authentik.sources.ldap.tests.mock_ad import mock_ad_connection -LDAP_PASSWORD = generate_client_secret() +LDAP_PASSWORD = generate_key() LDAP_CONNECTION_PATCH = PropertyMock(return_value=mock_ad_connection(LDAP_PASSWORD)) diff --git a/authentik/sources/ldap/tests/test_sync.py b/authentik/sources/ldap/tests/test_sync.py index bd150dc02..0d158b4db 100644 --- a/authentik/sources/ldap/tests/test_sync.py +++ b/authentik/sources/ldap/tests/test_sync.py @@ -6,8 +6,8 @@ from django.test import TestCase from authentik.core.models import Group, User from authentik.events.models import Event, EventAction +from authentik.lib.generators import generate_key from authentik.managed.manager import ObjectManager -from authentik.providers.oauth2.generators import generate_client_secret from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer from authentik.sources.ldap.sync.membership import MembershipLDAPSynchronizer @@ -16,7 +16,7 @@ from authentik.sources.ldap.tasks import ldap_sync_all from authentik.sources.ldap.tests.mock_ad import mock_ad_connection from authentik.sources.ldap.tests.mock_slapd import mock_slapd_connection -LDAP_PASSWORD = generate_client_secret() +LDAP_PASSWORD = generate_key() class LDAPSyncTests(TestCase): diff --git a/authentik/sources/plex/migrations/0001_initial.py b/authentik/sources/plex/migrations/0001_initial.py index 8d04cc70a..09b37a6d0 100644 --- a/authentik/sources/plex/migrations/0001_initial.py +++ b/authentik/sources/plex/migrations/0001_initial.py @@ -4,7 +4,7 @@ import django.contrib.postgres.fields import django.db.models.deletion from django.db import migrations, models -import authentik.providers.oauth2.generators +import authentik.lib.generators class Migration(migrations.Migration): @@ -33,7 +33,7 @@ class Migration(migrations.Migration): ( "client_id", models.TextField( - default=authentik.providers.oauth2.generators.generate_client_id, + default=authentik.lib.generators.generate_id, help_text="Client identifier used to talk to Plex.", ), ), diff --git a/authentik/sources/plex/migrations/0002_auto_20210505_1717.py b/authentik/sources/plex/migrations/0002_auto_20210505_1717.py index cf5977ead..6b3d5c8b9 100644 --- a/authentik/sources/plex/migrations/0002_auto_20210505_1717.py +++ b/authentik/sources/plex/migrations/0002_auto_20210505_1717.py @@ -3,7 +3,7 @@ import django.contrib.postgres.fields from django.db import migrations, models -import authentik.providers.oauth2.generators +import authentik.lib.generators class Migration(migrations.Migration): diff --git a/authentik/sources/plex/models.py b/authentik/sources/plex/models.py index fa6a605dc..25d61823c 100644 --- a/authentik/sources/plex/models.py +++ b/authentik/sources/plex/models.py @@ -11,7 +11,7 @@ from rest_framework.serializers import BaseSerializer from authentik.core.models import Source, UserSourceConnection from authentik.core.types import UILoginButton, UserSettingSerializer from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes -from authentik.providers.oauth2.generators import generate_client_id +from authentik.lib.generators import generate_id class PlexAuthenticationChallenge(Challenge): @@ -32,7 +32,7 @@ class PlexSource(Source): """Authenticate against plex.tv""" client_id = models.TextField( - default=generate_client_id, + default=generate_id, help_text=_("Client identifier used to talk to Plex."), ) allowed_servers = ArrayField( diff --git a/authentik/sources/plex/tests.py b/authentik/sources/plex/tests.py index 21c049977..6a60433f7 100644 --- a/authentik/sources/plex/tests.py +++ b/authentik/sources/plex/tests.py @@ -4,7 +4,7 @@ from requests.exceptions import RequestException from requests_mock import Mocker from authentik.events.models import Event, EventAction -from authentik.providers.oauth2.generators import generate_client_secret +from authentik.lib.generators import generate_key from authentik.sources.plex.models import PlexSource from authentik.sources.plex.plex import PlexAuth from authentik.sources.plex.tasks import check_plex_token_all @@ -41,7 +41,7 @@ class TestPlexSource(TestCase): def test_get_user_info(self): """Test get_user_info""" - token = generate_client_secret() + token = generate_key() api = PlexAuth(self.source, token) with Mocker() as mocker: mocker.get("https://plex.tv/api/v2/user", json=USER_INFO_RESPONSE) @@ -55,7 +55,7 @@ class TestPlexSource(TestCase): def test_check_server_overlap(self): """Test check_server_overlap""" - token = generate_client_secret() + token = generate_key() api = PlexAuth(self.source, token) with Mocker() as mocker: mocker.get("https://plex.tv/api/v2/resources", json=RESOURCES_RESPONSE) diff --git a/authentik/stages/authenticator_validate/tests.py b/authentik/stages/authenticator_validate/tests.py index c5071b5cc..6eacb525a 100644 --- a/authentik/stages/authenticator_validate/tests.py +++ b/authentik/stages/authenticator_validate/tests.py @@ -11,8 +11,8 @@ from rest_framework.exceptions import ValidationError from authentik.core.models import User from authentik.flows.challenge import ChallengeTypes from authentik.flows.models import Flow, FlowStageBinding, NotConfiguredAction +from authentik.lib.generators import generate_id, generate_key from authentik.lib.tests.utils import get_request -from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice from authentik.stages.authenticator_validate.api import AuthenticatorValidateStageSerializer from authentik.stages.authenticator_validate.challenge import ( @@ -132,8 +132,8 @@ class AuthenticatorValidateStageTests(TestCase): request = self.request_factory.get("/") stage = AuthenticatorDuoStage.objects.create( name="test", - client_id=generate_client_id(), - client_secret=generate_client_secret(), + client_id=generate_id(), + client_secret=generate_key(), api_hostname="", ) duo_device = DuoDevice.objects.create( diff --git a/authentik/stages/identification/tests.py b/authentik/stages/identification/tests.py index fb2beeabe..5cd8d63cf 100644 --- a/authentik/stages/identification/tests.py +++ b/authentik/stages/identification/tests.py @@ -6,7 +6,7 @@ from django.utils.encoding import force_str from authentik.core.models import User from authentik.flows.challenge import ChallengeTypes from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding -from authentik.providers.oauth2.generators import generate_client_secret +from authentik.lib.generators import generate_key from authentik.sources.oauth.models import OAuthSource from authentik.stages.identification.models import IdentificationStage, UserFields from authentik.stages.password import BACKEND_INBUILT @@ -18,7 +18,7 @@ class TestIdentificationStage(TestCase): def setUp(self): super().setUp() - self.password = generate_client_secret() + self.password = generate_key() self.user = User.objects.create_user( username="unittest", email="test@beryju.org", password=self.password ) diff --git a/authentik/stages/password/tests.py b/authentik/stages/password/tests.py index ea4100d78..ebd1e137d 100644 --- a/authentik/stages/password/tests.py +++ b/authentik/stages/password/tests.py @@ -13,7 +13,7 @@ from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan from authentik.flows.tests.test_views import TO_STAGE_RESPONSE_MOCK from authentik.flows.views import SESSION_KEY_PLAN -from authentik.providers.oauth2.generators import generate_client_secret +from authentik.lib.generators import generate_key from authentik.stages.password import BACKEND_INBUILT from authentik.stages.password.models import PasswordStage @@ -25,7 +25,7 @@ class TestPasswordStage(TestCase): def setUp(self): super().setUp() - self.password = generate_client_secret() + self.password = generate_key() self.user = User.objects.create_user( username="unittest", email="test@beryju.org", password=self.password ) diff --git a/scripts/generate_ci_config.py b/scripts/generate_ci_config.py index e8ff268a6..6a9613ada 100644 --- a/scripts/generate_ci_config.py +++ b/scripts/generate_ci_config.py @@ -1,9 +1,9 @@ """Utility script to generate a config for CI runs""" -from authentik.providers.oauth2.generators import generate_client_id +from authentik.lib.generators import generate_id from yaml import safe_dump with open("local.env.yml", "w") as _config: safe_dump({ - "secret_key": generate_client_id(), - "log_level": "debug" + "log_level": "debug", + "secret_key": generate_id(), }, _config, default_flow_style=False) diff --git a/tests/e2e/test_flows_stage_setup.py b/tests/e2e/test_flows_stage_setup.py index 93b77733a..109266879 100644 --- a/tests/e2e/test_flows_stage_setup.py +++ b/tests/e2e/test_flows_stage_setup.py @@ -7,7 +7,7 @@ from selenium.webdriver.common.keys import Keys from authentik.core.models import User from authentik.flows.models import Flow, FlowDesignation -from authentik.providers.oauth2.generators import generate_client_secret +from authentik.lib.generators import generate_key from authentik.stages.password.models import PasswordStage from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, retry @@ -33,7 +33,7 @@ class TestFlowsStageSetup(SeleniumTestCase): stage.configure_flow = flow stage.save() - new_password = generate_client_secret() + new_password = generate_key() self.driver.get( self.url( diff --git a/tests/e2e/test_provider_oauth2_github.py b/tests/e2e/test_provider_oauth2_github.py index bd0ef5d13..40a9dd431 100644 --- a/tests/e2e/test_provider_oauth2_github.py +++ b/tests/e2e/test_provider_oauth2_github.py @@ -10,9 +10,9 @@ from selenium.webdriver.support import expected_conditions as ec from authentik.core.models import Application from authentik.flows.models import Flow +from authentik.lib.generators import generate_id, generate_key from authentik.policies.expression.models import ExpressionPolicy from authentik.policies.models import PolicyBinding -from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret from authentik.providers.oauth2.models import ClientTypes, OAuth2Provider from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, retry @@ -22,8 +22,8 @@ class TestProviderOAuth2Github(SeleniumTestCase): """test OAuth Provider flow""" def setUp(self): - self.client_id = generate_client_id() - self.client_secret = generate_client_secret() + self.client_id = generate_id() + self.client_secret = generate_key() super().setUp() def get_container_specs(self) -> Optional[dict[str, Any]]: diff --git a/tests/e2e/test_provider_oauth2_grafana.py b/tests/e2e/test_provider_oauth2_grafana.py index 289441b31..d627f5b4d 100644 --- a/tests/e2e/test_provider_oauth2_grafana.py +++ b/tests/e2e/test_provider_oauth2_grafana.py @@ -12,6 +12,7 @@ from structlog.stdlib import get_logger from authentik.core.models import Application from authentik.crypto.models import CertificateKeyPair from authentik.flows.models import Flow +from authentik.lib.generators import generate_id, generate_key from authentik.policies.expression.models import ExpressionPolicy from authentik.policies.models import PolicyBinding from authentik.providers.oauth2.constants import ( @@ -19,7 +20,6 @@ from authentik.providers.oauth2.constants import ( SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE, ) -from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret from authentik.providers.oauth2.models import ClientTypes, OAuth2Provider, ScopeMapping from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, object_manager, retry @@ -32,8 +32,8 @@ class TestProviderOAuth2OAuth(SeleniumTestCase): """test OAuth with OAuth Provider flow""" def setUp(self): - self.client_id = generate_client_id() - self.client_secret = generate_client_secret() + self.client_id = generate_id() + self.client_secret = generate_key() super().setUp() def get_container_specs(self) -> Optional[dict[str, Any]]: diff --git a/tests/e2e/test_provider_oauth2_oidc.py b/tests/e2e/test_provider_oauth2_oidc.py index 1c8dac26a..cf2eaaddb 100644 --- a/tests/e2e/test_provider_oauth2_oidc.py +++ b/tests/e2e/test_provider_oauth2_oidc.py @@ -14,6 +14,7 @@ from structlog.stdlib import get_logger from authentik.core.models import Application from authentik.crypto.models import CertificateKeyPair from authentik.flows.models import Flow +from authentik.lib.generators import generate_id, generate_key from authentik.policies.expression.models import ExpressionPolicy from authentik.policies.models import PolicyBinding from authentik.providers.oauth2.constants import ( @@ -21,7 +22,6 @@ from authentik.providers.oauth2.constants import ( SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE, ) -from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret from authentik.providers.oauth2.models import ClientTypes, OAuth2Provider, ScopeMapping from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, object_manager, retry @@ -33,8 +33,8 @@ class TestProviderOAuth2OIDC(SeleniumTestCase): """test OAuth with OpenID Provider flow""" def setUp(self): - self.client_id = generate_client_id() - self.client_secret = generate_client_secret() + self.client_id = generate_id() + self.client_secret = generate_key() self.application_slug = "test" super().setUp() diff --git a/tests/e2e/test_provider_oauth2_oidc_implicit.py b/tests/e2e/test_provider_oauth2_oidc_implicit.py index 4251817b0..b296334ce 100644 --- a/tests/e2e/test_provider_oauth2_oidc_implicit.py +++ b/tests/e2e/test_provider_oauth2_oidc_implicit.py @@ -14,6 +14,7 @@ from structlog.stdlib import get_logger from authentik.core.models import Application from authentik.crypto.models import CertificateKeyPair from authentik.flows.models import Flow +from authentik.lib.generators import generate_id, generate_key from authentik.policies.expression.models import ExpressionPolicy from authentik.policies.models import PolicyBinding from authentik.providers.oauth2.constants import ( @@ -21,7 +22,6 @@ from authentik.providers.oauth2.constants import ( SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE, ) -from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret from authentik.providers.oauth2.models import ClientTypes, OAuth2Provider, ScopeMapping from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, object_manager, retry @@ -33,8 +33,8 @@ class TestProviderOAuth2OIDCImplicit(SeleniumTestCase): """test OAuth with OpenID Provider flow""" def setUp(self): - self.client_id = generate_client_id() - self.client_secret = generate_client_secret() + self.client_id = generate_id() + self.client_secret = generate_key() self.application_slug = "test" super().setUp() diff --git a/tests/e2e/test_source_oauth.py b/tests/e2e/test_source_oauth.py index e2dba3b27..8d665fcb7 100644 --- a/tests/e2e/test_source_oauth.py +++ b/tests/e2e/test_source_oauth.py @@ -18,7 +18,7 @@ from yaml import safe_dump from authentik.core.models import User from authentik.flows.models import Flow -from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret +from authentik.lib.generators import generate_id, generate_key from authentik.sources.oauth.models import OAuthSource from authentik.sources.oauth.types.manager import SourceType from authentik.sources.oauth.types.twitter import TwitterOAuthCallback @@ -53,7 +53,7 @@ class TestSourceOAuth2(SeleniumTestCase): container: Container def setUp(self): - self.client_secret = generate_client_secret() + self.client_secret = generate_key() self.prepare_dex_config() super().setUp() @@ -264,8 +264,8 @@ class TestSourceOAuth1(SeleniumTestCase): """Test OAuth1 Source""" def setUp(self) -> None: - self.client_id = generate_client_id() - self.client_secret = generate_client_secret() + self.client_id = generate_id() + self.client_secret = generate_key() self.source_slug = "oauth1-test" super().setUp() diff --git a/web/rollup.config.js b/web/rollup.config.js index 89f19ddf0..a06e836c9 100644 --- a/web/rollup.config.js +++ b/web/rollup.config.js @@ -90,6 +90,7 @@ export default [ // Main Application { input: "./src/interfaces/AdminInterface.ts", + context: "window", output: [ { format: "es", @@ -122,6 +123,7 @@ export default [ // Flow executor { input: "./src/interfaces/FlowInterface.ts", + context: "window", output: [ { format: "es", diff --git a/web/src/elements/buttons/ActionButton.ts b/web/src/elements/buttons/ActionButton.ts index c17d381a1..ef87760e5 100644 --- a/web/src/elements/buttons/ActionButton.ts +++ b/web/src/elements/buttons/ActionButton.ts @@ -27,7 +27,6 @@ export class ActionButton extends SpinnerButton { }); }); } - throw e; }); }; }