Selaa lähdekoodia

refactor OidcSecuritySettingContents

Yuki Takei 5 kuukautta sitten
vanhempi
sitoutus
25c89516e0

+ 402 - 397
apps/app/src/client/components/Admin/Security/OidcSecuritySettingContents.tsx

@@ -1,8 +1,8 @@
-import React from 'react';
+import React, { useEffect, useCallback } from 'react';
 
 import { pathUtils } from '@growi/core/dist/utils';
 import { useTranslation } from 'next-i18next';
-import PropTypes from 'prop-types';
+import { useForm } from 'react-hook-form';
 import urljoin from 'url-join';
 
 
@@ -13,18 +13,73 @@ import { useSiteUrl } from '~/stores-universal/context';
 
 import { withUnstatedContainers } from '../../UnstatedUtils';
 
-class OidcSecurityManagementContents extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    this.onClickSubmit = this.onClickSubmit.bind(this);
-  }
-
-  async onClickSubmit() {
-    const { t, adminOidcSecurityContainer, adminGeneralSecurityContainer } = this.props;
+type Props = {
+  t: any;
+  adminGeneralSecurityContainer: AdminGeneralSecurityContainer;
+  adminOidcSecurityContainer: AdminOidcSecurityContainer;
+  siteUrl: string;
+};
 
+const OidcSecurityManagementContents = (props: Props) => {
+  const {
+    t, adminGeneralSecurityContainer, adminOidcSecurityContainer, siteUrl,
+  } = props;
+  const { isOidcEnabled } = adminGeneralSecurityContainer.state;
+  const {
+    oidcProviderName, oidcIssuerHost, oidcClientId, oidcClientSecret,
+    oidcAuthorizationEndpoint, oidcTokenEndpoint, oidcRevocationEndpoint, oidcIntrospectionEndpoint,
+    oidcUserInfoEndpoint, oidcEndSessionEndpoint, oidcRegistrationEndpoint, oidcJWKSUri,
+    oidcAttrMapId, oidcAttrMapUserName, oidcAttrMapName, oidcAttrMapEmail,
+  } = adminOidcSecurityContainer.state;
+
+  const oidcCallbackUrl = urljoin(pathUtils.removeTrailingSlash(siteUrl), '/passport/oidc/callback');
+
+  const { register, handleSubmit, reset } = useForm();
+
+  useEffect(() => {
+    reset({
+      oidcProviderName,
+      oidcIssuerHost,
+      oidcClientId,
+      oidcClientSecret,
+      oidcAuthorizationEndpoint,
+      oidcTokenEndpoint,
+      oidcRevocationEndpoint,
+      oidcIntrospectionEndpoint,
+      oidcUserInfoEndpoint,
+      oidcEndSessionEndpoint,
+      oidcRegistrationEndpoint,
+      oidcJWKSUri,
+      oidcAttrMapId,
+      oidcAttrMapUserName,
+      oidcAttrMapName,
+      oidcAttrMapEmail,
+    });
+  }, [
+    reset, oidcProviderName, oidcIssuerHost, oidcClientId, oidcClientSecret,
+    oidcAuthorizationEndpoint, oidcTokenEndpoint, oidcRevocationEndpoint, oidcIntrospectionEndpoint,
+    oidcUserInfoEndpoint, oidcEndSessionEndpoint, oidcRegistrationEndpoint, oidcJWKSUri,
+    oidcAttrMapId, oidcAttrMapUserName, oidcAttrMapName, oidcAttrMapEmail,
+  ]);
+
+  const onSubmit = useCallback(async(data) => {
     try {
+      await adminOidcSecurityContainer.changeOidcProviderName(data.oidcProviderName);
+      await adminOidcSecurityContainer.changeOidcIssuerHost(data.oidcIssuerHost);
+      await adminOidcSecurityContainer.changeOidcClientId(data.oidcClientId);
+      await adminOidcSecurityContainer.changeOidcClientSecret(data.oidcClientSecret);
+      await adminOidcSecurityContainer.changeOidcAuthorizationEndpoint(data.oidcAuthorizationEndpoint);
+      await adminOidcSecurityContainer.changeOidcTokenEndpoint(data.oidcTokenEndpoint);
+      await adminOidcSecurityContainer.changeOidcRevocationEndpoint(data.oidcRevocationEndpoint);
+      await adminOidcSecurityContainer.changeOidcIntrospectionEndpoint(data.oidcIntrospectionEndpoint);
+      await adminOidcSecurityContainer.changeOidcUserInfoEndpoint(data.oidcUserInfoEndpoint);
+      await adminOidcSecurityContainer.changeOidcEndSessionEndpoint(data.oidcEndSessionEndpoint);
+      await adminOidcSecurityContainer.changeOidcRegistrationEndpoint(data.oidcRegistrationEndpoint);
+      await adminOidcSecurityContainer.changeOidcJWKSUri(data.oidcJWKSUri);
+      await adminOidcSecurityContainer.changeOidcAttrMapId(data.oidcAttrMapId);
+      await adminOidcSecurityContainer.changeOidcAttrMapUserName(data.oidcAttrMapUserName);
+      await adminOidcSecurityContainer.changeOidcAttrMapName(data.oidcAttrMapName);
+      await adminOidcSecurityContainer.changeOidcAttrMapEmail(data.oidcAttrMapEmail);
       await adminOidcSecurityContainer.updateOidcSetting();
       await adminGeneralSecurityContainer.retrieveSetupStratedies();
       toastSuccess(t('security_settings.OAuth.OIDC.updated_oidc'));
@@ -32,446 +87,396 @@ class OidcSecurityManagementContents extends React.Component {
     catch (err) {
       toastError(err);
     }
-  }
+  }, [t, adminOidcSecurityContainer, adminGeneralSecurityContainer]);
+
+  return (
+    <>
+      <h2 className="alert-anchor border-bottom">
+        {t('security_settings.OAuth.OIDC.name')}
+      </h2>
 
-  render() {
-    const {
-      t, adminGeneralSecurityContainer, adminOidcSecurityContainer, siteUrl,
-    } = this.props;
-    const { isOidcEnabled } = adminGeneralSecurityContainer.state;
-    const oidcCallbackUrl = urljoin(pathUtils.removeTrailingSlash(siteUrl), '/passport/oidc/callback');
+      <div className="row  my-4">
+        <div className="offset-3 col-6">
+          <div className="form-check form-switch form-check-success">
+            <input
+              id="isOidcEnabled"
+              className="form-check-input"
+              type="checkbox"
+              checked={adminGeneralSecurityContainer.state.isOidcEnabled}
+              onChange={() => { adminGeneralSecurityContainer.switchIsOidcEnabled() }}
+            />
+            <label className="form-label form-check-label" htmlFor="isOidcEnabled">
+              {t('security_settings.OAuth.enable_oidc')}
+            </label>
+          </div>
+          {(!adminGeneralSecurityContainer.state.setupStrategies.includes('oidc') && isOidcEnabled)
+              && <div className="badge text-bg-warning">{t('security_settings.setup_is_not_yet_complete')}</div>}
+        </div>
+      </div>
+
+      <div className="row mb-5">
+        <label className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.callback_URL')}</label>
+        <div className="col-md-6">
+          <input
+            className="form-control"
+            type="text"
+            value={oidcCallbackUrl}
+            readOnly
+          />
+          <p className="form-text text-muted small">{t('security_settings.desc_of_callback_URL', { AuthName: 'OAuth' })}</p>
+          {(siteUrl == null || siteUrl === '') && (
+            <div className="alert alert-danger">
+              <span className="material-symbols-outlined">error</span>
+              <span
+                // eslint-disable-next-line max-len
+                dangerouslySetInnerHTML={{ __html: t('alert.siteUrl_is_not_set', { link: `<a href="/admin/app">${t('headers.app_settings', { ns: 'commons' })}<span class="material-symbols-outlined">login</span></a>`, ns: 'commons' }) }}
+              />
+            </div>
+          )}
+        </div>
+      </div>
 
-    return (
+      {isOidcEnabled && (
+        <form onSubmit={handleSubmit(onSubmit)}>
 
-      <>
-        <h2 className="alert-anchor border-bottom">
-          {t('security_settings.OAuth.OIDC.name')}
-        </h2>
+          <h3 className="border-bottom mb-4">{t('security_settings.configuration')}</h3>
 
-        <div className="row  my-4">
-          <div className="offset-3 col-6">
-            <div className="form-check form-switch form-check-success">
+          <div className="row mb-4">
+            <label htmlFor="oidcProviderName" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.providerName')}</label>
+            <div className="col-md-6">
               <input
-                id="isOidcEnabled"
-                className="form-check-input"
-                type="checkbox"
-                checked={adminGeneralSecurityContainer.state.isOidcEnabled}
-                onChange={() => { adminGeneralSecurityContainer.switchIsOidcEnabled() }}
+                className="form-control"
+                type="text"
+                {...register('oidcProviderName')}
               />
-              <label className="form-label form-check-label" htmlFor="isOidcEnabled">
-                {t('security_settings.OAuth.enable_oidc')}
-              </label>
             </div>
-            {(!adminGeneralSecurityContainer.state.setupStrategies.includes('oidc') && isOidcEnabled)
-              && <div className="badge text-bg-warning">{t('security_settings.setup_is_not_yet_complete')}</div>}
           </div>
-        </div>
 
-        <div className="row mb-5">
-          <label className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.callback_URL')}</label>
-          <div className="col-md-6">
-            <input
-              className="form-control"
-              type="text"
-              value={oidcCallbackUrl}
-              readOnly
-            />
-            <p className="form-text text-muted small">{t('security_settings.desc_of_callback_URL', { AuthName: 'OAuth' })}</p>
-            {(siteUrl == null || siteUrl === '') && (
-              <div className="alert alert-danger">
-                <span className="material-symbols-outlined">error</span>
-                <span
-                  // eslint-disable-next-line max-len
-                  dangerouslySetInnerHTML={{ __html: t('alert.siteUrl_is_not_set', { link: `<a href="/admin/app">${t('headers.app_settings', { ns: 'commons' })}<span class="material-symbols-outlined">login</span></a>`, ns: 'commons' }) }}
-                />
-              </div>
-            )}
+          <div className="row mb-4">
+            <label htmlFor="oidcIssuerHost" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.issuerHost')}</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcIssuerHost')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.Use env var if empty', { env: 'OAUTH_OIDC_ISSUER_HOST' }) }} />
+              </p>
+            </div>
           </div>
-        </div>
 
-        {isOidcEnabled && (
-          <>
-
-            <h3 className="border-bottom mb-4">{t('security_settings.configuration')}</h3>
-
-            <div className="row mb-4">
-              <label htmlFor="oidcProviderName" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.providerName')}</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcProviderName"
-                  value={adminOidcSecurityContainer.state.oidcProviderName || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcProviderName(e.target.value)}
-                />
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcClientId" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.clientID')}</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcClientId')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.Use env var if empty', { env: 'OAUTH_OIDC_CLIENT_ID' }) }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcIssuerHost" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.issuerHost')}</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcIssuerHost"
-                  value={adminOidcSecurityContainer.state.oidcIssuerHost || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcIssuerHost(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.Use env var if empty', { env: 'OAUTH_OIDC_ISSUER_HOST' }) }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcClientSecret" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.client_secret')}</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcClientSecret')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.Use env var if empty', { env: 'OAUTH_OIDC_CLIENT_SECRET' }) }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcClientId" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.clientID')}</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcClientId"
-                  value={adminOidcSecurityContainer.state.oidcClientId || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcClientId(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.Use env var if empty', { env: 'OAUTH_OIDC_CLIENT_ID' }) }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcAuthorizationEndpoint" className="text-start text-md-end col-md-3 col-form-label">
+              {t('security_settings.authorization_endpoint')}
+            </label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcAuthorizationEndpoint')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcClientSecret" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.client_secret')}</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcClientSecret"
-                  value={adminOidcSecurityContainer.state.oidcClientSecret || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcClientSecret(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.Use env var if empty', { env: 'OAUTH_OIDC_CLIENT_SECRET' }) }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcTokenEndpoint" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.token_endpoint')}</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcTokenEndpoint')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcAuthorizationEndpoint" className="text-start text-md-end col-md-3 col-form-label">
-                {t('security_settings.authorization_endpoint')}
-              </label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcAuthorizationEndpoint"
-                  value={adminOidcSecurityContainer.state.oidcAuthorizationEndpoint || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcAuthorizationEndpoint(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcRevocationEndpoint" className="text-start text-md-end col-md-3 col-form-label">
+              {t('security_settings.revocation_endpoint')}
+            </label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcRevocationEndpoint')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcTokenEndpoint" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.token_endpoint')}</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcTokenEndpoint"
-                  value={adminOidcSecurityContainer.state.oidcTokenEndpoint || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcTokenEndpoint(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcIntrospectionEndpoint" className="text-start text-md-end col-md-3 col-form-label">
+              {t('security_settings.introspection_endpoint')}
+            </label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcIntrospectionEndpoint')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcRevocationEndpoint" className="text-start text-md-end col-md-3 col-form-label">
-                {t('security_settings.revocation_endpoint')}
-              </label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcRevocationEndpoint"
-                  value={adminOidcSecurityContainer.state.oidcRevocationEndpoint || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcRevocationEndpoint(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcUserInfoEndpoint" className="text-start text-md-end col-md-3 col-form-label">
+              {t('security_settings.userinfo_endpoint')}
+            </label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcUserInfoEndpoint')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcIntrospectionEndpoint" className="text-start text-md-end col-md-3 col-form-label">
-                {t('security_settings.introspection_endpoint')}
-              </label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcIntrospectionEndpoint"
-                  value={adminOidcSecurityContainer.state.oidcIntrospectionEndpoint || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcIntrospectionEndpoint(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcEndSessionEndpoint" className="text-start text-md-end col-md-3 col-form-label">
+              {t('security_settings.end_session_endpoint')}
+            </label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcEndSessionEndpoint')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcUserInfoEndpoint" className="text-start text-md-end col-md-3 col-form-label">
-                {t('security_settings.userinfo_endpoint')}
-              </label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcUserInfoEndpoint"
-                  value={adminOidcSecurityContainer.state.oidcUserInfoEndpoint || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcUserInfoEndpoint(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcRegistrationEndpoint" className="text-start text-md-end col-md-3 col-form-label">
+              {t('security_settings.registration_endpoint')}
+            </label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcRegistrationEndpoint')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcEndSessionEndpoint" className="text-start text-md-end col-md-3 col-form-label">
-                {t('security_settings.end_session_endpoint')}
-              </label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcEndSessionEndpoint"
-                  value={adminOidcSecurityContainer.state.oidcEndSessionEndpoint || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcEndSessionEndpoint(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcJWKSUri" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.jwks_uri')}</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcJWKSUri')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcRegistrationEndpoint" className="text-start text-md-end col-md-3 col-form-label">
-                {t('security_settings.registration_endpoint')}
-              </label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcRegistrationEndpoint"
-                  value={adminOidcSecurityContainer.state.oidcRegistrationEndpoint || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcRegistrationEndpoint(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
-                </p>
-              </div>
-            </div>
+          <h3 className="alert-anchor border-bottom mb-4">
+            Attribute Mapping ({t('optional')})
+          </h3>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcJWKSUri" className="text-start text-md-end col-md-3 col-form-label">{t('security_settings.jwks_uri')}</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcJWKSUri"
-                  value={adminOidcSecurityContainer.state.oidcJWKSUri || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcJWKSUri(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.Use discovered URL if empty') }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcAttrMapId" className="text-start text-md-end col-md-3 col-form-label">Identifier</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcAttrMapId')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.id_detail') }} />
+              </p>
             </div>
+          </div>
 
-            <h3 className="alert-anchor border-bottom mb-4">
-              Attribute Mapping ({t('optional')})
-            </h3>
+          <div className="row mb-4">
+            <label htmlFor="oidcAttrMapUserName" className="text-start text-md-end col-md-3 col-form-label">{t('username')}</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcAttrMapUserName')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.username_detail') }} />
+              </p>
+            </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcAttrMapId" className="text-start text-md-end col-md-3 col-form-label">Identifier</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcAttrMapId"
-                  value={adminOidcSecurityContainer.state.oidcAttrMapId || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcAttrMapId(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.id_detail') }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcAttrMapName" className="text-start text-md-end col-md-3 col-form-label">{t('Name')}</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcAttrMapName')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.name_detail') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcAttrMapUserName" className="text-start text-md-end col-md-3 col-form-label">{t('username')}</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcAttrMapUserName"
-                  value={adminOidcSecurityContainer.state.oidcAttrMapUserName || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcAttrMapUserName(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.username_detail') }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label htmlFor="oidcAttrMapEmail" className="text-start text-md-end col-md-3 col-form-label">{t('Email')}</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                {...register('oidcAttrMapEmail')}
+              />
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.mapping_detail', { target: t('Email') }) }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcAttrMapName" className="text-start text-md-end col-md-3 col-form-label">{t('Name')}</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="oidcAttrMapName"
-                  value={adminOidcSecurityContainer.state.oidcAttrMapName || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcAttrMapName(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.name_detail') }} />
-                </p>
-              </div>
+          <div className="row mb-4">
+            <label className="form-label text-start text-md-end col-md-3 col-form-label">{t('security_settings.callback_URL')}</label>
+            <div className="col-md-6">
+              <input
+                className="form-control"
+                type="text"
+                defaultValue={oidcCallbackUrl}
+                readOnly
+              />
+              <p className="form-text text-muted small">{t('security_settings.desc_of_callback_URL', { AuthName: 'OAuth' })}</p>
+              {(siteUrl == null || siteUrl === '') && (
+                <div className="alert alert-danger">
+                  <span className="material-symbols-outlined">error</span>
+                  <span
+                    // eslint-disable-next-line max-len
+                    dangerouslySetInnerHTML={{ __html: t('alert.siteUrl_is_not_set', { link: `<a href="/admin/app">${t('headers.app_settings', { ns: 'commons' })}<span class="material-symbols-outlined">login</span></a>`, ns: 'commons' }) }}
+                  />
+                </div>
+              )}
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label htmlFor="oidcAttrMapEmail" className="text-start text-md-end col-md-3 col-form-label">{t('Email')}</label>
-              <div className="col-md-6">
+          <div className="row mb-4">
+            <div className="offset-md-3 col-md-6">
+              <div className="form-check form-check-success">
                 <input
-                  className="form-control"
-                  type="text"
-                  name="oidcAttrMapEmail"
-                  value={adminOidcSecurityContainer.state.oidcAttrMapEmail || ''}
-                  onChange={e => adminOidcSecurityContainer.changeOidcAttrMapEmail(e.target.value)}
+                  id="bindByUserName-oidc"
+                  className="form-check-input"
+                  type="checkbox"
+                  checked={adminOidcSecurityContainer.state.isSameUsernameTreatedAsIdenticalUser}
+                  onChange={() => { adminOidcSecurityContainer.switchIsSameUsernameTreatedAsIdenticalUser() }}
+                />
+                <label
+                  className="form-label form-check-label"
+                  htmlFor="bindByUserName-oidc"
+                  dangerouslySetInnerHTML={{ __html: t('security_settings.Treat username matching as identical') }}
                 />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.mapping_detail', { target: t('Email') }) }} />
-                </p>
               </div>
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.Treat username matching as identical_warn') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row mb-4">
-              <label className="form-label text-start text-md-end col-md-3 col-form-label">{t('security_settings.callback_URL')}</label>
-              <div className="col-md-6">
+          <div className="row mb-4">
+            <div className="offset-md-3 col-md-6">
+              <div className="form-check form-check-success">
                 <input
-                  className="form-control"
-                  type="text"
-                  defaultValue={oidcCallbackUrl}
-                  readOnly
+                  id="bindByEmail-oidc"
+                  className="form-check-input"
+                  type="checkbox"
+                  checked={adminOidcSecurityContainer.state.isSameEmailTreatedAsIdenticalUser || false}
+                  onChange={() => { adminOidcSecurityContainer.switchIsSameEmailTreatedAsIdenticalUser() }}
+                />
+                <label
+                  className="form-label form-check-label"
+                  htmlFor="bindByEmail-oidc"
+                  dangerouslySetInnerHTML={{ __html: t('security_settings.Treat email matching as identical') }}
                 />
-                <p className="form-text text-muted small">{t('security_settings.desc_of_callback_URL', { AuthName: 'OAuth' })}</p>
-                {(siteUrl == null || siteUrl === '') && (
-                  <div className="alert alert-danger">
-                    <span className="material-symbols-outlined">error</span>
-                    <span
-                      // eslint-disable-next-line max-len
-                      dangerouslySetInnerHTML={{ __html: t('alert.siteUrl_is_not_set', { link: `<a href="/admin/app">${t('headers.app_settings', { ns: 'commons' })}<span class="material-symbols-outlined">login</span></a>`, ns: 'commons' }) }}
-                    />
-                  </div>
-                )}
-              </div>
-            </div>
-
-            <div className="row mb-4">
-              <div className="offset-md-3 col-md-6">
-                <div className="form-check form-check-success">
-                  <input
-                    id="bindByUserName-oidc"
-                    className="form-check-input"
-                    type="checkbox"
-                    checked={adminOidcSecurityContainer.state.isSameUsernameTreatedAsIdenticalUser}
-                    onChange={() => { adminOidcSecurityContainer.switchIsSameUsernameTreatedAsIdenticalUser() }}
-                  />
-                  <label
-                    className="form-label form-check-label"
-                    htmlFor="bindByUserName-oidc"
-                    dangerouslySetInnerHTML={{ __html: t('security_settings.Treat username matching as identical') }}
-                  />
-                </div>
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.Treat username matching as identical_warn') }} />
-                </p>
-              </div>
-            </div>
-
-            <div className="row mb-4">
-              <div className="offset-md-3 col-md-6">
-                <div className="form-check form-check-success">
-                  <input
-                    id="bindByEmail-oidc"
-                    className="form-check-input"
-                    type="checkbox"
-                    checked={adminOidcSecurityContainer.state.isSameEmailTreatedAsIdenticalUser || false}
-                    onChange={() => { adminOidcSecurityContainer.switchIsSameEmailTreatedAsIdenticalUser() }}
-                  />
-                  <label
-                    className="form-label form-check-label"
-                    htmlFor="bindByEmail-oidc"
-                    dangerouslySetInnerHTML={{ __html: t('security_settings.Treat email matching as identical') }}
-                  />
-                </div>
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.Treat email matching as identical_warn') }} />
-                </p>
               </div>
+              <p className="form-text text-muted">
+                <small dangerouslySetInnerHTML={{ __html: t('security_settings.Treat email matching as identical_warn') }} />
+              </p>
             </div>
+          </div>
 
-            <div className="row my-3">
-              <div className="offset-3 col-5">
-                <button
-                  type="button"
-                  className="btn btn-primary"
-                  disabled={adminOidcSecurityContainer.state.retrieveError != null}
-                  onClick={this.onClickSubmit}
-                >
-                  {t('Update')}
-                </button>
-              </div>
+          <div className="row my-3">
+            <div className="offset-3 col-5">
+              <button
+                type="submit"
+                className="btn btn-primary"
+                disabled={adminOidcSecurityContainer.state.retrieveError != null}
+              >
+                {t('Update')}
+              </button>
             </div>
-          </>
-        )}
-
-
-        <hr />
-
-        <div style={{ minHeight: '300px' }}>
-          <h4>
-            <span className="material-symbols-outlined" aria-hidden="true">help</span>
-            <a href="#collapseHelpForOidcOauth" data-bs-toggle="collapse"> {t('security_settings.OAuth.how_to.oidc')}</a>
-          </h4>
-          <div className=" card custom-card bg-body-tertiary">
-            <ol id="collapseHelpForOidcOauth" className="collapse mb-0">
-              <li>{t('security_settings.OAuth.OIDC.register_1')}</li>
-              <li dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.register_2', { url: oidcCallbackUrl }) }} />
-              <li>{t('security_settings.OAuth.OIDC.register_3')}</li>
-            </ol>
           </div>
+        </form>
+      )}
+
+
+      <hr />
+
+      <div style={{ minHeight: '300px' }}>
+        <h4>
+          <span className="material-symbols-outlined" aria-hidden="true">help</span>
+          <a href="#collapseHelpForOidcOauth" data-bs-toggle="collapse"> {t('security_settings.OAuth.how_to.oidc')}</a>
+        </h4>
+        <div className=" card custom-card bg-body-tertiary">
+          <ol id="collapseHelpForOidcOauth" className="collapse mb-0">
+            <li>{t('security_settings.OAuth.OIDC.register_1')}</li>
+            <li dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.OIDC.register_2', { url: oidcCallbackUrl }) }} />
+            <li>{t('security_settings.OAuth.OIDC.register_3')}</li>
+          </ol>
         </div>
+      </div>
 
-      </>
-    );
-  }
-
-}
-
-OidcSecurityManagementContents.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  adminGeneralSecurityContainer: PropTypes.instanceOf(AdminGeneralSecurityContainer).isRequired,
-  adminOidcSecurityContainer: PropTypes.instanceOf(AdminOidcSecurityContainer).isRequired,
-  siteUrl: PropTypes.string,
+    </>
+  );
 };
 
 const OidcSecurityManagementContentsWrapperFC = (props) => {