Merge branch 'master' into app-passwords

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	authentik/core/tests/test_source_flow_manager.py
#	authentik/stages/authenticator_validate/tests.py
#	authentik/stages/password/tests.py
#	scripts/generate_ci_config.py
This commit is contained in:
Jens Langhammer 2021-08-23 20:30:58 +02:00
commit cba255eaaa
34 changed files with 126 additions and 119 deletions

View file

@ -33,7 +33,7 @@ def bearer_auth(raw_header: bytes) -> Optional[User]:
raise AuthenticationFailed("Malformed header") raise AuthenticationFailed("Malformed header")
# Accept credentials with username and without # Accept credentials with username and without
if ":" in auth_credentials: if ":" in auth_credentials:
_, password = auth_credentials.split(":") _, _, password = auth_credentials.partition(":")
else: else:
password = auth_credentials password = auth_credentials
if password == "": # nosec if password == "": # nosec

View file

@ -28,6 +28,7 @@ from authentik.core.signals import password_changed
from authentik.core.types import UILoginButton, UserSettingSerializer from authentik.core.types import UILoginButton, UserSettingSerializer
from authentik.flows.models import Flow from authentik.flows.models import Flow
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.lib.generators import generate_id
from authentik.lib.models import CreatedUpdatedModel, SerializerModel from authentik.lib.models import CreatedUpdatedModel, SerializerModel
from authentik.lib.utils.http import get_client_ip from authentik.lib.utils.http import get_client_ip
from authentik.managed.models import ManagedModel from authentik.managed.models import ManagedModel
@ -54,7 +55,9 @@ def default_token_duration():
def default_token_key(): def default_token_key():
"""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): class Group(models.Model):

View file

@ -6,8 +6,8 @@ from guardian.utils import get_anonymous_user
from authentik.core.models import SourceUserMatchingModes, User from authentik.core.models import SourceUserMatchingModes, User
from authentik.core.sources.flow_manager import Action 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.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.models import OAuthSource, UserOAuthSourceConnection
from authentik.sources.oauth.views.callback import OAuthSourceFlowManager from authentik.sources.oauth.views.callback import OAuthSourceFlowManager
@ -19,7 +19,7 @@ class TestSourceFlowManager(TestCase):
super().setUp() super().setUp()
self.source = OAuthSource.objects.create(name="test") self.source = OAuthSource.objects.create(name="test")
self.factory = RequestFactory() self.factory = RequestFactory()
self.identifier = generate_client_id() self.identifier = generate_id()
def test_unauthenticated_enroll(self): def test_unauthenticated_enroll(self):
"""Test un-authenticated user enrolling""" """Test un-authenticated user enrolling"""

View file

@ -10,7 +10,7 @@ from authentik.crypto.api import CertificateKeyPairSerializer
from authentik.crypto.builder import CertificateBuilder from authentik.crypto.builder import CertificateBuilder
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow 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 from authentik.providers.oauth2.models import OAuth2Provider
@ -103,7 +103,7 @@ class TestCrypto(TestCase):
provider = OAuth2Provider.objects.create( provider = OAuth2Provider.objects.create(
name="test", name="test",
client_id="test", client_id="test",
client_secret=generate_client_secret(), client_secret=generate_key(),
authorization_flow=Flow.objects.first(), authorization_flow=Flow.objects.first(),
redirect_uris="http://localhost", redirect_uris="http://localhost",
rsa_key=CertificateKeyPair.objects.first(), rsa_key=CertificateKeyPair.objects.first(),

View file

@ -7,9 +7,9 @@ from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
from authentik.flows.transfer.common import DataclassEncoder from authentik.flows.transfer.common import DataclassEncoder
from authentik.flows.transfer.exporter import FlowExporter from authentik.flows.transfer.exporter import FlowExporter
from authentik.flows.transfer.importer import FlowImporter, transaction_rollback 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.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding 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.prompt.models import FieldTypes, Prompt, PromptStage
from authentik.stages.user_login.models import UserLoginStage from authentik.stages.user_login.models import UserLoginStage
@ -31,15 +31,15 @@ class TestFlowTransfer(TransactionTestCase):
def test_export_validate_import(self): def test_export_validate_import(self):
"""Test export and validate it""" """Test export and validate it"""
flow_slug = generate_client_id() flow_slug = generate_id()
with transaction_rollback(): with transaction_rollback():
login_stage = UserLoginStage.objects.create(name=generate_client_id()) login_stage = UserLoginStage.objects.create(name=generate_id())
flow = Flow.objects.create( flow = Flow.objects.create(
slug=flow_slug, slug=flow_slug,
designation=FlowDesignation.AUTHENTICATION, designation=FlowDesignation.AUTHENTICATION,
name=generate_client_id(), name=generate_id(),
title=generate_client_id(), title=generate_id(),
) )
FlowStageBinding.objects.update_or_create( FlowStageBinding.objects.update_or_create(
target=flow, target=flow,
@ -60,18 +60,18 @@ class TestFlowTransfer(TransactionTestCase):
def test_export_validate_import_policies(self): def test_export_validate_import_policies(self):
"""Test export and validate it""" """Test export and validate it"""
flow_slug = generate_client_id() flow_slug = generate_id()
stage_name = generate_client_id() stage_name = generate_id()
with transaction_rollback(): with transaction_rollback():
flow_policy = ExpressionPolicy.objects.create( flow_policy = ExpressionPolicy.objects.create(
name=generate_client_id(), name=generate_id(),
expression="return True", expression="return True",
) )
flow = Flow.objects.create( flow = Flow.objects.create(
slug=flow_slug, slug=flow_slug,
designation=FlowDesignation.AUTHENTICATION, designation=FlowDesignation.AUTHENTICATION,
name=generate_client_id(), name=generate_id(),
title=generate_client_id(), title=generate_id(),
) )
PolicyBinding.objects.create(policy=flow_policy, target=flow, order=0) PolicyBinding.objects.create(policy=flow_policy, target=flow, order=0)
@ -111,15 +111,15 @@ class TestFlowTransfer(TransactionTestCase):
) )
# Stages # 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.fields.set([username_prompt, password, password_repeat])
first_stage.save() first_stage.save()
flow = Flow.objects.create( flow = Flow.objects.create(
name=generate_client_id(), name=generate_id(),
slug=generate_client_id(), slug=generate_id(),
designation=FlowDesignation.ENROLLMENT, designation=FlowDesignation.ENROLLMENT,
title=generate_client_id(), title=generate_id(),
) )
FlowStageBinding.objects.create(target=flow, stage=first_stage, order=0) FlowStageBinding.objects.create(target=flow, stage=first_stage, order=0)

View file

@ -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)
)

View file

@ -2,9 +2,9 @@
from django.test import TestCase from django.test import TestCase
from guardian.shortcuts import get_anonymous_user from guardian.shortcuts import get_anonymous_user
from authentik.lib.generators import generate_key
from authentik.policies.hibp.models import HaveIBeenPwendPolicy from authentik.policies.hibp.models import HaveIBeenPwendPolicy
from authentik.policies.types import PolicyRequest, PolicyResult from authentik.policies.types import PolicyRequest, PolicyResult
from authentik.providers.oauth2.generators import generate_client_secret
class TestHIBPPolicy(TestCase): class TestHIBPPolicy(TestCase):
@ -37,7 +37,7 @@ class TestHIBPPolicy(TestCase):
name="test_true", name="test_true",
) )
request = PolicyRequest(get_anonymous_user()) request = PolicyRequest(get_anonymous_user())
request.context["password"] = generate_client_secret() request.context["password"] = generate_key()
result: PolicyResult = policy.passes(request) result: PolicyResult = policy.passes(request)
self.assertTrue(result.passing) self.assertTrue(result.passing)
self.assertEqual(result.messages, tuple()) self.assertEqual(result.messages, tuple())

View file

@ -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))

View file

@ -7,8 +7,8 @@ from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor from django.db.backends.base.schema import BaseDatabaseSchemaEditor
import authentik.core.models import authentik.core.models
import authentik.lib.generators
import authentik.lib.utils.time import authentik.lib.utils.time
import authentik.providers.oauth2.generators
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -55,7 +55,7 @@ class Migration(migrations.Migration):
( (
"client_id", "client_id",
models.CharField( models.CharField(
default=authentik.providers.oauth2.generators.generate_client_id, default=authentik.lib.generators.generate_id,
max_length=255, max_length=255,
unique=True, unique=True,
verbose_name="Client ID", verbose_name="Client ID",
@ -65,7 +65,7 @@ class Migration(migrations.Migration):
"client_secret", "client_secret",
models.CharField( models.CharField(
blank=True, blank=True,
default=authentik.providers.oauth2.generators.generate_client_secret, default=authentik.lib.generators.generate_key,
max_length=255, max_length=255,
verbose_name="Client Secret", verbose_name="Client Secret",
), ),

View file

@ -22,10 +22,10 @@ from authentik.core.models import ExpiringModel, PropertyMapping, Provider, User
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.events.utils import get_user 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.lib.utils.time import timedelta_from_string, timedelta_string_validator
from authentik.providers.oauth2.apps import AuthentikProviderOAuth2Config from authentik.providers.oauth2.apps import AuthentikProviderOAuth2Config
from authentik.providers.oauth2.constants import ACR_AUTHENTIK_DEFAULT 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): class ClientTypes(models.TextChoices):
@ -138,13 +138,13 @@ class OAuth2Provider(Provider):
max_length=255, max_length=255,
unique=True, unique=True,
verbose_name=_("Client ID"), verbose_name=_("Client ID"),
default=generate_client_id, default=generate_id,
) )
client_secret = models.CharField( client_secret = models.CharField(
max_length=255, max_length=255,
blank=True, blank=True,
verbose_name=_("Client Secret"), verbose_name=_("Client Secret"),
default=generate_client_secret, default=generate_key,
) )
jwt_alg = models.CharField( jwt_alg = models.CharField(
max_length=10, max_length=10,

View file

@ -7,8 +7,8 @@ from authentik.core.models import Application, User
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.flows.challenge import ChallengeTypes from authentik.flows.challenge import ChallengeTypes
from authentik.flows.models import Flow 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.errors import AuthorizeError, ClientIdError, RedirectUriError
from authentik.providers.oauth2.generators import generate_client_id, generate_client_secret
from authentik.providers.oauth2.models import ( from authentik.providers.oauth2.models import (
AuthorizationCode, AuthorizationCode,
GrantTypes, GrantTypes,
@ -183,7 +183,7 @@ class TestAuthorize(OAuthTestCase):
redirect_uris="foo://localhost", redirect_uris="foo://localhost",
) )
Application.objects.create(name="app", slug="app", provider=provider) Application.objects.create(name="app", slug="app", provider=provider)
state = generate_client_id() state = generate_id()
user = User.objects.get(username="akadmin") user = User.objects.get(username="akadmin")
self.client.force_login(user) self.client.force_login(user)
# Step 1, initiate params and get redirect to flow # Step 1, initiate params and get redirect to flow
@ -215,13 +215,13 @@ class TestAuthorize(OAuthTestCase):
provider = OAuth2Provider.objects.create( provider = OAuth2Provider.objects.create(
name="test", name="test",
client_id="test", client_id="test",
client_secret=generate_client_secret(), client_secret=generate_key(),
authorization_flow=flow, authorization_flow=flow,
redirect_uris="http://localhost", redirect_uris="http://localhost",
rsa_key=CertificateKeyPair.objects.first(), rsa_key=CertificateKeyPair.objects.first(),
) )
Application.objects.create(name="app", slug="app", provider=provider) Application.objects.create(name="app", slug="app", provider=provider)
state = generate_client_id() state = generate_id()
user = User.objects.get(username="akadmin") user = User.objects.get(username="akadmin")
self.client.force_login(user) self.client.force_login(user)
# Step 1, initiate params and get redirect to flow # Step 1, initiate params and get redirect to flow

View file

@ -9,12 +9,12 @@ from authentik.core.models import Application, User
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.flows.models import Flow from authentik.flows.models import Flow
from authentik.lib.generators import generate_id, generate_key
from authentik.providers.oauth2.constants import ( from authentik.providers.oauth2.constants import (
GRANT_TYPE_AUTHORIZATION_CODE, GRANT_TYPE_AUTHORIZATION_CODE,
GRANT_TYPE_REFRESH_TOKEN, GRANT_TYPE_REFRESH_TOKEN,
) )
from authentik.providers.oauth2.errors import TokenError 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.models import AuthorizationCode, OAuth2Provider, RefreshToken
from authentik.providers.oauth2.tests.utils import OAuthTestCase from authentik.providers.oauth2.tests.utils import OAuthTestCase
from authentik.providers.oauth2.views.token import TokenParams from authentik.providers.oauth2.views.token import TokenParams
@ -32,8 +32,8 @@ class TestToken(OAuthTestCase):
"""test request param""" """test request param"""
provider = OAuth2Provider.objects.create( provider = OAuth2Provider.objects.create(
name="test", name="test",
client_id=generate_client_id(), client_id=generate_id(),
client_secret=generate_client_secret(), client_secret=generate_key(),
authorization_flow=Flow.objects.first(), authorization_flow=Flow.objects.first(),
redirect_uris="http://testserver", redirect_uris="http://testserver",
rsa_key=CertificateKeyPair.objects.first(), rsa_key=CertificateKeyPair.objects.first(),
@ -53,14 +53,14 @@ class TestToken(OAuthTestCase):
params = TokenParams.parse(request, provider, provider.client_id, provider.client_secret) params = TokenParams.parse(request, provider, provider.client_id, provider.client_secret)
self.assertEqual(params.provider, provider) self.assertEqual(params.provider, provider)
with self.assertRaises(TokenError): 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): def test_request_auth_code_invalid(self):
"""test request param""" """test request param"""
provider = OAuth2Provider.objects.create( provider = OAuth2Provider.objects.create(
name="test", name="test",
client_id=generate_client_id(), client_id=generate_id(),
client_secret=generate_client_secret(), client_secret=generate_key(),
authorization_flow=Flow.objects.first(), authorization_flow=Flow.objects.first(),
redirect_uris="http://testserver", redirect_uris="http://testserver",
rsa_key=CertificateKeyPair.objects.first(), rsa_key=CertificateKeyPair.objects.first(),
@ -82,8 +82,8 @@ class TestToken(OAuthTestCase):
"""test request param""" """test request param"""
provider = OAuth2Provider.objects.create( provider = OAuth2Provider.objects.create(
name="test", name="test",
client_id=generate_client_id(), client_id=generate_id(),
client_secret=generate_client_secret(), client_secret=generate_key(),
authorization_flow=Flow.objects.first(), authorization_flow=Flow.objects.first(),
redirect_uris="http://local.invalid", redirect_uris="http://local.invalid",
rsa_key=CertificateKeyPair.objects.first(), rsa_key=CertificateKeyPair.objects.first(),
@ -93,7 +93,7 @@ class TestToken(OAuthTestCase):
token: RefreshToken = RefreshToken.objects.create( token: RefreshToken = RefreshToken.objects.create(
provider=provider, provider=provider,
user=user, user=user,
refresh_token=generate_client_id(), refresh_token=generate_id(),
) )
request = self.factory.post( request = self.factory.post(
"/", "/",
@ -111,8 +111,8 @@ class TestToken(OAuthTestCase):
"""test request param""" """test request param"""
provider = OAuth2Provider.objects.create( provider = OAuth2Provider.objects.create(
name="test", name="test",
client_id=generate_client_id(), client_id=generate_id(),
client_secret=generate_client_secret(), client_secret=generate_key(),
authorization_flow=Flow.objects.first(), authorization_flow=Flow.objects.first(),
redirect_uris="http://local.invalid", redirect_uris="http://local.invalid",
rsa_key=CertificateKeyPair.objects.first(), rsa_key=CertificateKeyPair.objects.first(),
@ -153,8 +153,8 @@ class TestToken(OAuthTestCase):
"""test request param""" """test request param"""
provider = OAuth2Provider.objects.create( provider = OAuth2Provider.objects.create(
name="test", name="test",
client_id=generate_client_id(), client_id=generate_id(),
client_secret=generate_client_secret(), client_secret=generate_key(),
authorization_flow=Flow.objects.first(), authorization_flow=Flow.objects.first(),
redirect_uris="http://local.invalid", redirect_uris="http://local.invalid",
rsa_key=CertificateKeyPair.objects.first(), rsa_key=CertificateKeyPair.objects.first(),
@ -167,7 +167,7 @@ class TestToken(OAuthTestCase):
token: RefreshToken = RefreshToken.objects.create( token: RefreshToken = RefreshToken.objects.create(
provider=provider, provider=provider,
user=user, user=user,
refresh_token=generate_client_id(), refresh_token=generate_id(),
) )
response = self.client.post( response = self.client.post(
reverse("authentik_providers_oauth2:token"), reverse("authentik_providers_oauth2:token"),
@ -202,8 +202,8 @@ class TestToken(OAuthTestCase):
"""test request param""" """test request param"""
provider = OAuth2Provider.objects.create( provider = OAuth2Provider.objects.create(
name="test", name="test",
client_id=generate_client_id(), client_id=generate_id(),
client_secret=generate_client_secret(), client_secret=generate_key(),
authorization_flow=Flow.objects.first(), authorization_flow=Flow.objects.first(),
redirect_uris="http://local.invalid", redirect_uris="http://local.invalid",
rsa_key=CertificateKeyPair.objects.first(), rsa_key=CertificateKeyPair.objects.first(),
@ -213,7 +213,7 @@ class TestToken(OAuthTestCase):
token: RefreshToken = RefreshToken.objects.create( token: RefreshToken = RefreshToken.objects.create(
provider=provider, provider=provider,
user=user, user=user,
refresh_token=generate_client_id(), refresh_token=generate_id(),
) )
response = self.client.post( response = self.client.post(
reverse("authentik_providers_oauth2:token"), reverse("authentik_providers_oauth2:token"),
@ -247,8 +247,8 @@ class TestToken(OAuthTestCase):
"""test request param""" """test request param"""
provider = OAuth2Provider.objects.create( provider = OAuth2Provider.objects.create(
name="test", name="test",
client_id=generate_client_id(), client_id=generate_id(),
client_secret=generate_client_secret(), client_secret=generate_key(),
authorization_flow=Flow.objects.first(), authorization_flow=Flow.objects.first(),
redirect_uris="http://testserver", redirect_uris="http://testserver",
rsa_key=CertificateKeyPair.objects.first(), rsa_key=CertificateKeyPair.objects.first(),
@ -261,7 +261,7 @@ class TestToken(OAuthTestCase):
token: RefreshToken = RefreshToken.objects.create( token: RefreshToken = RefreshToken.objects.create(
provider=provider, provider=provider,
user=user, user=user,
refresh_token=generate_client_id(), refresh_token=generate_id(),
) )
# Create initial refresh token # Create initial refresh token
response = self.client.post( response = self.client.post(

View file

@ -9,8 +9,8 @@ from authentik.core.models import Application, User
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.flows.models import Flow from authentik.flows.models import Flow
from authentik.lib.generators import generate_id, generate_key
from authentik.managed.manager import ObjectManager 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.models import IDToken, OAuth2Provider, RefreshToken, ScopeMapping
from authentik.providers.oauth2.tests.utils import OAuthTestCase 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.app = Application.objects.create(name="test", slug="test")
self.provider: OAuth2Provider = OAuth2Provider.objects.create( self.provider: OAuth2Provider = OAuth2Provider.objects.create(
name="test", name="test",
client_id=generate_client_id(), client_id=generate_id(),
client_secret=generate_client_secret(), client_secret=generate_key(),
authorization_flow=Flow.objects.first(), authorization_flow=Flow.objects.first(),
redirect_uris="", redirect_uris="",
rsa_key=CertificateKeyPair.objects.first(), rsa_key=CertificateKeyPair.objects.first(),
@ -38,8 +38,8 @@ class TestUserinfo(OAuthTestCase):
self.token: RefreshToken = RefreshToken.objects.create( self.token: RefreshToken = RefreshToken.objects.create(
provider=self.provider, provider=self.provider,
user=self.user, user=self.user,
access_token=generate_client_id(), access_token=generate_id(),
refresh_token=generate_client_id(), refresh_token=generate_id(),
_scope="openid user profile", _scope="openid user profile",
_id_token=json.dumps( _id_token=json.dumps(
asdict( asdict(

View file

@ -103,8 +103,8 @@ def extract_client_auth(request: HttpRequest) -> tuple[str, str]:
if re.compile(r"^Basic\s{1}.+$").match(auth_header): if re.compile(r"^Basic\s{1}.+$").match(auth_header):
b64_user_pass = auth_header.split()[1] b64_user_pass = auth_header.split()[1]
try: try:
user_pass = b64decode(b64_user_pass).decode("utf-8").split(":") user_pass = b64decode(b64_user_pass).decode("utf-8").partition(":")
client_id, client_secret = user_pass client_id, _, client_secret = user_pass
except (ValueError, Error): except (ValueError, Error):
client_id = client_secret = "" # nosec client_id = client_secret = "" # nosec
else: else:

View file

@ -1,11 +1,11 @@
"""LDAP Source API tests""" """LDAP Source API tests"""
from rest_framework.test import APITestCase 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.api import LDAPSourceSerializer
from authentik.sources.ldap.models import LDAPSource from authentik.sources.ldap.models import LDAPSource
LDAP_PASSWORD = generate_client_secret() LDAP_PASSWORD = generate_key()
class LDAPAPITests(APITestCase): class LDAPAPITests(APITestCase):

View file

@ -5,15 +5,15 @@ from django.db.models import Q
from django.test import TestCase from django.test import TestCase
from authentik.core.models import User from authentik.core.models import User
from authentik.lib.generators import generate_key
from authentik.managed.manager import ObjectManager 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.auth import LDAPBackend
from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource
from authentik.sources.ldap.sync.users import UserLDAPSynchronizer 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_ad import mock_ad_connection
from authentik.sources.ldap.tests.mock_slapd import mock_slapd_connection from authentik.sources.ldap.tests.mock_slapd import mock_slapd_connection
LDAP_PASSWORD = generate_client_secret() LDAP_PASSWORD = generate_key()
class LDAPSyncTests(TestCase): class LDAPSyncTests(TestCase):

View file

@ -4,12 +4,12 @@ from unittest.mock import PropertyMock, patch
from django.test import TestCase from django.test import TestCase
from authentik.core.models import User 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.models import LDAPPropertyMapping, LDAPSource
from authentik.sources.ldap.password import LDAPPasswordChanger from authentik.sources.ldap.password import LDAPPasswordChanger
from authentik.sources.ldap.tests.mock_ad import mock_ad_connection 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)) LDAP_CONNECTION_PATCH = PropertyMock(return_value=mock_ad_connection(LDAP_PASSWORD))

View file

@ -6,8 +6,8 @@ from django.test import TestCase
from authentik.core.models import Group, User from authentik.core.models import Group, User
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.lib.generators import generate_key
from authentik.managed.manager import ObjectManager 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.models import LDAPPropertyMapping, LDAPSource
from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer
from authentik.sources.ldap.sync.membership import MembershipLDAPSynchronizer 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_ad import mock_ad_connection
from authentik.sources.ldap.tests.mock_slapd import mock_slapd_connection from authentik.sources.ldap.tests.mock_slapd import mock_slapd_connection
LDAP_PASSWORD = generate_client_secret() LDAP_PASSWORD = generate_key()
class LDAPSyncTests(TestCase): class LDAPSyncTests(TestCase):

View file

@ -4,7 +4,7 @@ import django.contrib.postgres.fields
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models from django.db import migrations, models
import authentik.providers.oauth2.generators import authentik.lib.generators
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -33,7 +33,7 @@ class Migration(migrations.Migration):
( (
"client_id", "client_id",
models.TextField( 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.", help_text="Client identifier used to talk to Plex.",
), ),
), ),

View file

@ -3,7 +3,7 @@
import django.contrib.postgres.fields import django.contrib.postgres.fields
from django.db import migrations, models from django.db import migrations, models
import authentik.providers.oauth2.generators import authentik.lib.generators
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -11,7 +11,7 @@ from rest_framework.serializers import BaseSerializer
from authentik.core.models import Source, UserSourceConnection from authentik.core.models import Source, UserSourceConnection
from authentik.core.types import UILoginButton, UserSettingSerializer from authentik.core.types import UILoginButton, UserSettingSerializer
from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes 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): class PlexAuthenticationChallenge(Challenge):
@ -32,7 +32,7 @@ class PlexSource(Source):
"""Authenticate against plex.tv""" """Authenticate against plex.tv"""
client_id = models.TextField( client_id = models.TextField(
default=generate_client_id, default=generate_id,
help_text=_("Client identifier used to talk to Plex."), help_text=_("Client identifier used to talk to Plex."),
) )
allowed_servers = ArrayField( allowed_servers = ArrayField(

View file

@ -4,7 +4,7 @@ from requests.exceptions import RequestException
from requests_mock import Mocker from requests_mock import Mocker
from authentik.events.models import Event, EventAction 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.models import PlexSource
from authentik.sources.plex.plex import PlexAuth from authentik.sources.plex.plex import PlexAuth
from authentik.sources.plex.tasks import check_plex_token_all from authentik.sources.plex.tasks import check_plex_token_all
@ -41,7 +41,7 @@ class TestPlexSource(TestCase):
def test_get_user_info(self): def test_get_user_info(self):
"""Test get_user_info""" """Test get_user_info"""
token = generate_client_secret() token = generate_key()
api = PlexAuth(self.source, token) api = PlexAuth(self.source, token)
with Mocker() as mocker: with Mocker() as mocker:
mocker.get("https://plex.tv/api/v2/user", json=USER_INFO_RESPONSE) 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): def test_check_server_overlap(self):
"""Test check_server_overlap""" """Test check_server_overlap"""
token = generate_client_secret() token = generate_key()
api = PlexAuth(self.source, token) api = PlexAuth(self.source, token)
with Mocker() as mocker: with Mocker() as mocker:
mocker.get("https://plex.tv/api/v2/resources", json=RESOURCES_RESPONSE) mocker.get("https://plex.tv/api/v2/resources", json=RESOURCES_RESPONSE)

View file

@ -11,8 +11,8 @@ from rest_framework.exceptions import ValidationError
from authentik.core.models import User from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes from authentik.flows.challenge import ChallengeTypes
from authentik.flows.models import Flow, FlowStageBinding, NotConfiguredAction 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.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_duo.models import AuthenticatorDuoStage, DuoDevice
from authentik.stages.authenticator_validate.api import AuthenticatorValidateStageSerializer from authentik.stages.authenticator_validate.api import AuthenticatorValidateStageSerializer
from authentik.stages.authenticator_validate.challenge import ( from authentik.stages.authenticator_validate.challenge import (
@ -132,8 +132,8 @@ class AuthenticatorValidateStageTests(TestCase):
request = self.request_factory.get("/") request = self.request_factory.get("/")
stage = AuthenticatorDuoStage.objects.create( stage = AuthenticatorDuoStage.objects.create(
name="test", name="test",
client_id=generate_client_id(), client_id=generate_id(),
client_secret=generate_client_secret(), client_secret=generate_key(),
api_hostname="", api_hostname="",
) )
duo_device = DuoDevice.objects.create( duo_device = DuoDevice.objects.create(

View file

@ -6,7 +6,7 @@ from django.utils.encoding import force_str
from authentik.core.models import User from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes from authentik.flows.challenge import ChallengeTypes
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding 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.sources.oauth.models import OAuthSource
from authentik.stages.identification.models import IdentificationStage, UserFields from authentik.stages.identification.models import IdentificationStage, UserFields
from authentik.stages.password import BACKEND_INBUILT from authentik.stages.password import BACKEND_INBUILT
@ -18,7 +18,7 @@ class TestIdentificationStage(TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.password = generate_client_secret() self.password = generate_key()
self.user = User.objects.create_user( self.user = User.objects.create_user(
username="unittest", email="test@beryju.org", password=self.password username="unittest", email="test@beryju.org", password=self.password
) )

View file

@ -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.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
from authentik.flows.tests.test_views import TO_STAGE_RESPONSE_MOCK from authentik.flows.tests.test_views import TO_STAGE_RESPONSE_MOCK
from authentik.flows.views import SESSION_KEY_PLAN 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 import BACKEND_INBUILT
from authentik.stages.password.models import PasswordStage from authentik.stages.password.models import PasswordStage
@ -25,7 +25,7 @@ class TestPasswordStage(TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.password = generate_client_secret() self.password = generate_key()
self.user = User.objects.create_user( self.user = User.objects.create_user(
username="unittest", email="test@beryju.org", password=self.password username="unittest", email="test@beryju.org", password=self.password
) )

View file

@ -1,9 +1,9 @@
"""Utility script to generate a config for CI runs""" """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 from yaml import safe_dump
with open("local.env.yml", "w") as _config: with open("local.env.yml", "w") as _config:
safe_dump({ safe_dump({
"secret_key": generate_client_id(), "log_level": "debug",
"log_level": "debug" "secret_key": generate_id(),
}, _config, default_flow_style=False) }, _config, default_flow_style=False)

View file

@ -7,7 +7,7 @@ from selenium.webdriver.common.keys import Keys
from authentik.core.models import User from authentik.core.models import User
from authentik.flows.models import Flow, FlowDesignation 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 authentik.stages.password.models import PasswordStage
from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, retry from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, retry
@ -33,7 +33,7 @@ class TestFlowsStageSetup(SeleniumTestCase):
stage.configure_flow = flow stage.configure_flow = flow
stage.save() stage.save()
new_password = generate_client_secret() new_password = generate_key()
self.driver.get( self.driver.get(
self.url( self.url(

View file

@ -10,9 +10,9 @@ from selenium.webdriver.support import expected_conditions as ec
from authentik.core.models import Application from authentik.core.models import Application
from authentik.flows.models import Flow 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.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding 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 authentik.providers.oauth2.models import ClientTypes, OAuth2Provider
from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, retry from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, retry
@ -22,8 +22,8 @@ class TestProviderOAuth2Github(SeleniumTestCase):
"""test OAuth Provider flow""" """test OAuth Provider flow"""
def setUp(self): def setUp(self):
self.client_id = generate_client_id() self.client_id = generate_id()
self.client_secret = generate_client_secret() self.client_secret = generate_key()
super().setUp() super().setUp()
def get_container_specs(self) -> Optional[dict[str, Any]]: def get_container_specs(self) -> Optional[dict[str, Any]]:

View file

@ -12,6 +12,7 @@ from structlog.stdlib import get_logger
from authentik.core.models import Application from authentik.core.models import Application
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow 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.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding from authentik.policies.models import PolicyBinding
from authentik.providers.oauth2.constants import ( from authentik.providers.oauth2.constants import (
@ -19,7 +20,6 @@ from authentik.providers.oauth2.constants import (
SCOPE_OPENID_EMAIL, SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE, 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 authentik.providers.oauth2.models import ClientTypes, OAuth2Provider, ScopeMapping
from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, object_manager, retry 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""" """test OAuth with OAuth Provider flow"""
def setUp(self): def setUp(self):
self.client_id = generate_client_id() self.client_id = generate_id()
self.client_secret = generate_client_secret() self.client_secret = generate_key()
super().setUp() super().setUp()
def get_container_specs(self) -> Optional[dict[str, Any]]: def get_container_specs(self) -> Optional[dict[str, Any]]:

View file

@ -14,6 +14,7 @@ from structlog.stdlib import get_logger
from authentik.core.models import Application from authentik.core.models import Application
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow 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.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding from authentik.policies.models import PolicyBinding
from authentik.providers.oauth2.constants import ( from authentik.providers.oauth2.constants import (
@ -21,7 +22,6 @@ from authentik.providers.oauth2.constants import (
SCOPE_OPENID_EMAIL, SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE, 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 authentik.providers.oauth2.models import ClientTypes, OAuth2Provider, ScopeMapping
from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, object_manager, retry 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""" """test OAuth with OpenID Provider flow"""
def setUp(self): def setUp(self):
self.client_id = generate_client_id() self.client_id = generate_id()
self.client_secret = generate_client_secret() self.client_secret = generate_key()
self.application_slug = "test" self.application_slug = "test"
super().setUp() super().setUp()

View file

@ -14,6 +14,7 @@ from structlog.stdlib import get_logger
from authentik.core.models import Application from authentik.core.models import Application
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow 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.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding from authentik.policies.models import PolicyBinding
from authentik.providers.oauth2.constants import ( from authentik.providers.oauth2.constants import (
@ -21,7 +22,6 @@ from authentik.providers.oauth2.constants import (
SCOPE_OPENID_EMAIL, SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE, 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 authentik.providers.oauth2.models import ClientTypes, OAuth2Provider, ScopeMapping
from tests.e2e.utils import USER, SeleniumTestCase, apply_migration, object_manager, retry 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""" """test OAuth with OpenID Provider flow"""
def setUp(self): def setUp(self):
self.client_id = generate_client_id() self.client_id = generate_id()
self.client_secret = generate_client_secret() self.client_secret = generate_key()
self.application_slug = "test" self.application_slug = "test"
super().setUp() super().setUp()

View file

@ -18,7 +18,7 @@ from yaml import safe_dump
from authentik.core.models import User from authentik.core.models import User
from authentik.flows.models import Flow 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.models import OAuthSource
from authentik.sources.oauth.types.manager import SourceType from authentik.sources.oauth.types.manager import SourceType
from authentik.sources.oauth.types.twitter import TwitterOAuthCallback from authentik.sources.oauth.types.twitter import TwitterOAuthCallback
@ -53,7 +53,7 @@ class TestSourceOAuth2(SeleniumTestCase):
container: Container container: Container
def setUp(self): def setUp(self):
self.client_secret = generate_client_secret() self.client_secret = generate_key()
self.prepare_dex_config() self.prepare_dex_config()
super().setUp() super().setUp()
@ -264,8 +264,8 @@ class TestSourceOAuth1(SeleniumTestCase):
"""Test OAuth1 Source""" """Test OAuth1 Source"""
def setUp(self) -> None: def setUp(self) -> None:
self.client_id = generate_client_id() self.client_id = generate_id()
self.client_secret = generate_client_secret() self.client_secret = generate_key()
self.source_slug = "oauth1-test" self.source_slug = "oauth1-test"
super().setUp() super().setUp()

View file

@ -90,6 +90,7 @@ export default [
// Main Application // Main Application
{ {
input: "./src/interfaces/AdminInterface.ts", input: "./src/interfaces/AdminInterface.ts",
context: "window",
output: [ output: [
{ {
format: "es", format: "es",
@ -122,6 +123,7 @@ export default [
// Flow executor // Flow executor
{ {
input: "./src/interfaces/FlowInterface.ts", input: "./src/interfaces/FlowInterface.ts",
context: "window",
output: [ output: [
{ {
format: "es", format: "es",

View file

@ -27,7 +27,6 @@ export class ActionButton extends SpinnerButton {
}); });
}); });
} }
throw e;
}); });
}; };
} }