add initial
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
parent
0156249123
commit
f28b18805f
|
@ -42,6 +42,7 @@ class ProviderSerializer(ModelSerializer, MetaNameSerializer):
|
|||
"name",
|
||||
"authentication_flow",
|
||||
"authorization_flow",
|
||||
"invalidation_flow",
|
||||
"property_mappings",
|
||||
"component",
|
||||
"assigned_application_slug",
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# Generated by Django 4.1.7 on 2023-03-22 22:26
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("authentik_flows", "0025_alter_flowstagebinding_evaluate_on_plan_and_more"),
|
||||
("authentik_core", "0027_alter_user_uuid"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="provider",
|
||||
name="invalidation_flow",
|
||||
field=models.ForeignKey(
|
||||
default=None,
|
||||
help_text="Flow used ending the session from a provider.",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_DEFAULT,
|
||||
related_name="provider_invalidation",
|
||||
to="authentik_flows.flow",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -299,11 +299,21 @@ class Provider(SerializerModel):
|
|||
|
||||
authorization_flow = models.ForeignKey(
|
||||
"authentik_flows.Flow",
|
||||
# Set to cascade even though null is allowed, since most providers
|
||||
# still require an authorization flow set
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
help_text=_("Flow used when authorizing this provider."),
|
||||
related_name="provider_authorization",
|
||||
)
|
||||
invalidation_flow = models.ForeignKey(
|
||||
"authentik_flows.Flow",
|
||||
on_delete=models.SET_DEFAULT,
|
||||
default=None,
|
||||
null=True,
|
||||
help_text=_("Flow used ending the session from a provider."),
|
||||
related_name="provider_invalidation",
|
||||
)
|
||||
|
||||
property_mappings = models.ManyToManyField("PropertyMapping", default=None, blank=True)
|
||||
|
||||
|
|
|
@ -125,6 +125,12 @@ class AccessDeniedChallenge(WithUserInfoChallenge):
|
|||
component = CharField(default="ak-stage-access-denied")
|
||||
|
||||
|
||||
class SessionEndChallenge(WithUserInfoChallenge):
|
||||
"""Challenge for ending a session"""
|
||||
|
||||
component = CharField(default="ak-stage-session-end")
|
||||
|
||||
|
||||
class PermissionDict(TypedDict):
|
||||
"""Consent Permission"""
|
||||
|
||||
|
|
|
@ -105,7 +105,9 @@ class Stage(SerializerModel):
|
|||
|
||||
|
||||
def in_memory_stage(view: type["StageView"], **kwargs) -> Stage:
|
||||
"""Creates an in-memory stage instance, based on a `view` as view."""
|
||||
"""Creates an in-memory stage instance, based on a `view` as view.
|
||||
Any key-word arguments are set as attributes on the stage object,
|
||||
accessible via `self.executor.current_stage`."""
|
||||
stage = Stage()
|
||||
# Because we can't pickle a locally generated function,
|
||||
# we set the view as a separate property and reference a generic function
|
||||
|
|
|
@ -11,6 +11,7 @@ from authentik.providers.oauth2.api.tokens import (
|
|||
)
|
||||
from authentik.providers.oauth2.views.authorize import AuthorizationFlowInitView
|
||||
from authentik.providers.oauth2.views.device_backchannel import DeviceView
|
||||
from authentik.providers.oauth2.views.end_session import EndSessionView
|
||||
from authentik.providers.oauth2.views.introspection import TokenIntrospectionView
|
||||
from authentik.providers.oauth2.views.jwks import JWKSView
|
||||
from authentik.providers.oauth2.views.provider import ProviderInfoView
|
||||
|
@ -43,7 +44,7 @@ urlpatterns = [
|
|||
),
|
||||
path(
|
||||
"<slug:application_slug>/end-session/",
|
||||
RedirectView.as_view(pattern_name="authentik_core:if-session-end", query_string=True),
|
||||
EndSessionView.as_view(),
|
||||
name="end-session",
|
||||
),
|
||||
path("<slug:application_slug>/jwks/", JWKSView.as_view(), name="jwks"),
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
"""oauth2 provider end_session Views"""
|
||||
from django.http import Http404, HttpRequest, HttpResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from authentik.core.models import Application
|
||||
from authentik.flows.challenge import SessionEndChallenge
|
||||
from authentik.flows.models import in_memory_stage
|
||||
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner
|
||||
from authentik.flows.views.executor import SESSION_KEY_PLAN
|
||||
from authentik.lib.utils.urls import redirect_with_qs
|
||||
from authentik.policies.views import PolicyAccessView
|
||||
|
||||
|
||||
class EndSessionView(PolicyAccessView):
|
||||
"""Redirect to application's provider's invalidation flow"""
|
||||
|
||||
def resolve_provider_application(self):
|
||||
self.application = get_object_or_404(Application, slug=self.kwargs["application_slug"])
|
||||
self.provider = self.application.get_provider()
|
||||
if not self.provider or not self.provider.invalidation_flow:
|
||||
raise Http404
|
||||
|
||||
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||
"""Dispatch the flow planner for the invalidation flow"""
|
||||
planner = FlowPlanner(self.provider.invalidation_flow)
|
||||
planner.allow_empty_flows = True
|
||||
plan = planner.plan(
|
||||
request,
|
||||
{
|
||||
PLAN_CONTEXT_APPLICATION: self.application,
|
||||
},
|
||||
)
|
||||
plan.insert_stage(in_memory_stage(SessionEndChallenge))
|
||||
request.session[SESSION_KEY_PLAN] = plan
|
||||
return redirect_with_qs(
|
||||
"authentik_core:if-flow",
|
||||
self.request.GET,
|
||||
flow_slug=self.provider.invalidation_flow.slug,
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
version: 1
|
||||
metadata:
|
||||
name: Default - Provider invalidation flow
|
||||
entries:
|
||||
- attrs:
|
||||
designation: invalidation
|
||||
name: Logout
|
||||
title: You've logged out of %(app)s.
|
||||
authentication: none
|
||||
identifiers:
|
||||
slug: default-provider-invalidation-flow
|
||||
model: authentik_flows.flow
|
||||
id: flow
|
117
schema.yml
117
schema.yml
|
@ -16394,6 +16394,11 @@ paths:
|
|||
name: is_backchannel
|
||||
schema:
|
||||
type: boolean
|
||||
- in: query
|
||||
name: invalidation_flow
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- in: query
|
||||
name: issuer
|
||||
schema:
|
||||
|
@ -29557,6 +29562,7 @@ components:
|
|||
- $ref: '#/components/schemas/PlexAuthenticationChallenge'
|
||||
- $ref: '#/components/schemas/PromptChallenge'
|
||||
- $ref: '#/components/schemas/RedirectChallenge'
|
||||
- $ref: '#/components/schemas/SessionEndChallenge'
|
||||
- $ref: '#/components/schemas/ShellChallenge'
|
||||
- $ref: '#/components/schemas/UserLoginChallenge'
|
||||
discriminator:
|
||||
|
@ -29583,6 +29589,7 @@ components:
|
|||
ak-source-plex: '#/components/schemas/PlexAuthenticationChallenge'
|
||||
ak-stage-prompt: '#/components/schemas/PromptChallenge'
|
||||
xak-flow-redirect: '#/components/schemas/RedirectChallenge'
|
||||
ak-stage-session-end: '#/components/schemas/SessionEndChallenge'
|
||||
xak-flow-shell: '#/components/schemas/ShellChallenge'
|
||||
ak-stage-user-login: '#/components/schemas/UserLoginChallenge'
|
||||
ClientTypeEnum:
|
||||
|
@ -32592,6 +32599,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -32705,6 +32717,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -33627,6 +33644,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -33760,6 +33782,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -36728,6 +36755,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -36986,6 +37018,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -37478,6 +37515,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -37566,6 +37608,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -37657,6 +37704,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -38984,6 +39036,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -39074,6 +39131,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -39242,6 +39304,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -39386,6 +39453,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -39515,6 +39587,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -39602,6 +39679,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -39944,6 +40026,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -40118,6 +40205,11 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Flow used when authorizing this provider.
|
||||
invalidation_flow:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
description: Flow used ending the session from a provider.
|
||||
property_mappings:
|
||||
type: array
|
||||
items:
|
||||
|
@ -40814,6 +40906,31 @@ components:
|
|||
required:
|
||||
- healthy
|
||||
- version
|
||||
SessionEndChallenge:
|
||||
type: object
|
||||
description: Challenge for ending a session
|
||||
properties:
|
||||
type:
|
||||
$ref: '#/components/schemas/ChallengeChoices'
|
||||
flow_info:
|
||||
$ref: '#/components/schemas/ContextualFlowInfo'
|
||||
component:
|
||||
type: string
|
||||
default: ak-stage-session-end
|
||||
response_errors:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ErrorDetail'
|
||||
pending_user:
|
||||
type: string
|
||||
pending_user_avatar:
|
||||
type: string
|
||||
required:
|
||||
- pending_user
|
||||
- pending_user_avatar
|
||||
- type
|
||||
SessionUser:
|
||||
type: object
|
||||
description: |-
|
||||
|
|
|
@ -193,6 +193,41 @@ export class OAuth2ProviderFormPage extends BaseProviderForm<OAuth2Provider> {
|
|||
${msg("Flow used when authorizing this provider.")}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Invalidation flow`}
|
||||
?required=${true}
|
||||
name="invalidationFlow"
|
||||
>
|
||||
<ak-search-select
|
||||
.fetchObjects=${async (query?: string): Promise<Flow[]> => {
|
||||
const args: FlowsInstancesListRequest = {
|
||||
ordering: "slug",
|
||||
designation: FlowsInstancesListDesignationEnum.Invalidation,
|
||||
};
|
||||
if (query !== undefined) {
|
||||
args.search = query;
|
||||
}
|
||||
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList(args);
|
||||
return flows.results;
|
||||
}}
|
||||
.renderElement=${(flow: Flow): string => {
|
||||
return RenderFlowOption(flow);
|
||||
}}
|
||||
.renderDescription=${(flow: Flow): TemplateResult => {
|
||||
return html`${flow.name}`;
|
||||
}}
|
||||
.value=${(flow: Flow | undefined): string | undefined => {
|
||||
return flow?.pk;
|
||||
}}
|
||||
.selected=${(flow: Flow): boolean => {
|
||||
return flow.pk === this.instance?.invalidationFlow;
|
||||
}}
|
||||
>
|
||||
</ak-search-select>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${t`Flow used when authorizing this provider.`}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
|
||||
<ak-form-group .expanded=${true}>
|
||||
<span slot="header"> ${msg("Protocol settings")} </span>
|
||||
|
|
Reference in New Issue