sources/oauth: ensure all UI sources return a valid source (#9401)

* web/admin: prevent selection of inbuilt source in identification stage

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix apple source

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* also fix plex challenge

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L
2024-04-24 22:55:19 +02:00
committed by GitHub
parent 64ce170882
commit 80af26ef50
6 changed files with 63 additions and 24 deletions

View File

@ -0,0 +1,37 @@
"""Apple Type tests"""
from django.test import RequestFactory, TestCase
from guardian.shortcuts import get_anonymous_user
from authentik.lib.generators import generate_id
from authentik.lib.tests.utils import dummy_get_response
from authentik.root.middleware import SessionMiddleware
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.registry import registry
class TestTypeApple(TestCase):
"""OAuth Source tests"""
def setUp(self):
self.source = OAuthSource.objects.create(
name="test",
slug="test",
provider_type="apple",
authorization_url="",
profile_url="",
consumer_key=generate_id(),
)
self.factory = RequestFactory()
def test_login_challenge(self):
"""Test login_challenge"""
request = self.factory.get("/")
request.user = get_anonymous_user()
middleware = SessionMiddleware(dummy_get_response)
middleware.process_request(request)
request.session.save()
oauth_type = registry.find_type("apple")
challenge = oauth_type().login_challenge(self.source, request)
self.assertTrue(challenge.is_valid(raise_exception=True))

View File

@ -125,7 +125,7 @@ class AppleType(SourceType):
)
args = apple_client.get_redirect_args()
return AppleLoginChallenge(
instance={
data={
"client_id": apple_client.get_client_id(),
"scope": "name email",
"redirect_uri": args["redirect_uri"],

View File

@ -66,7 +66,7 @@ class PlexSource(Source):
icon = static("authentik/sources/plex.svg")
return UILoginButton(
challenge=PlexAuthenticationChallenge(
{
data={
"type": ChallengeTypes.NATIVE.value,
"component": "ak-source-plex",
"client_id": self.client_id,

View File

@ -40,6 +40,11 @@ class TestPlexSource(TestCase):
slug="test",
)
def test_login_challenge(self):
"""Test login_challenge"""
ui_login_button = self.source.ui_login_button(None)
self.assertTrue(ui_login_button.challenge.is_valid(raise_exception=True))
def test_get_user_info(self):
"""Test get_user_info"""
token = generate_key()

View File

@ -237,6 +237,8 @@ class IdentificationStageView(ChallengeStageView):
)
for source in sources:
ui_login_button = source.ui_login_button(self.request)
if source.component == "":
continue
if ui_login_button:
button = asdict(ui_login_button)
source_challenge = ui_login_button.challenge

View File

@ -214,21 +214,16 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
name="sources"
>
<select class="pf-c-form-control" multiple>
${this.sources?.results.map((source) => {
let selected = Array.from(this.instance?.sources || []).some(
${this.sources?.results
.filter((source) => {
return source.component !== "";
})
.map((source) => {
const selected = Array.from(this.instance?.sources || []).some(
(su) => {
return su == source.pk;
},
);
// Creating a new instance, auto-select built-in source
// Only when no other sources exist
if (
!this.instance &&
source.component === "" &&
(this.sources?.results || []).length < 2
) {
selected = true;
}
return html`<option
value=${ifDefined(source.pk)}
?selected=${selected}