diff --git a/backend/src/main/resources/dynamic-registration.schema.json b/backend/src/main/resources/dynamic-registration.schema.json index 2ff19e746..ce4916e75 100644 --- a/backend/src/main/resources/dynamic-registration.schema.json +++ b/backend/src/main/resources/dynamic-registration.schema.json @@ -1,34 +1,48 @@ { "type": "object", "required": [ - "redirectUris" + "redirectUris", + "name" ], "properties": { - "applicationType": { - "title": "label.application-type", - "description": "tooltip.application-type", - "type": "string" + "name": { + "title": "label.dynamic-registration-name", + "description": "tooltip.dynamic-registration-name", + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "redirectUris": { + "title": "label.redirect-uris", + "description": "tooltip.redirect-uris", + "type": "string", + "minLength": 1, + "maxLength": 255 }, "approved": { "title": "label.approved", "description": "tooltip.approved", "type": "boolean" }, - "contacts": { - "title": "label.contacts", - "description": "tooltip.contacts", - "type": "string" - }, "enabled": { "title": "label.enabled", "description": "tooltip.enabled", "type": "boolean" }, + "applicationType": { + "title": "label.application-type", + "description": "tooltip.application-type", + "type": "string" + }, + "contacts": { + "title": "label.contacts", + "description": "tooltip.contacts", + "type": "string" + }, "grantType": { "title": "label.grant-type", "description": "tooltip.grant-type", "type": "string", - "widget": "select", "minLength": 1, "oneOf": [ { @@ -55,23 +69,12 @@ "description": "tooltip.logo-uri", "type": "string" }, - "name": { - "title": "label.name", - "description": "tooltip.name", - "type": "string" - }, "policyUri": { "title": "label.policy-uri", "description": "tooltip.policy-uri", "type": "string" }, - "redirectUris": { - "title": "label.redirect-uris", - "description": "tooltip.redirect-uris", - "type": "string", - "minLength": 1, - "maxLength": 255 - }, + "responseTypes": { "title": "label.response-types", "description": "tooltip.response-types", diff --git a/ui/public/assets/schema/source/metadata-source-oidc.json b/ui/public/assets/schema/source/metadata-source-oidc.json index 6714441fe..e9106fb4c 100644 --- a/ui/public/assets/schema/source/metadata-source-oidc.json +++ b/ui/public/assets/schema/source/metadata-source-oidc.json @@ -5,7 +5,8 @@ "protocol": { "title": "label.source-protocol", "description": "tooltip.source-protocol", - "type": "string" + "type": "string", + "default": "oidc" }, "serviceProviderName": { "title": "label.service-provider-name", @@ -36,6 +37,7 @@ "mdui": { "$ref": "#/definitions/MDUI" }, "securityInfo": { "type": "object", + "widget": { "id": "fieldset" }, "dependencies": { "authenticationRequestsSigned": { "oneOf": [ @@ -44,7 +46,7 @@ "authenticationRequestsSigned": { "enum": [true] }, - "keyDescriptors": { "minItems": 1 } + "x509Certificates": { "minItems": 1 } } }, { @@ -52,13 +54,14 @@ "authenticationRequestsSigned": { "enum": [false] }, - "keyDescriptors": { "minItems": 0 } + "x509Certificates": { "minItems": 0 } } } ] } }, "properties": { + "x509CertificateAvailable": { "type": "boolean" }, "authenticationRequestsSigned": { "title": "label.authentication-requests-signed", "description": "tooltip.authentication-requests-signed", @@ -93,16 +96,7 @@ "description": "tooltip.protocol-support-enumeration", "type": "string", "widget": { "id": "select" }, - "oneOf": [ - { "enum": ["SAML 2"], "description": "SAML 2" }, - { "enum": ["SAML 1.1"], "description": "SAML 1.1" }, - { - "enum": [ - "http://openid.net/specs/openid-connect-core-1_0.html" - ], - "description": "OIDC" - } - ] + "default": "http://openid.net/specs/openid-connect-core-1_0.html" }, "nameIdFormats": { "$ref": "#/definitions/nameIdFormats" }, "extensions": { @@ -116,33 +110,25 @@ "title": "label.post-logout-redirect-uris", "description": "tooltip.post-logout-redirect-uris", "type": "array", - "items": { - "type": "string" - } + "items": { "type": "string" } }, "defaultAcrValues": { "title": "label.default-acr-values", "description": "tooltip.default-acr-values", "type": "array", - "items": { - "type": "string" - } + "items": { "type": "string" } }, "requestUris": { "title": "label.request-uris", "description": "tooltip.request-uris", "type": "array", - "items": { - "type": "string" - } + "items": { "type": "string" } }, "audiences": { "title": "label.audience", "description": "tooltip.audience", "type": "array", - "items": { - "type": "string" - } + "items": { "type": "string" } }, "attributes": { "type": "object", @@ -274,20 +260,223 @@ "relyingPartyOverrides": { "type": "object", "properties": { + "authorizationCodeFlowEnabled": { + "title": "label.authorizationCodeFlowEnabled", + "description": "tooltip.authorizationCodeFlowEnabled", + "type": "boolean", + "default": true + }, + "alwaysIncludedAttributesToken": { + "title": "label.alwaysIncludedAttributes.token", + "description": "tooltip.alwaysIncludedAttributes.token", + "type": "string" + }, + "encryptionOptional": { + "title": "label.encryptionOptional", + "description": "tooltip.encryptionOptional", + "type": "boolean", + "default": true + }, + "proxyCount": { + "title": "label.proxyCount", + "description": "tooltip.proxyCount", + "type": "integer" + }, + "refreshTokenLifetimeOidc": { + "title": "label.refreshTokenLifetime.oidc", + "description": "tooltip.refreshTokenLifetime.oidc", + "type": "string", + "default": "PT2H" + }, + "acrRequestAlwaysEssential": { + "title": "label.acrRequestAlwaysEssential", + "description": "tooltip.acrRequestAlwaysEssential", + "type": "boolean", + "default": false + }, + "authorizeCodeLifetime": { + "title": "label.authorizeCodeLifetime", + "description": "tooltip.authorizeCodeLifetime", + "type": "string", + "default": "PT5M" + }, + "useSha": { + "title": "label.use-sha1-signing-algorithm", + "description": "tooltip.usa-sha-algorithm", + "type": "boolean", + "default": false + }, + "deniedUserInfoAttributes": { + "title": "label.deniedUserInfoAttributes", + "description": "tooltip.deniedUserInfoAttributes", + "type": "string" + }, "signAssertion": { "title": "label.sign-the-assertion", "description": "tooltip.sign-assertion", "type": "boolean", "default": false }, + "accessTokenTypeOauth": { + "title": "label.accessTokenType.oauth", + "description": "tooltip.accessTokenType.oauth", + "type": "string" + }, + "forcePKCEOidc": { + "title": "label.forcePKCE.oidc", + "description": "tooltip.forcePKCE.oidc", + "type": "boolean", + "default": false + }, + "inboundInterceptorFlows": { + "title": "label.inboundInterceptorFlows", + "description": "tooltip.inboundInterceptorFlows", + "type": "string" + }, + "enforceRefreshTokenRotation": { + "title": "label.enforceRefreshTokenRotation", + "description": "tooltip.enforceRefreshTokenRotation", + "type": "boolean", + "default": false + }, + "IDTokenLifetime": { + "title": "label.IDTokenLifetime", + "description": "tooltip.IDTokenLifetime", + "type": "string", + "default": "PT1H" + }, + "authenticationMethods": { + "$ref": "#/definitions/authenticationMethods" + }, + "resolveAttributesOauth": { + "title": "label.resolveAttributes.oauth", + "description": "tooltip.resolveAttributes.oauth", + "type": "boolean", + "default": true + }, + "encodedAttributes": { + "title": "label.encodedAttributes", + "description": "tooltip.encodedAttributes", + "type": "string" + }, + "accessTokenLifetimeOauth": { + "title": "label.accessTokenLifetime.oauth", + "description": "tooltip.accessTokenLifetime.oauth", + "type": "string", + "default": "PT10M" + }, + "allowPKCEPlainOauth": { + "title": "label.allowPKCEPlain.oauth", + "description": "tooltip.allowPKCEPlain.oauth", + "type": "boolean", + "default": false + }, + "encodeConsentInTokens": { + "title": "label.encodeConsentInTokens", + "description": "tooltip.encodeConsentInTokens", + "type": "boolean", + "default": false + }, + "postAuthenticationFlows": { + "title": "label.postAuthenticationFlows", + "description": "tooltip.postAuthenticationFlows", + "type": "string" + }, + "accessTokenLifetimeOidc": { + "title": "label.accessTokenLifetime.oidc", + "description": "tooltip.accessTokenLifetime.oidc", + "type": "string", + "default": "PT10M" + }, + "ignoreAuthenticationMethod": { + "title": "label.ignore-any-sp-requested-authentication-method", + "description": "tooltip.ignore-auth-method", + "type": "boolean", + "default": false + }, + "refreshTokensEnabled": { + "title": "label.refreshTokensEnabled", + "description": "tooltip.refreshTokensEnabled", + "type": "boolean", + "default": true + }, + "omitNotBefore": { + "title": "label.omit-not-before-condition", + "description": "tooltip.omit-not-before-condition", + "type": "boolean", + "default": false + }, + "IDTokenLifetimeBrowser": { + "title": "label.IDTokenLifetime.browser", + "description": "tooltip.IDTokenLifetime.browser", + "type": "string", + "default": "PT1H" + }, + "revocationMethod": { + "$ref": "#/definitions/revocationMethod" + }, + "resolveAttributesOIDC": { + "title": "label.resolveAttributes.oidc", + "description": "tooltip.resolveAttributes.oidc", + "type": "boolean", + "default": false + }, + "allowPKCEPlainOidc": { + "title": "label.allowPKCEPlain.oidc", + "description": "tooltip.allowPKCEPlain.oidc", + "type": "boolean", + "default": false + }, + "accessTokenTypeOidc": { + "title": "label.accessTokenType.oidc", + "description": "tooltip.accessTokenType.oidc", + "type": "string" + }, + "deniedUserInfoAttributesBrowser": { + "title": "label.deniedUserInfoAttributes.browser", + "description": "tooltip.deniedUserInfoAttributes.browser", + "type": "string" + }, + "hybridFlowEnabled": { + "title": "label.hybridFlowEnabled", + "description": "tooltip.hybridFlowEnabled", + "type": "boolean", + "default": true + }, + "tokenEndpointAuthMethods": { + "title": "label.tokenEndpointAuthMethods", + "description": "tooltip.tokenEndpointAuthMethods", + "type": "string", + "default": "client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt" + }, + "revocationLifetime": { + "title": "label.revocationLifetime", + "description": "tooltip.revocationLifetime", + "type": "string", + "default": "PT6H" + }, + "alwaysIncludedAttributesBrowser": { + "title": "label.alwaysIncludedAttributes.browser", + "description": "tooltip.alwaysIncludedAttributes.browser", + "type": "string" + }, "nameIdFormats": { "$ref": "#/definitions/nameIdFormats" }, + "implicitFlowEnabled": { + "title": "label.implicitFlowEnabled", + "description": "tooltip.implicitFlowEnabled", + "type": "boolean", + "default": true + }, "responderId": { "title": "label.responder-id", "description": "tooltip.responder-id", "type": "string" }, - "authenticationMethods": { - "$ref": "#/definitions/authenticationMethods" + "grantTypes": { + "title": "label.grantTypes", + "description": "tooltip.grantTypes", + "type": "string", + "default": "authorization_code, refresh_token" }, "ignoreRequestSignatures": { "title": "label.ignore-request-signatures", @@ -301,35 +490,40 @@ "type": "boolean", "default": false }, + "includeIssuerInResponse": { + "title": "label.includeIssuerInResponse", + "description": "tooltip.includeIssuerInResponse", + "type": "boolean", + "default": false + }, "forceAuthn": { "title": "label.force-authn", "description": "tooltip.force-authn", "type": "boolean", "default": false }, - "dontSignResponse": { - "title": "label.dont-sign-the-response", - "description": "tooltip.dont-sign-response", + "forcePKCEOauth": { + "title": "label.forcePKCE.oauth", + "description": "tooltip.forcePKCE.oauth", "type": "boolean", "default": false }, - "ignoreAuthenticationMethod": { - "title": "label.ignore-any-sp-requested-authentication-method", - "description": "tooltip.ignore-auth-method", + "dontSignResponse": { + "title": "label.dont-sign-the-response", + "description": "tooltip.dont-sign-response", "type": "boolean", "default": false }, - "useSha": { - "title": "label.use-sha1-signing-algorithm", - "description": "tooltip.usa-sha-algorithm", - "type": "boolean", - "default": false + "outboundInterceptorFlows": { + "title": "label.outboundInterceptorFlows", + "description": "tooltip.outboundInterceptorFlows", + "type": "string" }, - "omitNotBefore": { - "title": "label.omit-not-before-condition", - "description": "tooltip.omit-not-before-condition", - "type": "boolean", - "default": false + "refreshTokenLifetimeOauth": { + "title": "label.refreshTokenLifetime.oauth", + "description": "tooltip.refreshTokenLifetime.oauth", + "type": "string", + "default": "PT2H" } } }, @@ -426,13 +620,7 @@ "title": "label.element-type", "description": "tooltip.element-type", "type": "string", - "enum": [ - "X509Data", - "jwksUri", - "jwksData", - "clientSecret", - "clientSecretRef" - ] + "enum": ["X509Data", "jwksUri", "jwksData"] }, "type": { "title": "label.certificate-type", @@ -514,7 +702,7 @@ "enum": [ "https://tools.ietf.org/html/rfc6749#section-3.1.2" ], - "description": "https://tools.ietf.org/html/rfc6749#section-3.1.2" + "description": "OIDC / OAUTH Binding" } ] }, @@ -672,9 +860,9 @@ "url": { "required": ["name", "displayName"] } } }, - "nameIdFormats": { - "title": "label.nameid-format-to-send", - "description": "tooltip.nameid-format", + "authenticationMethods": { + "title": "label.authentication-methods-to-use", + "description": "tooltip.authentication-methods-to-use", "type": "array", "uniqueItems": true, "items": { @@ -682,16 +870,28 @@ "minLength": 1, "maxLength": 255, "examples": [ - "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", - "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", - "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", - "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" + "https://refeds.org/profile/mfa", + "urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken", + "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" ] } }, - "authenticationMethods": { - "title": "label.authentication-methods-to-use", - "description": "tooltip.authentication-methods-to-use", + "revocationMethod": { + "title": "label.revocationMethod", + "description": "tooltip.revocationMethod", + "type": "array", + "uniqueItems": false, + "items": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "enum": ["CHAIN", "TOKEN"], + "default": "CHAIN" + } + }, + "nameIdFormats": { + "title": "label.nameid-format-to-send", + "description": "tooltip.nameid-format", "type": "array", "uniqueItems": true, "items": { @@ -699,9 +899,10 @@ "minLength": 1, "maxLength": 255, "examples": [ - "https://refeds.org/profile/mfa", - "urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken", - "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" + "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", + "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", + "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", + "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" ] } } diff --git a/ui/src/app/dynamic-registration/api.js b/ui/src/app/dynamic-registration/api.js index 0d557f4f0..fc7b41508 100644 --- a/ui/src/app/dynamic-registration/api.js +++ b/ui/src/app/dynamic-registration/api.js @@ -1,23 +1,27 @@ import useFetch from 'use-http'; import {API_BASE_PATH, BASE_PATH} from '../App.constant'; +import DynamicConfigurationDefinition from './hoc/DynamicConfigurationDefinition'; + +export const DYNAMIC_REGISTRATION_JSONSCHEMA_PATH = DynamicConfigurationDefinition.schema; + export function useDynamicRegistration(id, opts = {}, onMount) { // - return useFetch(`${BASE_PATH}/assets/data/registration.json`, opts, onMount); + return useFetch(`${API_BASE_PATH}/DynamicRegistration`, opts, onMount); } export function useDynamicRegistrations(opts = {}, onMount) { // - return useFetch(`${BASE_PATH}/assets/data/registrations.json`, opts, onMount); + return useFetch(`${API_BASE_PATH}/DynamicRegistrations`, opts, onMount); } export function useDynamicRegistrationJsonSchema(opts = {}) { - return useFetch(`${BASE_PATH}/assets/schema/dynamic-registration/oidc.json`, opts, []); + return useFetch(DYNAMIC_REGISTRATION_JSONSCHEMA_PATH, opts, []); } export function useDynamicRegistrationUiSchema() { - return {}; + return DynamicConfigurationDefinition.uiSchema; } export function useDynamicRegistrationValidator() { return (formData, errors) => { diff --git a/ui/src/app/dynamic-registration/component/DynamicRegistrationForm.js b/ui/src/app/dynamic-registration/component/DynamicRegistrationForm.js index 1590d23be..98c64287b 100644 --- a/ui/src/app/dynamic-registration/component/DynamicRegistrationForm.js +++ b/ui/src/app/dynamic-registration/component/DynamicRegistrationForm.js @@ -19,6 +19,8 @@ export function DynamicRegistrationForm ({registration = {}, errors = [], loadin const uiSchema = useDynamicRegistrationUiSchema(); const validator = useDynamicRegistrationValidator(); + React.useEffect(() => console.log(registration), [registration]); + return (<>
diff --git a/ui/src/app/dynamic-registration/hoc/DynamicConfigurationDefinition.js b/ui/src/app/dynamic-registration/hoc/DynamicConfigurationDefinition.js index 9ccf0bd42..1a37c1af5 100644 --- a/ui/src/app/dynamic-registration/hoc/DynamicConfigurationDefinition.js +++ b/ui/src/app/dynamic-registration/hoc/DynamicConfigurationDefinition.js @@ -1,4 +1,4 @@ -import { BASE_PATH } from '../../App.constant'; +import API_BASE_PATH from '../../App.constant'; export const DynamicRegistrationDefinition = { label: 'Dynamic Registration', @@ -10,7 +10,6 @@ export const DynamicRegistrationDefinition = { index: 1, fields: [ 'name', - 'resourceId', 'redirectUris', 'responseTypes', 'grantTypes', @@ -27,17 +26,19 @@ export const DynamicRegistrationDefinition = { ] } ], - schema: `${BASE_PATH}assets/schema/dynamic-registration/oidc.json`, + schema: `${API_BASE_PATH}/ui/DynamicRegistration`, uiSchema: { layout: { groups: [ { - size: 6, + sizes: { + xs: 12, + lg: 12 + }, classNames: '', fields: [ 'name', - 'resourceId', 'redirectUris', 'responseTypes', 'grantTypes', @@ -52,9 +53,14 @@ export const DynamicRegistrationDefinition = { 'tosUri', 'scope' ] - }, + } ] }, + 'ui:order': [ + 'name', + 'redirectUris', + '*' + ] }, parser: (changes) => changes, diff --git a/ui/src/app/dynamic-registration/hoc/DynamicRegistrationContext.js b/ui/src/app/dynamic-registration/hoc/DynamicRegistrationContext.js index f922f2247..a442b2d00 100644 --- a/ui/src/app/dynamic-registration/hoc/DynamicRegistrationContext.js +++ b/ui/src/app/dynamic-registration/hoc/DynamicRegistrationContext.js @@ -92,17 +92,17 @@ function DynamicRegistrationsApi({ children, initial = {} }) { } async function select(id) { - const s = await selector.get(); + const s = await selector.get(`/${id}`); if (selector.response.ok) { dispatch(selectRegistration(s)); } } async function update(id) { - /*const s = await selector.update(); + const s = await selector.put(`/${id}`); if (selector.response.ok) { dispatch(selectRegistration(s)); - }*/ + } return Promise.resolve(id); } @@ -115,10 +115,11 @@ function DynamicRegistrationsApi({ children, initial = {} }) { } async function create(body) { - /*const s = await selector.update(); + console.log(body); + const s = await selector.post(``, body); if (selector.response.ok) { dispatch(selectRegistration(s)); - }*/ + } return Promise.resolve(body); } diff --git a/ui/src/app/dynamic-registration/view/DynamicRegistrationCreate.js b/ui/src/app/dynamic-registration/view/DynamicRegistrationCreate.js index 8b38b4ad3..c8f045ab8 100644 --- a/ui/src/app/dynamic-registration/view/DynamicRegistrationCreate.js +++ b/ui/src/app/dynamic-registration/view/DynamicRegistrationCreate.js @@ -3,12 +3,12 @@ import { Prompt, useHistory, useParams } from 'react-router-dom'; import { useDynamicRegistrationApi } from '../hoc/DynamicRegistrationContext'; import Translate from '../../i18n/components/translate'; -import { BASE_PATH } from '../../App.constant'; import { Schema } from '../../form/Schema'; import { FormManager } from '../../form/FormManager'; import { DynamicRegistrationForm } from '../component/DynamicRegistrationForm'; import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; import { useTranslator } from '../../i18n/hooks'; +import DynamicConfigurationDefinition from '../hoc/DynamicConfigurationDefinition'; export function DynamicRegistrationCreate () { @@ -18,8 +18,9 @@ export function DynamicRegistrationCreate () { const { create } = useDynamicRegistrationApi(); async function save(reg) { + console.log(reg); let toast; - const resp = await create(``, reg); + const resp = await create(reg); if (resp.ok) { gotoDetail({ refresh: true }); toast = createNotificationAction(`Added group successfully.`, NotificationTypes.SUCCESS); @@ -60,7 +61,7 @@ export function DynamicRegistrationCreate () {
- + {(schema) => {(data, errors) => diff --git a/ui/src/app/dynamic-registration/view/DynamicRegistrationEdit.js b/ui/src/app/dynamic-registration/view/DynamicRegistrationEdit.js index e6d33f66f..748d5ab2e 100644 --- a/ui/src/app/dynamic-registration/view/DynamicRegistrationEdit.js +++ b/ui/src/app/dynamic-registration/view/DynamicRegistrationEdit.js @@ -3,14 +3,12 @@ import { Prompt, useHistory, useParams } from 'react-router-dom'; import { useDynamicRegistrationApi, useSelectedDynamicRegistration } from '../hoc/DynamicRegistrationContext'; import Translate from '../../i18n/components/translate'; -import { useDynamicRegistrationJsonSchema } from '../api'; -import Form from '../../form/Form'; -import { BASE_PATH } from '../../App.constant'; import { Schema } from '../../form/Schema'; import { FormManager } from '../../form/FormManager'; import { DynamicRegistrationForm } from '../component/DynamicRegistrationForm'; import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; import { useTranslator } from '../../i18n/hooks'; +import DynamicConfigurationDefinition from '../hoc/DynamicConfigurationDefinition'; export function DynamicRegistrationEdit () { @@ -67,7 +65,7 @@ export function DynamicRegistrationEdit () {
- + {(schema) => {(data, errors) =>