-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimplesamlphp_auth.module
More file actions
191 lines (169 loc) · 7.42 KB
/
simplesamlphp_auth.module
File metadata and controls
191 lines (169 loc) · 7.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<?php
/**
* @file
* SimpleSAMLphp authentication module for Drupal.
*
* This authentication module is based on the shibboleth authentication module,
* with changes to adopt to use simpleSAMLphp.
*
* ISSUES and TODOs:
* ISSUE: User is always dropped on user page after login, instead of where
* they were when they clicked "Federated Log In". Because of this, deep
* linking to access controlled content does not work. Usability would
* be considerably increased if this were resolved.
* FYI: Drupal now requires knowledge of the local user password in order to
* change e-mail address, etc. This could be an issue for users of
* accounts that are autoprovisioned by this module, though Drupal does
* give users the ability to reset their password to something they know
* via the Request new password feature.
* KLUDGE: Drupal does not kill the session on logout, even with
* drupal_session_destroy_uid(), so I had to use session_destroy().
*
* @todo Rework the default login limitation logic to use a drupal permission
* rather than a list of UIDs.
* @todo When denying access because the administrator has chosen not to allow
* the module to register/create accounts, the user is told to contact
* the administrator; the message should provide the contact information.
* ISSUE: Until Drupal issue #754560 is resolved users will not see logout
* notices.
*/
use Drupal\Core\Url;
use Drupal\Core\Form\FormStateInterface;
/**
* Implements hook_help().
*/
function simplesamlphp_auth_help($route_name) {
switch ($route_name) {
case 'simplesamlphp_auth.admin_settings':
case 'help.page.simplesamlphp_auth':
$output = t('<p>This module integrates Drupal with a SimpleSAMLphp Service Point (SP), effectively federating Drupal.</p>');
return $output;
}
}
/**
* Implements hook_user_logout().
*/
function simplesamlphp_auth_user_logout($account) {
$logout_url = \Drupal::config('simplesamlphp_auth.settings')->get('logout_goto_url');
$simplesaml = \Drupal::service('simplesamlphp_auth.manager');
// Have to destroy the session here as some configurations of
// SimpleSAMLphp_auth can create infinite loops. By removing IdP auth before
// Drupal auth, checks for local authentication will trigger before the
// session is destroyed naturally. We must therefore destroy the session
// manually here.
session_destroy();
if ($logout_url) {
$simplesaml->logout($logout_url);
}
else {
$simplesaml->logout();
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Alters the user register form to include a checkbox signifying the user
* should be SimpleSAML enabled. Removes password fields if the IdP
* is the sole place for password management.
*
* @see AccountForm::form()
* @see simplesamlphp_auth_user_form_submit()
*/
function simplesamlphp_auth_form_user_form_alter(&$form, FormStateInterface $form_state, $form_id) {
simplesamlphp_auth_user_form_includes($form);
$authmap = \Drupal::service('externalauth.authmap');
// If the user has a simplesamlphp_auth authmap record, then don't require
// them to know their Drupal password. This will allow them to change their
// e-mail address, and set a Drupal password if they want to
// (and are allowed).
$account = $form_state->getFormObject()->getEntity();
$saml_enabled = $authmap->get($account->id(), 'simplesamlphp_auth');
if ($saml_enabled) {
$form['simplesamlphp_auth_user_enable']['#default_value'] = TRUE;
$form['account']['current_pass']['#access'] = FALSE;
// If the user is a simplesamlphp_auth user and is NOT allowed to set their
// Drupal password, remove the fields from the form.
$config = \Drupal::config('simplesamlphp_auth.settings');
if (!$config->get('allow.set_drupal_pwd')) {
$form['account']['pass']['#access'] = FALSE;
}
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Alters the user register form to include a checkbox signifying the user
* should be SimpleSAML enabled.
*
* @see AccountForm::form()
* @see simplesamlphp_auth_user_form_submit()
*/
function simplesamlphp_auth_form_user_register_form_alter(&$form, FormStateInterface $form_state, $form_id) {
simplesamlphp_auth_user_form_includes($form);
$form['simplesamlphp_auth_user_enable']['#default_value'] = TRUE;
}
/**
* Helper function to include the SimpleSAML checkbox on user forms.
*
* @param array $form
* The user account form.
*
* @see simplesamlphp_auth_form_user_form_alter()
* @see simplesamlphp_auth_form_user_register_form_alter()
* @see simplesamlphp_auth_user_form_submit()
*/
function simplesamlphp_auth_user_form_includes(&$form) {
$form['simplesamlphp_auth_user_enable'] = array(
'#type' => 'checkbox',
'#title' => t('Enable this user to leverage SAML authentication'),
'#access' => \Drupal::currentUser()->hasPermission('change saml authentication setting'),
'#description' => t("WARNING: if unchecked, this will become a local Drupal user, which might be denied access based on the SimpleSAMLphp settings for authenticating local Drupal accounts.<br />Don't use this setting for access control, which should be configured in your IdP instead.<br />NOTE: if the configuration option 'Automatically enable SAML authentication for existing users upon successful login' is activated, this Drupal account can become linked with SAML (again) when the user succesfully authenticates to the IdP."),
);
// We store the authname as the initial email. If we're using SimpleSAML we
// need to enforce an email address.
$form['account']['mail']['#required'] = TRUE;
$form['actions']['submit']['#submit'][] = 'simplesamlphp_auth_user_form_submit';
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function simplesamlphp_auth_form_user_login_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Return without executing if the functionality is not enabled.
if (!\Drupal::config('simplesamlphp_auth.settings')->get('activate')) {
return;
}
$label = Drupal::config('simplesamlphp_auth.settings')->get('login_link_display_name');
$form['simplesamlphp_auth_login_link'] = array(
'#markup' => \Drupal::l($label, new Url('simplesamlphp_auth.saml_login', array(), array(
'attributes' => array(
'class' => array('simplesamlphp-auth-login-link'),
),
))),
);
}
/**
* Form submission handler for user_form.
*
* @see simplesamlphp_auth_form_user_register_form_alter()
* @see simplesamlphp_auth_form_user_form_alter()
*/
function simplesamlphp_auth_user_form_submit($form, FormStateInterface $form_state) {
$authmap = \Drupal::service('externalauth.authmap');
$externalauth = \Drupal::service('externalauth.externalauth');
// Add an authmap entry for this account, so it can leverage SAML
// authentication.
if ($form_state->getValue('simplesamlphp_auth_user_enable')) {
$account = $form_state->getFormObject()->getEntity();
// Link an authmap entry to this account, if not yet existing.
// By default, we use the username as authname.
// This can be altered if needed. See simplesamlphp_auth.api.php for
// details.
$authname = $account->getAccountName();
\Drupal::modulehandler()->alter('simplesamlphp_auth_account_authname', $authname, $account);
$externalauth->linkExistingAccount($authname, 'simplesamlphp_auth', $account);
}
// Remove this user from the ExternalAuth authmap table.
else {
$authmap->delete($form_state->getValue('uid'));
}
}