From c637489b06a1ee45063f1a09cc7f67b363d98082 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Fri, 24 Mar 2023 14:40:36 +0100 Subject: [PATCH] add invalidation_flow to saml importer Signed-off-by: Jens Langhammer --- authentik/core/models.py | 1 - authentik/providers/saml/api/providers.py | 7 +- .../saml/processors/metadata_parser.py | 3 +- blueprints/schema.json | 40 +++++ schema.yml | 12 +- .../providers/oauth2/OAuth2ProviderForm.ts | 158 ++++-------------- .../providers/proxy/ProxyProviderForm.ts | 84 ++++++---- .../admin/providers/saml/SAMLProviderForm.ts | 124 ++++---------- .../providers/saml/SAMLProviderImportForm.ts | 33 ++++ 9 files changed, 208 insertions(+), 254 deletions(-) diff --git a/authentik/core/models.py b/authentik/core/models.py index 06ab7d1cd..c6ff8064f 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -296,7 +296,6 @@ class Provider(SerializerModel): ), related_name="provider_authentication", ) - authorization_flow = models.ForeignKey( "authentik_flows.Flow", # Set to cascade even though null is allowed, since most providers diff --git a/authentik/providers/saml/api/providers.py b/authentik/providers/saml/api/providers.py index 226ec7e58..a2d5a785c 100644 --- a/authentik/providers/saml/api/providers.py +++ b/authentik/providers/saml/api/providers.py @@ -171,6 +171,9 @@ class SAMLProviderImportSerializer(PassiveSerializer): authorization_flow = PrimaryKeyRelatedField( queryset=Flow.objects.filter(designation=FlowDesignation.AUTHORIZATION), ) + invalidation_flow = PrimaryKeyRelatedField( + queryset=Flow.objects.filter(designation=FlowDesignation.INVALIDATION), + ) file = FileField() @@ -260,7 +263,9 @@ class SAMLProviderViewSet(UsedByMixin, ModelViewSet): try: metadata = ServiceProviderMetadataParser().parse(file.read().decode()) metadata.to_provider( - data.validated_data["name"], data.validated_data["authorization_flow"] + data.validated_data["name"], + data.validated_data["authorization_flow"], + data.validated_data["invalidation_flow"], ) except ValueError as exc: # pragma: no cover LOGGER.warning(str(exc)) diff --git a/authentik/providers/saml/processors/metadata_parser.py b/authentik/providers/saml/processors/metadata_parser.py index db284ee22..66cbd5529 100644 --- a/authentik/providers/saml/processors/metadata_parser.py +++ b/authentik/providers/saml/processors/metadata_parser.py @@ -49,12 +49,13 @@ class ServiceProviderMetadata: signing_keypair: Optional[CertificateKeyPair] = None - def to_provider(self, name: str, authorization_flow: Flow) -> SAMLProvider: + def to_provider(self, name: str, authorization_flow: Flow, invalidation_flow: Flow) -> SAMLProvider: """Create a SAMLProvider instance from the details. `name` is required, as depending on the metadata CertificateKeypairs might have to be created.""" provider = SAMLProvider.objects.create( name=name, authorization_flow=authorization_flow, + invalidation_flow=invalidation_flow ) provider.issuer = self.entity_id provider.sp_binding = self.acs_binding diff --git a/blueprints/schema.json b/blueprints/schema.json index 423094b60..a764a3b44 100644 --- a/blueprints/schema.json +++ b/blueprints/schema.json @@ -3831,6 +3831,11 @@ "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, + "invalidation_flow": { + "type": "integer", + "title": "Invalidation flow", + "description": "Flow used ending the session from a provider." + }, "property_mappings": { "type": "array", "items": { @@ -3949,6 +3954,11 @@ "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, + "invalidation_flow": { + "type": "integer", + "title": "Invalidation flow", + "description": "Flow used ending the session from a provider." + }, "property_mappings": { "type": "array", "items": { @@ -4063,6 +4073,11 @@ "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, + "invalidation_flow": { + "type": "integer", + "title": "Invalidation flow", + "description": "Flow used ending the session from a provider." + }, "property_mappings": { "type": "array", "items": { @@ -4264,6 +4279,11 @@ "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, + "invalidation_flow": { + "type": "integer", + "title": "Invalidation flow", + "description": "Flow used ending the session from a provider." + }, "property_mappings": { "type": "array", "items": { @@ -4469,6 +4489,11 @@ "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, + "invalidation_flow": { + "type": "integer", + "title": "Invalidation flow", + "description": "Flow used ending the session from a provider." + }, "property_mappings": { "type": "array", "items": { @@ -4671,6 +4696,11 @@ "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, + "invalidation_flow": { + "type": "integer", + "title": "Invalidation flow", + "description": "Flow used ending the session from a provider." + }, "property_mappings": { "type": "array", "items": { @@ -4776,6 +4806,11 @@ "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, + "invalidation_flow": { + "type": "integer", + "title": "Invalidation flow", + "description": "Flow used ending the session from a provider." + }, "property_mappings": { "type": "array", "items": { @@ -4821,6 +4856,11 @@ "title": "Authorization flow", "description": "Flow used when authorizing this provider." }, + "invalidation_flow": { + "type": "integer", + "title": "Invalidation flow", + "description": "Flow used ending the session from a provider." + }, "property_mappings": { "type": "array", "items": { diff --git a/schema.yml b/schema.yml index af808d704..1b4a50ac5 100644 --- a/schema.yml +++ b/schema.yml @@ -16390,15 +16390,15 @@ paths: * `http://www.w3.org/2001/04/xmlenc#sha256` - SHA256 * `http://www.w3.org/2001/04/xmldsig-more#sha384` - SHA384 * `http://www.w3.org/2001/04/xmlenc#sha512` - SHA512 - - in: query - name: is_backchannel - schema: - type: boolean - in: query name: invalidation_flow schema: type: string format: uuid + - in: query + name: is_backchannel + schema: + type: boolean - in: query name: issuer schema: @@ -40181,12 +40181,16 @@ components: authorization_flow: type: string format: uuid + invalidation_flow: + type: string + format: uuid file: type: string format: binary required: - authorization_flow - file + - invalidation_flow - name SAMLProviderRequest: type: object diff --git a/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts b/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts index 1b66b07b7..6b564b079 100644 --- a/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts +++ b/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts @@ -166,69 +166,6 @@ export class OAuth2ProviderFormPage extends BaseProviderForm { required > - - -

- ${msg("Flow used when a user access this provider and is not authenticated.")} -

-
- - -

- ${msg("Flow used when authorizing this provider.")} -

-
- - => { - 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; - }} - > - -

- ${t`Flow used when authorizing this provider.`} -

-
- ${msg("Protocol settings")}
@@ -283,80 +220,49 @@ export class OAuth2ProviderFormPage extends BaseProviderForm { - ${t`Flow settings`} + ${msg("Flow settings")}
- => { - const args: FlowsInstancesListRequest = { - ordering: "slug", - designation: FlowsInstancesListDesignationEnum.Authorization, - }; - 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?.authorizationFlow; - }} - > - +

- ${t`Flow used when authorizing this provider.`} + ${msg( + "Flow used when a user access this provider and is not authenticated.", + )}

+ +

+ ${msg("Flow used when authorizing this provider.")} +

+
+ - => { - 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; - }} - > - +

- ${t`Flow used when authorizing this provider.`} + ${msg("Flow used when logging out of this provider.")}

diff --git a/web/src/admin/providers/proxy/ProxyProviderForm.ts b/web/src/admin/providers/proxy/ProxyProviderForm.ts index ddd554572..65e0fada4 100644 --- a/web/src/admin/providers/proxy/ProxyProviderForm.ts +++ b/web/src/admin/providers/proxy/ProxyProviderForm.ts @@ -258,7 +258,8 @@ export class ProxyProviderFormPage extends BaseProviderForm { } renderForm(): TemplateResult { - return html` + return html` + { required /> - - -

- ${msg("Flow used when a user access this provider and is not authenticated.")} -

-
- - -

- ${msg("Flow used when authorizing this provider.")} -

-
${this.renderModeSelector()}
@@ -448,6 +421,57 @@ ${this.instance?.skipPathRegex}
-
`; + + + + ${msg("Flow settings")} +
+ + +

+ ${msg( + "Flow used when a user access this provider and is not authenticated.", + )} +

+
+ + +

+ ${msg("Flow used when authorizing this provider.")} +

+
+ + +

+ ${msg("Flow used when logging out of this provider.")} +

+
+
+
+ `; } } diff --git a/web/src/admin/providers/saml/SAMLProviderForm.ts b/web/src/admin/providers/saml/SAMLProviderForm.ts index e579ff573..b90f7bc2a 100644 --- a/web/src/admin/providers/saml/SAMLProviderForm.ts +++ b/web/src/admin/providers/saml/SAMLProviderForm.ts @@ -66,34 +66,6 @@ export class SAMLProviderFormPage extends BaseProviderForm { required /> - - -

- ${msg("Flow used when a user access this provider and is not authenticated.")} -

-
- - -

- ${msg("Flow used when authorizing this provider.")} -

-
${msg("Protocol settings")} @@ -160,80 +132,50 @@ export class SAMLProviderFormPage extends BaseProviderForm { - ${t`Flow settings`} + ${msg("Flow settings")}
- => { - const args: FlowsInstancesListRequest = { - ordering: "slug", - designation: FlowsInstancesListDesignationEnum.Authorization, - }; - 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?.authorizationFlow; - }} - > - +

- ${t`Flow used when authorizing this provider.`} + ${msg( + "Flow used when a user access this provider and is not authenticated.", + )}

+ +

+ ${msg("Flow used when authorizing this provider.")} +

+
+ - => { - 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; - }} - > - +

- ${t`Flow used when authorizing this provider.`} + ${msg("Flow used when logging out of this provider.")}

diff --git a/web/src/admin/providers/saml/SAMLProviderImportForm.ts b/web/src/admin/providers/saml/SAMLProviderImportForm.ts index b63c1512b..47f8947ee 100644 --- a/web/src/admin/providers/saml/SAMLProviderImportForm.ts +++ b/web/src/admin/providers/saml/SAMLProviderImportForm.ts @@ -26,6 +26,7 @@ export class SAMLProviderImportForm extends Form { file: file, name: data.name, authorizationFlow: data.authorizationFlow || "", + invalidationFlow: data.invalidationFlow || "", }); } @@ -46,6 +47,38 @@ export class SAMLProviderImportForm extends Form { ${msg("Flow used when authorizing this provider.")}

+ + => { + 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; + }} + > + +

+ ${t`Flow used when logging out of this provider.`} +

+