add invalidation_flow to saml importer

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer 2023-03-24 14:40:36 +01:00
parent 5dfda671eb
commit c637489b06
No known key found for this signature in database
9 changed files with 208 additions and 254 deletions

View file

@ -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

View file

@ -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))

View file

@ -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

View file

@ -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": {

View file

@ -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

View file

@ -166,69 +166,6 @@ export class OAuth2ProviderFormPage extends BaseProviderForm<OAuth2Provider> {
required
></ak-text-input>
<ak-form-element-horizontal
name="authenticationFlow"
label=${msg("Authentication flow")}
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authentication}
.currentFlow=${provider?.authenticationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg("Flow used when a user access this provider and is not authenticated.")}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
name="authorizationFlow"
label=${msg("Authorization flow")}
?required=${true}
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authorization}
.currentFlow=${provider?.authorizationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${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>
<div slot="body" class="pf-c-form">
@ -283,80 +220,49 @@ export class OAuth2ProviderFormPage extends BaseProviderForm<OAuth2Provider> {
</ak-form-group>
<ak-form-group .expanded=${true}>
<span slot="header"> ${t`Flow settings`} </span>
<span slot="header"> ${msg("Flow settings")} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`Authorization flow`}
?required=${true}
name="authorizationFlow"
name="authenticationFlow"
label=${msg("Authentication flow")}
>
<ak-search-select
.fetchObjects=${async (query?: string): Promise<Flow[]> => {
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;
}}
>
</ak-search-select>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authentication}
.currentFlow=${provider?.authenticationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${t`Flow used when authorizing this provider.`}
${msg(
"Flow used when a user access this provider and is not authenticated.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Invalidation flow`}
name="authorizationFlow"
label=${msg("Authorization flow")}
?required=${true}
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authorization}
.currentFlow=${provider?.authorizationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg("Flow used when authorizing this provider.")}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("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>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Invalidation}
.currentFlow=${provider?.invalidationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${t`Flow used when authorizing this provider.`}
${msg("Flow used when logging out of this provider.")}
</p>
</ak-form-element-horizontal>
</div>

View file

@ -258,7 +258,8 @@ export class ProxyProviderFormPage extends BaseProviderForm<ProxyProvider> {
}
renderForm(): TemplateResult {
return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
return html`
<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input
type="text"
value="${ifDefined(this.instance?.name)}"
@ -266,34 +267,6 @@ export class ProxyProviderFormPage extends BaseProviderForm<ProxyProvider> {
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Authentication flow")}
?required=${false}
name="authenticationFlow"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authentication}
.currentFlow=${this.instance?.authenticationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg("Flow used when a user access this provider and is not authenticated.")}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Authorization flow")}
?required=${true}
name="authorizationFlow"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authorization}
.currentFlow=${this.instance?.authorizationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg("Flow used when authorizing this provider.")}
</p>
</ak-form-element-horizontal>
<div class="pf-c-card pf-m-selectable pf-m-selected">
<div class="pf-c-card__body">${this.renderModeSelector()}</div>
@ -448,6 +421,57 @@ ${this.instance?.skipPathRegex}</textarea
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>`;
</ak-form-group>
<ak-form-group .expanded=${true}>
<span slot="header"> ${msg("Flow settings")} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${msg("Authentication flow")}
?required=${false}
name="authenticationFlow"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authentication}
.currentFlow=${this.instance?.authenticationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg(
"Flow used when a user access this provider and is not authenticated.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Authorization flow")}
?required=${true}
name="authorizationFlow"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authorization}
.currentFlow=${this.instance?.authorizationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg("Flow used when authorizing this provider.")}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Invalidation flow")}
?required=${true}
name="invalidationFlow"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Invalidation}
.currentFlow=${this.instance?.invalidationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg("Flow used when logging out of this provider.")}
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>
`;
}
}

View file

@ -66,34 +66,6 @@ export class SAMLProviderFormPage extends BaseProviderForm<SAMLProvider> {
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Authentication flow")}
?required=${false}
name="authenticationFlow"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authentication}
.currentFlow=${this.instance?.authenticationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg("Flow used when a user access this provider and is not authenticated.")}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Authorization flow")}
?required=${true}
name="authorizationFlow"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authorization}
.currentFlow=${this.instance?.authorizationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg("Flow used when authorizing this provider.")}
</p>
</ak-form-element-horizontal>
<ak-form-group .expanded=${true}>
<span slot="header"> ${msg("Protocol settings")} </span>
@ -160,80 +132,50 @@ export class SAMLProviderFormPage extends BaseProviderForm<SAMLProvider> {
</ak-form-group>
<ak-form-group .expanded=${true}>
<span slot="header"> ${t`Flow settings`} </span>
<span slot="header"> ${msg("Flow settings")} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`Authorization flow`}
?required=${true}
name="authorizationFlow"
label=${msg("Authentication flow")}
?required=${false}
name="authenticationFlow"
>
<ak-search-select
.fetchObjects=${async (query?: string): Promise<Flow[]> => {
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;
}}
>
</ak-search-select>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authentication}
.currentFlow=${this.instance?.authenticationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${t`Flow used when authorizing this provider.`}
${msg(
"Flow used when a user access this provider and is not authenticated.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Invalidation flow`}
label=${msg("Authorization flow")}
?required=${true}
name="authorizationFlow"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authorization}
.currentFlow=${this.instance?.authorizationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg("Flow used when authorizing this provider.")}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("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>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Invalidation}
.currentFlow=${this.instance?.invalidationFlow}
required
></ak-flow-search>
<p class="pf-c-form__helper-text">
${t`Flow used when authorizing this provider.`}
${msg("Flow used when logging out of this provider.")}
</p>
</ak-form-element-horizontal>
</div>

View file

@ -26,6 +26,7 @@ export class SAMLProviderImportForm extends Form<SAMLProvider> {
file: file,
name: data.name,
authorizationFlow: data.authorizationFlow || "",
invalidationFlow: data.invalidationFlow || "",
});
}
@ -46,6 +47,38 @@ export class SAMLProviderImportForm extends Form<SAMLProvider> {
${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;
}}
>
</ak-search-select>
<p class="pf-c-form__helper-text">
${t`Flow used when logging out of this provider.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Metadata")} name="metadata">
<input type="file" value="" class="pf-c-form-control" />