diff --git a/swagger.yaml b/swagger.yaml index 4718ed966..263ba6629 100755 --- a/swagger.yaml +++ b/swagger.yaml @@ -14652,7 +14652,6 @@ definitions: Provider: required: - name - - application - authorization_flow type: object properties: @@ -14664,9 +14663,6 @@ definitions: title: Name type: string minLength: 1 - application: - title: Application - type: string authorization_flow: title: Authorization flow description: Flow used when authorizing this provider. @@ -15456,7 +15452,6 @@ definitions: OAuth2Provider: required: - name - - application - authorization_flow type: object properties: @@ -15468,9 +15463,6 @@ definitions: title: Name type: string minLength: 1 - application: - title: Application - type: string authorization_flow: title: Authorization flow description: Flow used when authorizing this provider. @@ -16686,7 +16678,6 @@ definitions: ProxyProvider: required: - name - - application - authorization_flow - internal_host - external_host @@ -16700,9 +16691,6 @@ definitions: title: Name type: string minLength: 1 - application: - title: Application - type: string authorization_flow: title: Authorization flow description: Flow used when authorizing this provider. @@ -16774,7 +16762,6 @@ definitions: SAMLProvider: required: - name - - application - authorization_flow - acs_url type: object @@ -16787,9 +16774,6 @@ definitions: title: Name type: string minLength: 1 - application: - title: Application - type: string authorization_flow: title: Authorization flow description: Flow used when authorizing this provider. @@ -16892,6 +16876,14 @@ definitions: type: string format: uuid x-nullable: true + sp_binding: + title: Service Provider Binding + description: This determines how authentik sends the response back to the + Service Provider. + type: string + enum: + - redirect + - post SAMLMetadata: type: object properties: diff --git a/web/src/api/legacy.ts b/web/src/api/legacy.ts index ab601baba..8c9986c0b 100644 --- a/web/src/api/legacy.ts +++ b/web/src/api/legacy.ts @@ -4,10 +4,6 @@ export class AdminURLManager { return `/administration/policies/${rest}`; } - static providers(rest: string): string { - return `/administration/providers/${rest}`; - } - static stages(rest: string): string { return `/administration/stages/${rest}`; } diff --git a/web/src/pages/groups/GroupForm.ts b/web/src/pages/groups/GroupForm.ts index 03ee52647..620432542 100644 --- a/web/src/pages/groups/GroupForm.ts +++ b/web/src/pages/groups/GroupForm.ts @@ -72,12 +72,14 @@ export class GroupForm extends Form { ?required=${true} name="users"> diff --git a/web/src/pages/outposts/ServiceConnectionDockerForm.ts b/web/src/pages/outposts/ServiceConnectionDockerForm.ts index 3e9010f83..409e2aa4d 100644 --- a/web/src/pages/outposts/ServiceConnectionDockerForm.ts +++ b/web/src/pages/outposts/ServiceConnectionDockerForm.ts @@ -77,10 +77,7 @@ export class ServiceConnectionDockerForm extends Form { ordering: "pk" }).then(certs => { return certs.results.map(cert => { - const selected = Array.from(this.sc?.tlsVerification || []).some(sp => { - return sp == cert.pk; - }); - return html``; + return html``; }); }))} @@ -96,10 +93,7 @@ export class ServiceConnectionDockerForm extends Form { ordering: "pk" }).then(certs => { return certs.results.map(cert => { - const selected = Array.from(this.sc?.tlsAuthentication || []).some(sp => { - return sp == cert.pk; - }); - return html``; + return html``; }); }))} diff --git a/web/src/pages/property-mappings/PropertyMappingLDAPForm.ts b/web/src/pages/property-mappings/PropertyMappingLDAPForm.ts index c6d34855a..6b0bba82e 100644 --- a/web/src/pages/property-mappings/PropertyMappingLDAPForm.ts +++ b/web/src/pages/property-mappings/PropertyMappingLDAPForm.ts @@ -6,6 +6,7 @@ import { DEFAULT_CONFIG } from "../../api/Config"; import { Form } from "../../elements/forms/Form"; import { ifDefined } from "lit-html/directives/if-defined"; import "../../elements/forms/HorizontalFormElement"; +import "../../elements/CodeMirror"; @customElement("ak-property-mapping-ldap-form") export class PropertyMappingLDAPForm extends Form { @@ -60,7 +61,7 @@ export class PropertyMappingLDAPForm extends Form { - +

Expression using Python. See here for a list of all variables. diff --git a/web/src/pages/property-mappings/PropertyMappingSAMLForm.ts b/web/src/pages/property-mappings/PropertyMappingSAMLForm.ts index a68e4ae68..dd26006fe 100644 --- a/web/src/pages/property-mappings/PropertyMappingSAMLForm.ts +++ b/web/src/pages/property-mappings/PropertyMappingSAMLForm.ts @@ -6,6 +6,7 @@ import { DEFAULT_CONFIG } from "../../api/Config"; import { Form } from "../../elements/forms/Form"; import { ifDefined } from "lit-html/directives/if-defined"; import "../../elements/forms/HorizontalFormElement"; +import "../../elements/CodeMirror"; @customElement("ak-property-mapping-saml-form") export class PropertyMappingLDAPForm extends Form { @@ -62,7 +63,7 @@ export class PropertyMappingLDAPForm extends Form { - +

${gettext("Optionally set the `FriendlyName` value of the Assertion attribute.")}

@@ -70,7 +71,7 @@ export class PropertyMappingLDAPForm extends Form { - +

Expression using Python. See here for a list of all variables. diff --git a/web/src/pages/property-mappings/PropertyMappingScopeForm.ts b/web/src/pages/property-mappings/PropertyMappingScopeForm.ts index d2be12078..40cc3417b 100644 --- a/web/src/pages/property-mappings/PropertyMappingScopeForm.ts +++ b/web/src/pages/property-mappings/PropertyMappingScopeForm.ts @@ -6,6 +6,7 @@ import { DEFAULT_CONFIG } from "../../api/Config"; import { Form } from "../../elements/forms/Form"; import { ifDefined } from "lit-html/directives/if-defined"; import "../../elements/forms/HorizontalFormElement"; +import "../../elements/CodeMirror"; @customElement("ak-property-mapping-scope-form") export class PropertyMappingScopeForm extends Form { @@ -67,7 +68,7 @@ export class PropertyMappingScopeForm extends Form { - +

Expression using Python. See here for a list of all variables. diff --git a/web/src/pages/providers/ProviderListPage.ts b/web/src/pages/providers/ProviderListPage.ts index daf4c29cf..5a797e52f 100644 --- a/web/src/pages/providers/ProviderListPage.ts +++ b/web/src/pages/providers/ProviderListPage.ts @@ -3,16 +3,20 @@ import { customElement, html, property, TemplateResult } from "lit-element"; import { AKResponse } from "../../api/Client"; import { TablePage } from "../../elements/table/TablePage"; -import "../../elements/buttons/ModalButton"; import "../../elements/buttons/SpinnerButton"; import "../../elements/buttons/Dropdown"; import "../../elements/forms/DeleteForm"; +import "../../elements/forms/ModalForm"; +import "../../elements/forms/ProxyForm"; +import "./oauth2/OAuth2ProviderForm"; +import "./proxy/ProxyProviderForm"; +import "./saml/SAMLProviderForm"; import { TableColumn } from "../../elements/table/Table"; import { until } from "lit-html/directives/until"; import { PAGE_SIZE } from "../../constants"; import { Provider, ProvidersApi } from "authentik-api"; import { DEFAULT_CONFIG } from "../../api/Config"; -import { AdminURLManager } from "../../api/legacy"; +import { ifDefined } from "lit-html/directives/if-defined"; @customElement("ak-provider-list") export class ProviderListPage extends TablePage { @@ -63,12 +67,29 @@ export class ProviderListPage extends TablePage { ${gettext("Warning: Provider not assigned to any application.")}`, html`${item.verboseName}`, html` - - + + + ${gettext("Update")} + + + ${gettext(`Update ${item.verboseName}`)} + + + + + { ${until(new ProvidersApi(DEFAULT_CONFIG).providersAllTypes({}).then((types) => { return types.map((type) => { return html`

  • - - -
    -
    +
  • `; }); }), html``)} diff --git a/web/src/pages/providers/ProviderViewPage.ts b/web/src/pages/providers/ProviderViewPage.ts index 6f7bba8ac..b854d8f70 100644 --- a/web/src/pages/providers/ProviderViewPage.ts +++ b/web/src/pages/providers/ProviderViewPage.ts @@ -4,9 +4,9 @@ import "../../elements/buttons/ModalButton"; import "../../elements/buttons/SpinnerButton"; import "../../elements/EmptyState"; -import "./SAMLProviderViewPage"; -import "./OAuth2ProviderViewPage"; -import "./ProxyProviderViewPage"; +import "./saml/SAMLProviderViewPage"; +import "./oauth2/OAuth2ProviderViewPage"; +import "./proxy/ProxyProviderViewPage"; import { Provider, ProvidersApi } from "authentik-api"; import { DEFAULT_CONFIG } from "../../api/Config"; import { ifDefined } from "lit-html/directives/if-defined"; diff --git a/web/src/pages/providers/oauth2/OAuth2ProviderForm.ts b/web/src/pages/providers/oauth2/OAuth2ProviderForm.ts new file mode 100644 index 000000000..929b319fb --- /dev/null +++ b/web/src/pages/providers/oauth2/OAuth2ProviderForm.ts @@ -0,0 +1,206 @@ +import { CryptoApi, FlowDesignationEnum, FlowsApi, OAuth2Provider, OAuth2ProviderClientTypeEnum, OAuth2ProviderIssuerModeEnum, OAuth2ProviderJwtAlgEnum, OAuth2ProviderSubModeEnum, PropertymappingsApi, ProvidersApi } from "authentik-api"; +import { gettext } from "django"; +import { customElement, property } from "lit-element"; +import { html, TemplateResult } from "lit-html"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import { Form } from "../../../elements/forms/Form"; +import { until } from "lit-html/directives/until"; +import { ifDefined } from "lit-html/directives/if-defined"; +import "../../../elements/forms/HorizontalFormElement"; + +@customElement("ak-provider-oauth2-form") +export class OAuth2ProviderFormPage extends Form { + + set providerUUID(value: number) { + new ProvidersApi(DEFAULT_CONFIG).providersOauth2Read({ + id: value, + }).then(provider => { + this.provider = provider; + }); + } + + @property({attribute: false}) + provider?: OAuth2Provider; + + getSuccessMessage(): string { + if (this.provider) { + return gettext("Successfully updated provider."); + } else { + return gettext("Successfully created provider."); + } + } + + send = (data: OAuth2Provider): Promise => { + if (this.provider) { + return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Update({ + id: this.provider.pk || 0, + data: data + }); + } else { + return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Create({ + data: data + }); + } + }; + + renderForm(): TemplateResult { + return html`
    + + + + + +

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

    +
    + + + +

    ${gettext("Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable.")}

    +
    + + + + + + + + + + + +

    ${gettext("Algorithm used to sign the JWT Tokens.")}

    +
    + + +

    ${gettext("Select which scopes can be used by the client. The client stil has to specify the scope to access the data.")}

    +

    ${gettext("Hold control/command to select multiple items.")}

    +
    + + +

    ${gettext("Key used to sign the tokens. Only required when JWT Algorithm is set to RS256.")}

    +
    + + + + + +

    + ${gettext("Configure what data should be used as unique User Identifier. For most cases, the default should be fine.")} +

    +
    + +
    + + +
    +

    ${gettext("Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.")}

    +
    + + +

    + ${gettext("Configure how the issuer field of the ID Token should be filled.")} +

    +
    +
    `; + } + +} diff --git a/web/src/pages/providers/OAuth2ProviderViewPage.ts b/web/src/pages/providers/oauth2/OAuth2ProviderViewPage.ts similarity index 88% rename from web/src/pages/providers/OAuth2ProviderViewPage.ts rename to web/src/pages/providers/oauth2/OAuth2ProviderViewPage.ts index a69e3cb5e..bb7da7e76 100644 --- a/web/src/pages/providers/OAuth2ProviderViewPage.ts +++ b/web/src/pages/providers/oauth2/OAuth2ProviderViewPage.ts @@ -9,23 +9,23 @@ import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList import PFSizing from "@patternfly/patternfly/utilities/Sizing/sizing.css"; import PFFlex from "@patternfly/patternfly/utilities/Flex/flex.css"; import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css"; -import AKGlobal from "../../authentik.css"; +import AKGlobal from "../../../authentik.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFForm from "@patternfly/patternfly/components/Form/form.css"; import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; -import "../../elements/buttons/ModalButton"; -import "../../elements/buttons/SpinnerButton"; -import "../../elements/CodeMirror"; -import "../../elements/Tabs"; -import "../../elements/events/ObjectChangelog"; -import "./RelatedApplicationButton"; -import { Page } from "../../elements/Page"; -import { convertToTitle } from "../../utils"; +import "../../../elements/buttons/ModalButton"; +import "../../../elements/buttons/SpinnerButton"; +import "../../../elements/CodeMirror"; +import "../../../elements/Tabs"; +import "../../../elements/events/ObjectChangelog"; +import "../RelatedApplicationButton"; +import "./OAuth2ProviderForm"; +import { Page } from "../../../elements/Page"; +import { convertToTitle } from "../../../utils"; import { OAuth2Provider, OAuth2ProviderSetupURLs, ProvidersApi } from "authentik-api"; -import { DEFAULT_CONFIG } from "../../api/Config"; -import { AdminURLManager } from "../../api/legacy"; -import { EVENT_REFRESH } from "../../constants"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import { EVENT_REFRESH } from "../../../constants"; @customElement("ak-provider-oauth2-view") export class OAuth2ProviderViewPage extends Page { @@ -128,12 +128,21 @@ export class OAuth2ProviderViewPage extends Page { diff --git a/web/src/pages/providers/proxy/ProxyProviderForm.ts b/web/src/pages/providers/proxy/ProxyProviderForm.ts new file mode 100644 index 000000000..5f1e1e39a --- /dev/null +++ b/web/src/pages/providers/proxy/ProxyProviderForm.ts @@ -0,0 +1,139 @@ +import { CryptoApi, FlowDesignationEnum, FlowsApi, ProvidersApi, ProxyProvider } from "authentik-api"; +import { gettext } from "django"; +import { customElement, property } from "lit-element"; +import { html, TemplateResult } from "lit-html"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import { Form } from "../../../elements/forms/Form"; +import { until } from "lit-html/directives/until"; +import { ifDefined } from "lit-html/directives/if-defined"; +import "../../../elements/forms/HorizontalFormElement"; + +@customElement("ak-provider-proxy-form") +export class ProxyProviderFormPage extends Form { + + set providerUUID(value: number) { + new ProvidersApi(DEFAULT_CONFIG).providersProxyRead({ + id: value, + }).then(provider => { + this.provider = provider; + }); + } + + @property({attribute: false}) + provider?: ProxyProvider; + + getSuccessMessage(): string { + if (this.provider) { + return gettext("Successfully updated provider."); + } else { + return gettext("Successfully created provider."); + } + } + + send = (data: ProxyProvider): Promise => { + if (this.provider) { + return new ProvidersApi(DEFAULT_CONFIG).providersProxyUpdate({ + id: this.provider.pk || 0, + data: data + }); + } else { + return new ProvidersApi(DEFAULT_CONFIG).providersProxyCreate({ + data: data + }); + } + }; + + renderForm(): TemplateResult { + return html`
    + + + + + +

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

    +
    + + + + + +
    + + +
    +

    ${gettext("Validate SSL Certificates of upstream servers.")}

    +
    + + + + + + + + + + +

    ${gettext("Regular expressions for which authentication is not required. Each new line is interpreted as a new Regular Expression.")}

    +
    + + +
    + + +
    +

    ${gettext("Set a custom HTTP-Basic Authentication header based on values from authentik.")}

    +
    + + +

    ${gettext("User/Group Attribute used for the user part of the HTTP-Basic Header. If not set, the user's Email address is used.")}

    +
    + + +

    ${gettext("User/Group Attribute used for the password part of the HTTP-Basic Header.")}

    +
    +
    `; + } + +} diff --git a/web/src/pages/providers/ProxyProviderViewPage.ts b/web/src/pages/providers/proxy/ProxyProviderViewPage.ts similarity index 85% rename from web/src/pages/providers/ProxyProviderViewPage.ts rename to web/src/pages/providers/proxy/ProxyProviderViewPage.ts index a1a49e465..8c3005240 100644 --- a/web/src/pages/providers/ProxyProviderViewPage.ts +++ b/web/src/pages/providers/proxy/ProxyProviderViewPage.ts @@ -9,20 +9,20 @@ import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList import PFSizing from "@patternfly/patternfly/utilities/Sizing/sizing.css"; import PFFlex from "@patternfly/patternfly/utilities/Flex/flex.css"; import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css"; -import AKGlobal from "../../authentik.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; +import AKGlobal from "../../../authentik.css"; -import "../../elements/buttons/ModalButton"; -import "../../elements/buttons/SpinnerButton"; -import "../../elements/CodeMirror"; -import "../../elements/Tabs"; -import "../../elements/events/ObjectChangelog"; -import "./RelatedApplicationButton"; -import { Page } from "../../elements/Page"; +import "../../../elements/buttons/ModalButton"; +import "../../../elements/buttons/SpinnerButton"; +import "../../../elements/CodeMirror"; +import "../../../elements/Tabs"; +import "../../../elements/events/ObjectChangelog"; +import "../RelatedApplicationButton"; +import "./ProxyProviderForm"; +import { Page } from "../../../elements/Page"; import { ProvidersApi, ProxyProvider } from "authentik-api"; -import { DEFAULT_CONFIG } from "../../api/Config"; -import { AdminURLManager } from "../../api/legacy"; -import { EVENT_REFRESH } from "../../constants"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import { EVENT_REFRESH } from "../../../constants"; @customElement("ak-provider-proxy-view") export class ProxyProviderViewPage extends Page { @@ -128,12 +128,21 @@ export class ProxyProviderViewPage extends Page { diff --git a/web/src/pages/providers/saml/SAMLProviderForm.ts b/web/src/pages/providers/saml/SAMLProviderForm.ts new file mode 100644 index 000000000..51b921902 --- /dev/null +++ b/web/src/pages/providers/saml/SAMLProviderForm.ts @@ -0,0 +1,237 @@ +import { CryptoApi, FlowDesignationEnum, FlowsApi, SAMLProvider, ProvidersApi, PropertymappingsApi, SAMLProviderSpBindingEnum, SAMLProviderDigestAlgorithmEnum, SAMLProviderSignatureAlgorithmEnum } from "authentik-api"; +import { gettext } from "django"; +import { customElement, property } from "lit-element"; +import { html, TemplateResult } from "lit-html"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import { Form } from "../../../elements/forms/Form"; +import { until } from "lit-html/directives/until"; +import { ifDefined } from "lit-html/directives/if-defined"; +import "../../../elements/forms/HorizontalFormElement"; + +@customElement("ak-provider-saml-form") +export class SAMLProviderFormPage extends Form { + + set providerUUID(value: number) { + new ProvidersApi(DEFAULT_CONFIG).providersSamlRead({ + id: value, + }).then(provider => { + this.provider = provider; + }); + } + + @property({attribute: false}) + provider?: SAMLProvider; + + getSuccessMessage(): string { + if (this.provider) { + return gettext("Successfully updated provider."); + } else { + return gettext("Successfully created provider."); + } + } + + send = (data: SAMLProvider): Promise => { + if (this.provider) { + return new ProvidersApi(DEFAULT_CONFIG).providersSamlUpdate({ + id: this.provider.pk || 0, + data: data + }); + } else { + return new ProvidersApi(DEFAULT_CONFIG).providersSamlCreate({ + data: data + }); + } + }; + + renderForm(): TemplateResult { + return html`
    + + + + + +

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

    +
    + + + + + + + + + + +

    ${gettext("Determines how authentik sends the response back to the Service Provider.")}

    +
    + + + + + + +

    ${gettext("Keypair used to sign outgoing Responses going to the Service Provider.")}

    +
    + + +

    ${gettext("When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.")}

    +
    + + + +

    ${gettext("Hold control/command to select multiple items.")}

    +
    + + +

    ${gettext("Configure how the NameID value will be created. When left empty, the NameIDPolicy of the incoming request will be respected.")}

    +
    + + + +

    ${gettext("Assertion valid not before current time + this value (Format: hours=-1;minutes=-2;seconds=-3).")}

    +
    + + +

    ${gettext("Assertion not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3).")}

    +
    + + +

    ${gettext("Session not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3).")}

    +
    + + + + + + + +
    `; + } + +} diff --git a/web/src/pages/providers/SAMLProviderViewPage.ts b/web/src/pages/providers/saml/SAMLProviderViewPage.ts similarity index 85% rename from web/src/pages/providers/SAMLProviderViewPage.ts rename to web/src/pages/providers/saml/SAMLProviderViewPage.ts index e6c992792..685f4a794 100644 --- a/web/src/pages/providers/SAMLProviderViewPage.ts +++ b/web/src/pages/providers/saml/SAMLProviderViewPage.ts @@ -10,20 +10,21 @@ import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList import PFSizing from "@patternfly/patternfly/utilities/Sizing/sizing.css"; import PFFlex from "@patternfly/patternfly/utilities/Flex/flex.css"; import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css"; -import AKGlobal from "../../authentik.css"; +import AKGlobal from "../../../authentik.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; -import "../../elements/buttons/ModalButton"; -import "../../elements/buttons/SpinnerButton"; -import "../../elements/CodeMirror"; -import "../../elements/Tabs"; -import "../../elements/events/ObjectChangelog"; -import "./RelatedApplicationButton"; -import { Page } from "../../elements/Page"; +import "../../../elements/buttons/ModalButton"; +import "../../../elements/buttons/SpinnerButton"; +import "../../../elements/CodeMirror"; +import "../../../elements/Tabs"; +import "../../../elements/events/ObjectChangelog"; +import "../RelatedApplicationButton"; +import "./SAMLProviderForm"; +import { Page } from "../../../elements/Page"; import { ProvidersApi, SAMLProvider } from "authentik-api"; -import { DEFAULT_CONFIG } from "../../api/Config"; -import { AdminURLManager, AppURLManager } from "../../api/legacy"; -import { EVENT_REFRESH } from "../../constants"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import { AppURLManager } from "../../../api/legacy"; +import { EVENT_REFRESH } from "../../../constants"; import { ifDefined } from "lit-html/directives/if-defined"; @customElement("ak-provider-saml-view") @@ -121,12 +122,21 @@ export class SAMLProviderViewPage extends Page {