social_auth_entra_id-1.0.x-dev/src/Form/SocialAuthEntraIdSettingsForm.php

src/Form/SocialAuthEntraIdSettingsForm.php
<?php

namespace Drupal\social_auth_entra_id\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;

/**
 * Configures settings for the Entra ID social authentication module.
 *
 * Provides configuration form for Microsoft Entra ID (Azure AD) OAuth 2.0
 * integration including:
 * - Azure AD application credentials (Client ID, Secret, Tenant ID)
 * - Login behavior (auto-registration vs login-only)
 * - Domain allowlisting for email restrictions
 * - Security settings for privileged account protection.
 *
 * Available at: /admin/config/services/entra-id/settings
 */
class SocialAuthEntraIdSettingsForm extends ConfigFormBase {

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames() {
    return ['social_auth_entra_id.settings'];
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'social_auth_entra_id_settings_form';
  }

  /**
   * Builds the configuration form.
   *
   * Creates form elements for all module settings including Azure AD
   * credentials, behavior options, and security configurations.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @return array
   *   The form structure.
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    // Load existing configuration.
    $config = $this->config('social_auth_entra_id.settings');

    // Azure AD credentials group.
    $form['azure_credentials'] = [
      '#type' => 'details',
      '#title' => $this->t('Azure AD Application Credentials'),
      '#open' => TRUE,
      '#description' => $this->t('Configure your Microsoft Entra ID (Azure AD) application credentials. <a href="@portal" target="_blank">Open Azure Portal</a> to manage your app registrations.', [
        '@portal' => 'https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade',
      ]),
    ];

    // Azure AD Application (client) ID.
    // Found in Azure Portal > App registrations > Overview.
    $form['azure_credentials']['client_id'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Client ID'),
      '#default_value' => $config->get('client_id'),
      '#description' => $this->t('Enter the Application (client) ID. Find it in') . ' '
      . $this->t('<a href="@link" target="_blank">Azure Portal > App registrations</a>.', [
        '@link' => 'https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade',
      ]),
      '#required' => TRUE,
    ];

    // Display the callback URL for administrator reference.
    // This is the Redirect URI to configure in Azure AD application
    // registration.
    // Disabled so it is not editable; generated automatically.
    $callback_url = Url::fromRoute(
      'social_auth_entra_id.callback',
      [],
      ['absolute' => TRUE]
    )->toString();
    $form['azure_credentials']['callback_url'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Callback URL (Redirect URI)'),
      '#default_value' => $callback_url,
      '#description' => $this->t('Copy this URL into Azure AD Redirect URIs.'),
      '#disabled' => TRUE,
    ];

    // Azure AD Application client secret value.
    // Created in Azure Portal > App registrations > Certificates & secrets.
    // SECURITY: Uses password field to prevent shoulder surfing.
    $form['azure_credentials']['client_secret'] = [
      '#type' => 'password',
      '#title' => $this->t('Client Secret'),
      '#default_value' => $config->get('client_secret'),
      '#description' => $this->t('Create a client secret in Azure Portal > App registrations.') . ' '
      . $this->t('Paste the secret value here. Leave blank to keep existing.') . ' '
      . $this->t('<a href="@link" target="_blank">Open App registrations</a>.', [
        '@link' => 'https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade',
      ]),
      '#required' => FALSE,
      '#attributes' => ['autocomplete' => 'off'],
    ];

    // Azure AD Directory (tenant) ID.
    // Found in Azure Portal > Azure Active Directory > Overview.
    $form['azure_credentials']['tenant_id'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Tenant ID'),
      '#default_value' => $config->get('tenant_id'),
      '#description' => $this->t('Directory (tenant) ID from Azure Active Directory > Overview.') . ' '
      . $this->t('Only required for single-tenant (organization accounts).') . ' '
      . $this->t('<a href="@link" target="_blank">Open Azure AD Overview</a>.', [
        '@link' => 'https://portal.azure.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/~/Overview',
      ]),
      '#required' => FALSE,
      '#states' => [
        'required' => [
          ':input[name="account_type"]' => ['value' => 'organization'],
        ],
        'visible' => [
          ':input[name="account_type"]' => ['value' => 'organization'],
        ],
      ],
    ];

    // Microsoft account type selection.
    // Determines which types of Microsoft accounts can authenticate.
    $form['azure_credentials']['account_type'] = [
      '#type' => 'radios',
      '#title' => $this->t('Account Type'),
      '#options' => [
        'organization' => $this->t('Organization accounts only (requires Tenant ID above)'),
        'common' => $this->t('Both organization and personal Microsoft accounts'),
        'consumers' => $this->t('Personal Microsoft accounts only (Hotmail, Outlook.com, Live.com)'),
      ],
      '#default_value' => $config->get('account_type') ?? 'organization',
      '#description' => $this->t('Choose what types of Microsoft accounts can authenticate.<br /><br /><strong>Mapping to Azure Portal “Supported account types”:</strong><ul><li><strong>Organization accounts only:</strong> Select <em>Accounts in this organizational directory only (Single tenant)</em></li><li><strong>Both organization and personal:</strong> Select <em>Accounts in any organizational directory and personal Microsoft accounts</em></li><li><strong>Personal accounts only:</strong> Select <em>Personal Microsoft accounts only</em></li></ul><em>Note:</em> The “Accounts in any organizational directory (Multitenant)” option alone does not allow personal accounts.'),
    ];

    // Authentication behavior settings group.
    $form['auth_behavior'] = [
      '#type' => 'details',
      '#title' => $this->t('Authentication Behavior'),
      '#open' => TRUE,
    ];

    // Determines behavior when new users authenticate.
    // register_and_login: Automatically creates Drupal accounts.
    // login_only: Restricts to existing accounts only.
    $form['auth_behavior']['login_behavior'] = [
      '#type' => 'radios',
      '#title' => $this->t('Login Behavior'),
      '#options' => [
        'register_and_login' => $this->t('Register and Login'),
        'login_only' => $this->t('Login Only'),
      ],
      '#default_value' => $config->get('login_behavior') ?? 'register_and_login',
      '#description' => $this->t('Choose whether to allow registration and login, or restrict to login only for existing accounts.'),
    ];

    // Email domain restrictions for corporate environments.
    // Comma-separated list, case-insensitive matching.
    // Empty = allow all domains.
    $form['auth_behavior']['allowed_domains'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Allowed Domains'),
      '#default_value' => $config->get('allowed_domains'),
      '#description' => $this->t('Enter the email domains that are allowed to register/login.')
      . ' ' . $this->t('You can enter them comma-separated or one per line.')
      . ' ' . $this->t('Leave empty to allow all domains.')
      . ' ' . $this->t('Examples: <code>example.com, another-domain.com</code> or on separate lines.'),
    ];

    // Security settings group for privileged account protection.
    $form['security'] = [
      '#type' => 'details',
      '#title' => $this->t('Security Settings'),
      '#open' => TRUE,
      '#description' => $this->t('<strong>Important:</strong> Review these security settings carefully before enabling SSO authentication. These settings protect privileged accounts from SSO-based attacks.'),
    ];

    // Prevent root admin (UID 1) from using SSO.
    // SECURITY: Recommended to prevent account takeover attacks.
    // Default: enabled.
    $form['security']['block_user_1'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Block User 1 (root user) from logging in via Entra ID'),
      '#default_value' => $config->get('block_user_1') ?? TRUE,
      '#description' => $this->t('Recommended: Prevent the root administrator account (user ID 1) from authenticating via Entra ID. This protects against SSO-based attacks on the most privileged account.'),
    ];

    // Prevent all administrator role users from using SSO.
    // SECURITY: Optional, for high-security environments.
    // Default: enabled (as per config/install).
    $form['security']['block_admin_role'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Block users with Administrator role from logging in via Entra ID'),
      '#default_value' => $config->get('block_admin_role') ?? TRUE,
      '#description' => $this->t('Prevent any user with the Administrator role from authenticating via Entra ID. Admins must use traditional username/password login.'),
    ];

    return parent::buildForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   *
   * Saves all configuration values to config storage.
   * Special handling for client_secret to preserve existing value when empty.
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $config = $this->config('social_auth_entra_id.settings');

    // Save all form values to configuration.
    $config->set('client_id', $form_state->getValue('client_id'))
      ->set('tenant_id', $form_state->getValue('tenant_id'))
      ->set('account_type', $form_state->getValue('account_type'))
      ->set('login_behavior', $form_state->getValue('login_behavior'))
      ->set('allowed_domains', $form_state->getValue('allowed_domains'))
      ->set('block_user_1', $form_state->getValue('block_user_1'))
      ->set('block_admin_role', $form_state->getValue('block_admin_role'));

    // SECURITY: Only update client_secret if a new value is provided.
    // Password fields return empty on re-submit, so preserve existing value.
    $client_secret = $form_state->getValue('client_secret');
    if (!empty($client_secret)) {
      $config->set('client_secret', $client_secret);
    }

    $config->save();

    parent::submitForm($form, $form_state);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc