Skip to content

Commit f9d2394

Browse files
authored
Merge branch 'main' into cpierre/ldap
Signed-off-by: Jens L. <[email protected]>
2 parents 0344b12 + e679066 commit f9d2394

File tree

20 files changed

+188
-56
lines changed

20 files changed

+188
-56
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: authentik-on-release-next-branch
2+
3+
on:
4+
schedule:
5+
- cron: "0 12 * * *" # every day at noon
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
update-next:
13+
runs-on: ubuntu-latest
14+
environment: internal-production
15+
steps:
16+
- uses: actions/checkout@v3
17+
with:
18+
ref: main
19+
- id: main-status
20+
run: |
21+
status=$(curl -fsSL -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ github.token }}" "https://api.github.com/repos/${{ github.repository }}/commits/HEAD/status" | jq -r '.status')
22+
echo "status=${status}" >> $GITHUB_OUTPUT
23+
- if: ${{ steps.main-status.outputs.status == 'success' }}
24+
run: |
25+
git push origin next --force

authentik/core/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,10 +376,10 @@ def get_meta_icon(self) -> Optional[str]:
376376
def get_launch_url(self, user: Optional["User"] = None) -> Optional[str]:
377377
"""Get launch URL if set, otherwise attempt to get launch URL based on provider."""
378378
url = None
379-
if provider := self.get_provider():
380-
url = provider.launch_url
381379
if self.meta_launch_url:
382380
url = self.meta_launch_url
381+
elif provider := self.get_provider():
382+
url = provider.launch_url
383383
if user and url:
384384
if isinstance(user, SimpleLazyObject):
385385
user._setup()

authentik/providers/ldap/api.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ class Meta:
105105
class LDAPOutpostConfigViewSet(ReadOnlyModelViewSet):
106106
"""LDAPProvider Viewset"""
107107

108-
queryset = LDAPProvider.objects.filter(application__isnull=False)
108+
queryset = LDAPProvider.objects.filter(
109+
Q(application__isnull=False) | Q(backchannel_application__isnull=False)
110+
)
109111
serializer_class = LDAPOutpostConfigSerializer
110112
ordering = ["name"]
111113
search_fields = ["name"]

authentik/providers/ldap/tests/__init__.py

Whitespace-only changes.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"""LDAP Provider API tests"""
2+
from json import loads
3+
4+
from django.urls import reverse
5+
from rest_framework.test import APITestCase
6+
7+
from authentik.core.models import Application
8+
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
9+
from authentik.lib.generators import generate_id
10+
from authentik.providers.ldap.models import LDAPProvider
11+
12+
13+
class TestLDAPProviderAPI(APITestCase):
14+
"""LDAP Provider API tests"""
15+
16+
def test_outpost_application(self):
17+
"""Test outpost-like provider retrieval (direct connection)"""
18+
provider = LDAPProvider.objects.create(
19+
name=generate_id(),
20+
authorization_flow=create_test_flow(),
21+
)
22+
Application.objects.create(
23+
name=generate_id(),
24+
slug=generate_id(),
25+
provider=provider,
26+
)
27+
user = create_test_admin_user()
28+
self.client.force_login(user)
29+
res = self.client.get(reverse("authentik_api:ldapprovideroutpost-list"))
30+
self.assertEqual(res.status_code, 200)
31+
data = loads(res.content.decode())
32+
self.assertEqual(data["pagination"]["count"], 1)
33+
self.assertEqual(len(data["results"]), 1)
34+
35+
def test_outpost_application_backchannel(self):
36+
"""Test outpost-like provider retrieval (backchannel connection)"""
37+
provider = LDAPProvider.objects.create(
38+
name=generate_id(),
39+
authorization_flow=create_test_flow(),
40+
)
41+
app: Application = Application.objects.create(
42+
name=generate_id(),
43+
slug=generate_id(),
44+
)
45+
app.backchannel_providers.add(provider)
46+
user = create_test_admin_user()
47+
self.client.force_login(user)
48+
res = self.client.get(reverse("authentik_api:ldapprovideroutpost-list"))
49+
self.assertEqual(res.status_code, 200)
50+
data = loads(res.content.decode())
51+
self.assertEqual(data["pagination"]["count"], 1)
52+
self.assertEqual(len(data["results"]), 1)

authentik/providers/ldap/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
from authentik.providers.ldap.api import LDAPOutpostConfigViewSet, LDAPProviderViewSet
33

44
api_urlpatterns = [
5-
("outposts/ldap", LDAPOutpostConfigViewSet),
5+
("outposts/ldap", LDAPOutpostConfigViewSet, "ldapprovideroutpost"),
66
("providers/ldap", LDAPProviderViewSet),
77
]

authentik/providers/oauth2/models.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from django.utils.translation import gettext_lazy as _
1818
from jwt import encode
1919
from rest_framework.serializers import Serializer
20+
from structlog.stdlib import get_logger
2021

2122
from authentik.core.models import ExpiringModel, PropertyMapping, Provider, User
2223
from authentik.crypto.models import CertificateKeyPair
@@ -26,6 +27,8 @@
2627
from authentik.providers.oauth2.id_token import IDToken, SubModes
2728
from authentik.sources.oauth.models import OAuthSource
2829

30+
LOGGER = get_logger()
31+
2932

3033
def generate_client_secret() -> str:
3134
"""Generate client secret with adequate length"""
@@ -251,8 +254,12 @@ def launch_url(self) -> Optional[str]:
251254
if self.redirect_uris == "":
252255
return None
253256
main_url = self.redirect_uris.split("\n", maxsplit=1)[0]
254-
launch_url = urlparse(main_url)._replace(path="")
255-
return urlunparse(launch_url)
257+
try:
258+
launch_url = urlparse(main_url)._replace(path="")
259+
return urlunparse(launch_url)
260+
except ValueError as exc:
261+
LOGGER.warning("Failed to format launch url", exc=exc)
262+
return None
256263

257264
@property
258265
def component(self) -> str:

authentik/providers/oauth2/tests/test_api.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Test OAuth2 API"""
22
from json import loads
3+
from sys import version_info
4+
from unittest import skipUnless
35

46
from django.urls import reverse
57
from rest_framework.test import APITestCase
@@ -42,3 +44,14 @@ def test_setup_urls(self):
4244
self.assertEqual(response.status_code, 200)
4345
body = loads(response.content.decode())
4446
self.assertEqual(body["issuer"], "http://testserver/application/o/test/")
47+
48+
# https://github.com/goauthentik/authentik/pull/5918
49+
@skipUnless(version_info >= (3, 11, 4), "This behaviour is only Python 3.11.4 and up")
50+
def test_launch_url(self):
51+
"""Test launch_url"""
52+
self.provider.redirect_uris = (
53+
"https://[\\d\\w]+.pr.test.goauthentik.io/source/oauth/callback/authentik/\n"
54+
)
55+
self.provider.save()
56+
self.provider.refresh_from_db()
57+
self.assertIsNone(self.provider.launch_url)

authentik/providers/proxy/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
from authentik.providers.proxy.api import ProxyOutpostConfigViewSet, ProxyProviderViewSet
33

44
api_urlpatterns = [
5-
("outposts/proxy", ProxyOutpostConfigViewSet),
5+
("outposts/proxy", ProxyOutpostConfigViewSet, "proxyprovideroutpost"),
66
("providers/proxy", ProxyProviderViewSet),
77
]

authentik/providers/radius/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
from authentik.providers.radius.api import RadiusOutpostConfigViewSet, RadiusProviderViewSet
33

44
api_urlpatterns = [
5-
("outposts/radius", RadiusOutpostConfigViewSet),
5+
("outposts/radius", RadiusOutpostConfigViewSet, "radiusprovideroutpost"),
66
("providers/radius", RadiusProviderViewSet),
77
]

0 commit comments

Comments
 (0)