sources/*: rewrite UILoginButton to return challenge instead
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
f1b100c8a5
commit
55250e88e5
|
@ -1,10 +1,11 @@
|
||||||
"""authentik core dataclasses"""
|
"""authentik core dataclasses"""
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, Optional
|
from typing import Optional
|
||||||
|
|
||||||
from rest_framework.fields import CharField, DictField
|
from rest_framework.fields import CharField, DictField
|
||||||
|
|
||||||
from authentik.core.api.utils import PassiveSerializer
|
from authentik.core.api.utils import PassiveSerializer
|
||||||
|
from authentik.flows.challenge import Challenge
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -14,23 +15,19 @@ class UILoginButton:
|
||||||
# Name, ran through i18n
|
# Name, ran through i18n
|
||||||
name: str
|
name: str
|
||||||
|
|
||||||
# URL Which Button points to
|
# Challenge which is presented to the user when they click the button
|
||||||
url: str
|
challenge: Challenge
|
||||||
|
|
||||||
# Icon URL, used as-is
|
# Icon URL, used as-is
|
||||||
icon_url: Optional[str] = None
|
icon_url: Optional[str] = None
|
||||||
|
|
||||||
# Additional data, optional
|
|
||||||
additional_data: Any = None
|
|
||||||
|
|
||||||
|
|
||||||
class UILoginButtonSerializer(PassiveSerializer):
|
class UILoginButtonSerializer(PassiveSerializer):
|
||||||
"""Serializer for Login buttons of sources"""
|
"""Serializer for Login buttons of sources"""
|
||||||
|
|
||||||
name = CharField()
|
name = CharField()
|
||||||
url = CharField()
|
challenge = DictField()
|
||||||
icon_url = CharField(required=False, allow_null=True)
|
icon_url = CharField(required=False, allow_null=True)
|
||||||
additional_data = DictField(required=False, allow_null=True)
|
|
||||||
|
|
||||||
|
|
||||||
class UserSettingSerializer(PassiveSerializer):
|
class UserSettingSerializer(PassiveSerializer):
|
||||||
|
|
|
@ -9,6 +9,7 @@ from rest_framework.serializers import Serializer
|
||||||
|
|
||||||
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 ChallengeTypes, RedirectChallenge
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from authentik.sources.oauth.types.manager import SourceType
|
from authentik.sources.oauth.types.manager import SourceType
|
||||||
|
@ -67,9 +68,14 @@ class OAuthSource(Source):
|
||||||
@property
|
@property
|
||||||
def ui_login_button(self) -> UILoginButton:
|
def ui_login_button(self) -> UILoginButton:
|
||||||
return UILoginButton(
|
return UILoginButton(
|
||||||
url=reverse(
|
challenge=RedirectChallenge(
|
||||||
"authentik_sources_oauth:oauth-client-login",
|
instance={
|
||||||
kwargs={"source_slug": self.slug},
|
"type": ChallengeTypes.REDIRECT.value,
|
||||||
|
"to": reverse(
|
||||||
|
"authentik_sources_oauth:oauth-client-login",
|
||||||
|
kwargs={"source_slug": self.slug},
|
||||||
|
),
|
||||||
|
}
|
||||||
),
|
),
|
||||||
icon_url=static(f"authentik/sources/{self.provider_type}.svg"),
|
icon_url=static(f"authentik/sources/{self.provider_type}.svg"),
|
||||||
name=self.name,
|
name=self.name,
|
||||||
|
|
|
@ -10,6 +10,7 @@ from rest_framework.serializers import Serializer
|
||||||
from authentik.core.models import Source
|
from authentik.core.models import Source
|
||||||
from authentik.core.types import UILoginButton
|
from authentik.core.types import UILoginButton
|
||||||
from authentik.crypto.models import CertificateKeyPair
|
from authentik.crypto.models import CertificateKeyPair
|
||||||
|
from authentik.flows.challenge import ChallengeTypes, RedirectChallenge
|
||||||
from authentik.flows.models import Flow
|
from authentik.flows.models import Flow
|
||||||
from authentik.lib.utils.time import timedelta_string_validator
|
from authentik.lib.utils.time import timedelta_string_validator
|
||||||
from authentik.sources.saml.processors.constants import (
|
from authentik.sources.saml.processors.constants import (
|
||||||
|
@ -169,10 +170,16 @@ class SAMLSource(Source):
|
||||||
@property
|
@property
|
||||||
def ui_login_button(self) -> UILoginButton:
|
def ui_login_button(self) -> UILoginButton:
|
||||||
return UILoginButton(
|
return UILoginButton(
|
||||||
name=self.name,
|
challenge=RedirectChallenge(
|
||||||
url=reverse(
|
instance={
|
||||||
"authentik_sources_saml:login", kwargs={"source_slug": self.slug}
|
"type": ChallengeTypes.REDIRECT.value,
|
||||||
|
"to": reverse(
|
||||||
|
"authentik_sources_saml:login",
|
||||||
|
kwargs={"source_slug": self.slug},
|
||||||
|
),
|
||||||
|
}
|
||||||
),
|
),
|
||||||
|
name=self.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
@ -112,7 +112,9 @@ class IdentificationStageView(ChallengeStageView):
|
||||||
for source in sources:
|
for source in sources:
|
||||||
ui_login_button = source.ui_login_button
|
ui_login_button = source.ui_login_button
|
||||||
if ui_login_button:
|
if ui_login_button:
|
||||||
ui_sources.append(asdict(ui_login_button))
|
button = asdict(ui_login_button)
|
||||||
|
button["challenge"] = ui_login_button.challenge.data
|
||||||
|
ui_sources.append(button)
|
||||||
challenge.initial_data["sources"] = ui_sources
|
challenge.initial_data["sources"] = ui_sources
|
||||||
return challenge
|
return challenge
|
||||||
|
|
||||||
|
|
|
@ -115,10 +115,12 @@ class TestIdentificationStage(TestCase):
|
||||||
"title": self.flow.title,
|
"title": self.flow.title,
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"additional_data": None,
|
|
||||||
"icon_url": "/static/authentik/sources/.svg",
|
"icon_url": "/static/authentik/sources/.svg",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"url": "/source/oauth/login/test/",
|
"challenge": {
|
||||||
|
"to": "/source/oauth/login/test/",
|
||||||
|
"type": "redirect",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -159,10 +161,12 @@ class TestIdentificationStage(TestCase):
|
||||||
"title": self.flow.title,
|
"title": self.flow.title,
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"additional_data": None,
|
"challenge": {
|
||||||
|
"to": "/source/oauth/login/test/",
|
||||||
|
"type": "redirect",
|
||||||
|
},
|
||||||
"icon_url": "/static/authentik/sources/.svg",
|
"icon_url": "/static/authentik/sources/.svg",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"url": "/source/oauth/login/test/",
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -272,7 +272,7 @@ body {
|
||||||
.pf-c-login__main-header-desc {
|
.pf-c-login__main-header-desc {
|
||||||
color: var(--ak-dark-foreground);
|
color: var(--ak-dark-foreground);
|
||||||
}
|
}
|
||||||
.pf-c-login__main-footer-links-item-link > img {
|
.pf-c-login__main-footer-links-item img {
|
||||||
filter: invert(1);
|
filter: invert(1);
|
||||||
}
|
}
|
||||||
.pf-c-login__main-footer-band {
|
.pf-c-login__main-footer-band {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
import { Challenge } from "authentik-api";
|
||||||
import { LitElement } from "lit-element";
|
import { LitElement } from "lit-element";
|
||||||
|
|
||||||
export interface StageHost {
|
export interface StageHost {
|
||||||
|
challenge?: Challenge;
|
||||||
submit<T>(formData?: T): Promise<void>;
|
submit<T>(formData?: T): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ export interface IdentificationChallenge extends Challenge {
|
||||||
|
|
||||||
export interface UILoginButton {
|
export interface UILoginButton {
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
challenge: Challenge;
|
||||||
icon_url?: string;
|
icon_url?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,11 @@ export class IdentificationStage extends BaseStage {
|
||||||
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton, AKGlobal].concat(
|
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton, AKGlobal].concat(
|
||||||
css`
|
css`
|
||||||
/* login page's icons */
|
/* login page's icons */
|
||||||
.pf-c-login__main-footer-links-item-link img {
|
.pf-c-login__main-footer-links-item button {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
.pf-c-login__main-footer-links-item img {
|
||||||
fill: var(--pf-c-login__main-footer-links-item-link-svg--Fill);
|
fill: var(--pf-c-login__main-footer-links-item-link-svg--Fill);
|
||||||
width: 100px;
|
width: 100px;
|
||||||
max-width: var(--pf-c-login__main-footer-links-item-link-svg--Width);
|
max-width: var(--pf-c-login__main-footer-links-item-link-svg--Width);
|
||||||
|
@ -131,9 +135,12 @@ export class IdentificationStage extends BaseStage {
|
||||||
icon = html`<img src="${source.icon_url}" alt="${source.name}">`;
|
icon = html`<img src="${source.icon_url}" alt="${source.name}">`;
|
||||||
}
|
}
|
||||||
return html`<li class="pf-c-login__main-footer-links-item">
|
return html`<li class="pf-c-login__main-footer-links-item">
|
||||||
<a href="${source.url}" class="pf-c-login__main-footer-links-item-link">
|
<button type="button" @click=${() => {
|
||||||
|
if (!this.host) return;
|
||||||
|
this.host.challenge = source.challenge;
|
||||||
|
}}>
|
||||||
${icon}
|
${icon}
|
||||||
</a>
|
</button>
|
||||||
</li>`;
|
</li>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue