DrupalOidcIntegration.java
package com.cloudforge.core.oidc;
import com.cloudforge.core.interfaces.Ec2Context;
import com.cloudforge.core.interfaces.OidcConfiguration;
import com.cloudforge.core.interfaces.OidcIntegration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* OIDC integration for Drupal using the native OpenID Connect module.
*
* <p>Drupal has excellent native support for OpenID Connect through
* the contributed openid_connect module. This is one of the most
* mature OIDC implementations in the PHP CMS ecosystem.</p>
*
* <h2>Module Details:</h2>
* <ul>
* <li>Name: OpenID Connect / OAuth client</li>
* <li>URL: https://www.drupal.org/project/openid_connect</li>
* <li>Supports: OAuth 2.0, OpenID Connect, Multiple IdPs</li>
* </ul>
*
* @since 3.1.0
* @see OidcIntegration
*/
public class DrupalOidcIntegration implements OidcIntegration {
private static final String CALLBACK_PATH = "/openid-connect/generic";
@Override
public boolean isSupported() {
return true;
}
@Override
public String getIntegrationMethod() {
return "Native OpenID Connect Module (openid_connect)";
}
@Override
public Map<String, String> getEnvironmentVariables(OidcConfiguration config) {
Map<String, String> env = new HashMap<>();
env.put("DRUPAL_OIDC_CLIENT_ID", config.getClientId());
env.put("DRUPAL_OIDC_AUTHORIZATION_ENDPOINT", config.getAuthorizationEndpoint());
env.put("DRUPAL_OIDC_TOKEN_ENDPOINT", config.getTokenEndpoint());
env.put("DRUPAL_OIDC_USERINFO_ENDPOINT", config.getUserInfoEndpoint());
env.put("DRUPAL_OIDC_END_SESSION_ENDPOINT", config.getLogoutEndpoint());
env.put("DRUPAL_OIDC_SCOPES", config.getScopes() != null ? config.getScopes() : "openid email profile");
return env;
}
@Override
public String getConfigurationFile(OidcConfiguration config) {
return """
<?php
/**
* CloudForge OIDC Configuration for Drupal
* Auto-generated - Do not edit manually
*
* This file is included from settings.php
*/
// OpenID Connect module settings
$config['openid_connect.settings.generic'] = [
'enabled' => TRUE,
'settings' => [
'client_id' => getenv('DRUPAL_OIDC_CLIENT_ID'),
'client_secret' => getenv('DRUPAL_OIDC_CLIENT_SECRET'),
'authorization_endpoint' => getenv('DRUPAL_OIDC_AUTHORIZATION_ENDPOINT'),
'token_endpoint' => getenv('DRUPAL_OIDC_TOKEN_ENDPOINT'),
'userinfo_endpoint' => getenv('DRUPAL_OIDC_USERINFO_ENDPOINT'),
'end_session_endpoint' => getenv('DRUPAL_OIDC_END_SESSION_ENDPOINT'),
'scopes' => explode(' ', getenv('DRUPAL_OIDC_SCOPES') ?: 'openid email profile'),
],
];
// General OpenID Connect settings
$config['openid_connect.settings'] = [
'always_save_userinfo' => TRUE,
'connect_existing_users' => TRUE,
'override_registration_settings' => TRUE,
'userinfo_mappings' => [
'name' => 'preferred_username',
'mail' => 'email',
],
];
""";
}
@Override
public String getConfigurationFilePath() {
return "/var/www/html/sites/default/cloudforge-oidc.settings.php";
}
@Override
public List<String> getUserDataCommands(OidcConfiguration config, Ec2Context context) {
List<String> commands = new ArrayList<>();
commands.add("# Install Drupal OIDC module");
commands.add("echo 'Installing OpenID Connect module...' >> /var/log/userdata.log");
// Install the OpenID Connect module via composer
commands.add("cd /var/www/html && composer require drupal/openid_connect --no-interaction");
// Enable the module via drush
commands.add("drush -r /var/www/html en openid_connect -y");
// Create OIDC configuration file
commands.add("cat > /var/www/html/sites/default/cloudforge-oidc.settings.php << 'OIDC_EOF'");
commands.add("<?php");
commands.add("/**");
commands.add(" * CloudForge OIDC Configuration");
commands.add(" * Auto-generated - Do not edit manually");
commands.add(" */");
commands.add("");
commands.add("$config['openid_connect.settings.generic'] = [");
commands.add(" 'enabled' => TRUE,");
commands.add(" 'settings' => [");
commands.add(" 'client_id' => getenv('DRUPAL_OIDC_CLIENT_ID'),");
commands.add(" 'client_secret' => getenv('DRUPAL_OIDC_CLIENT_SECRET'),");
commands.add(" 'authorization_endpoint' => getenv('DRUPAL_OIDC_AUTHORIZATION_ENDPOINT'),");
commands.add(" 'token_endpoint' => getenv('DRUPAL_OIDC_TOKEN_ENDPOINT'),");
commands.add(" 'userinfo_endpoint' => getenv('DRUPAL_OIDC_USERINFO_ENDPOINT'),");
commands.add(" 'end_session_endpoint' => getenv('DRUPAL_OIDC_END_SESSION_ENDPOINT'),");
commands.add(" ],");
commands.add("];");
commands.add("OIDC_EOF");
// Include the OIDC config in settings.php
commands.add("echo \"\\nif (file_exists(__DIR__ . '/cloudforge-oidc.settings.php')) {\" >> /var/www/html/sites/default/settings.php");
commands.add("echo \" include __DIR__ . '/cloudforge-oidc.settings.php';\" >> /var/www/html/sites/default/settings.php");
commands.add("echo \"}\" >> /var/www/html/sites/default/settings.php");
// Set permissions
commands.add("chown nginx:nginx /var/www/html/sites/default/cloudforge-oidc.settings.php");
commands.add("chmod 644 /var/www/html/sites/default/cloudforge-oidc.settings.php");
// Clear Drupal cache
commands.add("drush -r /var/www/html cr");
commands.add("echo 'Drupal OIDC module configured' >> /var/log/userdata.log");
return commands;
}
@Override
public String getPostDeploymentInstructions() {
return """
Drupal OIDC Integration Setup
=============================
The OpenID Connect module has been installed and configured.
Configuration is managed via environment variables:
- DRUPAL_OIDC_CLIENT_ID: OAuth client ID
- DRUPAL_OIDC_CLIENT_SECRET: OAuth client secret (from Secrets Manager)
- DRUPAL_OIDC_AUTHORIZATION_ENDPOINT: Authorization endpoint
- DRUPAL_OIDC_TOKEN_ENDPOINT: Token endpoint
- DRUPAL_OIDC_USERINFO_ENDPOINT: UserInfo endpoint
- DRUPAL_OIDC_END_SESSION_ENDPOINT: Logout endpoint
To verify setup:
1. Navigate to Drupal admin: /admin/config/people/openid-connect
2. Verify the "Generic OAuth 2.0" client is enabled
3. Test login by visiting /user/login and clicking the OIDC button
User provisioning:
- New users are created automatically on first login
- Existing users are linked by email address
- User roles can be mapped via the module's role mapping feature
Module documentation:
https://www.drupal.org/docs/contributed-modules/openid-connect
Troubleshooting:
- Check /admin/reports/dblog for authentication errors
- Enable verbose logging in module settings
- Verify callback URL is registered in Cognito/IdP
""";
}
@Override
public String getContainerStartupCommand() {
return "/usr/local/bin/docker-php-entrypoint php-fpm";
}
@Override
public String getOidcCallbackPath() {
return CALLBACK_PATH;
}
@Override
public boolean isDistroless() {
return false;
}
@Override
public boolean supportsAlbOidc() {
return true;
}
@Override
public boolean supportsCognito() {
return true;
}
@Override
public boolean supportsIdentityCenterSaml() {
return false;
}
@Override
public String getAuthenticationType() {
return "OIDC";
}
}