providers/oauth2: Add provider federation between OAuth2 Providers (#12083)
* rename + add field Signed-off-by: Jens Langhammer <jens@goauthentik.io> * initial implementation Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix Signed-off-by: Jens Langhammer <jens@goauthentik.io> * refactor Signed-off-by: Jens Langhammer <jens@goauthentik.io> * rework source cc tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * update docs Signed-off-by: Jens Langhammer <jens@goauthentik.io> * re-migrate Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix a Signed-off-by: Jens Langhammer <jens@goauthentik.io> * Apply suggestions from code review Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com> Signed-off-by: Jens L. <jens@beryju.org> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io> Signed-off-by: Jens L. <jens@beryju.org> Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
This commit is contained in:
@ -307,7 +307,7 @@ export class ApplicationWizardAuthenticationByOauth extends BaseProviderPanel {
|
||||
>
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${oauth2SourcesProvider}
|
||||
.selector=${oauth2SourcesSelector(provider?.jwksSources)}
|
||||
.selector=${oauth2SourcesSelector(provider?.jwtFederationSources)}
|
||||
available-label=${msg("Available Sources")}
|
||||
selected-label=${msg("Selected Sources")}
|
||||
></ak-dual-select-dynamic-selected>
|
||||
|
@ -248,7 +248,9 @@ export class AkTypeProxyApplicationWizardPage extends BaseProviderPanel {
|
||||
>
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${oauth2SourcesProvider}
|
||||
.selector=${oauth2SourcesSelector(this.instance?.jwksSources)}
|
||||
.selector=${oauth2SourcesSelector(
|
||||
this.instance?.jwtFederationSources,
|
||||
)}
|
||||
available-label=${msg("Available Sources")}
|
||||
selected-label=${msg("Selected Sources")}
|
||||
></ak-dual-select-dynamic-selected>
|
||||
|
@ -13,6 +13,7 @@ import "@goauthentik/components/ak-textarea-input";
|
||||
import "@goauthentik/elements/ak-array-input.js";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider.js";
|
||||
import { DualSelectPair } from "@goauthentik/elements/ak-dual-select/types";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import "@goauthentik/elements/forms/Radio";
|
||||
@ -116,6 +117,45 @@ export const redirectUriHelp = html`${redirectUriHelpMessages.map(
|
||||
(m) => html`<p class="pf-c-form__helper-text">${m}</p>`,
|
||||
)}`;
|
||||
|
||||
const providerToSelect = (provider: OAuth2Provider) => [provider.pk, provider.name];
|
||||
|
||||
export async function oauth2ProvidersProvider(page = 1, search = "") {
|
||||
const oauthProviders = await new ProvidersApi(DEFAULT_CONFIG).providersOauth2List({
|
||||
ordering: "name",
|
||||
pageSize: 20,
|
||||
search: search.trim(),
|
||||
page,
|
||||
});
|
||||
|
||||
return {
|
||||
pagination: oauthProviders.pagination,
|
||||
options: oauthProviders.results.map((provider) => providerToSelect(provider)),
|
||||
};
|
||||
}
|
||||
|
||||
export function oauth2ProviderSelector(instanceProviders: number[] | undefined) {
|
||||
if (!instanceProviders) {
|
||||
return async (mappings: DualSelectPair<OAuth2Provider>[]) =>
|
||||
mappings.filter(
|
||||
([_0, _1, _2, source]: DualSelectPair<OAuth2Provider>) => source !== undefined,
|
||||
);
|
||||
}
|
||||
|
||||
return async () => {
|
||||
const oauthSources = new ProvidersApi(DEFAULT_CONFIG);
|
||||
const mappings = await Promise.allSettled(
|
||||
instanceProviders.map((instanceId) =>
|
||||
oauthSources.providersOauth2Retrieve({ id: instanceId }),
|
||||
),
|
||||
);
|
||||
|
||||
return mappings
|
||||
.filter((s) => s.status === "fulfilled")
|
||||
.map((s) => s.value)
|
||||
.map(providerToSelect);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Form page for OAuth2 Authentication Method
|
||||
*
|
||||
@ -381,12 +421,12 @@ export class OAuth2ProviderFormPage extends BaseProviderForm<OAuth2Provider> {
|
||||
<span slot="header">${msg("Machine-to-Machine authentication settings")}</span>
|
||||
<div slot="body" class="pf-c-form">
|
||||
<ak-form-element-horizontal
|
||||
label=${msg("Trusted OIDC Sources")}
|
||||
name="jwksSources"
|
||||
label=${msg("Federated OIDC Sources")}
|
||||
name="jwtFederationSources"
|
||||
>
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${oauth2SourcesProvider}
|
||||
.selector=${oauth2SourcesSelector(provider?.jwksSources)}
|
||||
.selector=${oauth2SourcesSelector(provider?.jwtFederationSources)}
|
||||
available-label=${msg("Available Sources")}
|
||||
selected-label=${msg("Selected Sources")}
|
||||
></ak-dual-select-dynamic-selected>
|
||||
@ -396,6 +436,22 @@ export class OAuth2ProviderFormPage extends BaseProviderForm<OAuth2Provider> {
|
||||
)}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${msg("Federated OIDC Providers")}
|
||||
name="jwtFederationProviders"
|
||||
>
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${oauth2ProvidersProvider}
|
||||
.selector=${oauth2ProviderSelector(provider?.jwtFederationProviders)}
|
||||
available-label=${msg("Available Providers")}
|
||||
selected-label=${msg("Selected Providers")}
|
||||
></ak-dual-select-dynamic-selected>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"JWTs signed by the selected providers can be used to authenticate to this provider.",
|
||||
)}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</div>
|
||||
</ak-form-group>`;
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
||||
import { BaseProviderForm } from "@goauthentik/admin/providers/BaseProviderForm";
|
||||
import {
|
||||
oauth2ProviderSelector,
|
||||
oauth2ProvidersProvider,
|
||||
} from "@goauthentik/admin/providers/oauth2/OAuth2ProviderForm";
|
||||
import {
|
||||
oauth2SourcesProvider,
|
||||
oauth2SourcesSelector,
|
||||
@ -385,11 +389,11 @@ ${this.instance?.skipPathRegex}</textarea
|
||||
${this.showHttpBasic ? this.renderHttpBasic() : html``}
|
||||
<ak-form-element-horizontal
|
||||
label=${msg("Trusted OIDC Sources")}
|
||||
name="jwksSources"
|
||||
name="jwtFederationSources"
|
||||
>
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${oauth2SourcesProvider}
|
||||
.selector=${oauth2SourcesSelector(this.instance?.jwksSources)}
|
||||
.selector=${oauth2SourcesSelector(this.instance?.jwtFederationSources)}
|
||||
available-label=${msg("Available Sources")}
|
||||
selected-label=${msg("Selected Sources")}
|
||||
></ak-dual-select-dynamic-selected>
|
||||
@ -399,6 +403,24 @@ ${this.instance?.skipPathRegex}</textarea
|
||||
)}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${msg("Federated OIDC Providers")}
|
||||
name="jwtFederationProviders"
|
||||
>
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${oauth2ProvidersProvider}
|
||||
.selector=${oauth2ProviderSelector(
|
||||
this.instance?.jwtFederationProviders,
|
||||
)}
|
||||
available-label=${msg("Available Providers")}
|
||||
selected-label=${msg("Selected Providers")}
|
||||
></ak-dual-select-dynamic-selected>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"JWTs signed by the selected providers can be used to authenticate to this provider.",
|
||||
)}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</div>
|
||||
</ak-form-group>
|
||||
|
||||
|
Reference in New Issue
Block a user