Skip to content

Commit 5a7a14c

Browse files
authored
Add files via upload
0 parents  commit 5a7a14c

File tree

1 file changed

+255
-0
lines changed

1 file changed

+255
-0
lines changed

wp-saml-auth-uw.php

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
<?php
2+
/**
3+
* Plugin Name: WP SAML Auth for UW
4+
* Version: 0.0.0
5+
*
6+
*/
7+
8+
define('WP_SAML_AUTH_UW_GROUP_STEM', 'uw_asa_it_web');
9+
10+
function wpsax_filter_option( $value, $option_name ) {
11+
$defaults = array(
12+
/**
13+
* Type of SAML connection bridge to use.
14+
*
15+
* 'internal' uses OneLogin bundled library; 'simplesamlphp' uses SimpleSAMLphp.
16+
*
17+
* Defaults to SimpleSAMLphp for backwards compatibility.
18+
*
19+
* @param string
20+
*/
21+
'connection_type' => 'internal',
22+
/**
23+
* Configuration options for OneLogin library use.
24+
*
25+
* See comments with "Required:" for values you absolutely need to configure.
26+
*
27+
* @param array
28+
*/
29+
'internal_config' => array(
30+
// Validation of SAML responses is required.
31+
'strict' => true,
32+
'debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
33+
'baseurl' => home_url(),
34+
'sp' => array(
35+
'entityId' => network_site_url('sp'),
36+
'assertionConsumerService' => array(
37+
'url' => site_url('wp-login.php'),
38+
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
39+
),
40+
// 'x509cert' => file_get_contents(ABSPATH . '/private/sp.crt'),
41+
// 'privateKey' => file_get_contents(ABSPATH . '/private/sp.key'),
42+
// 'x509certNew' => file_get_contents(ABSPATH . '/private/sp-new.crt'),
43+
),
44+
'idp' => array(
45+
// Required: Set based on provider's supplied value.
46+
'entityId' => 'urn:mace:incommon:washington.edu',
47+
'singleSignOnService' => array(
48+
// Required: Set based on provider's supplied value.
49+
'url' => 'https://idp.u.washington.edu/idp/profile/SAML2/Redirect/SSO',
50+
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
51+
),
52+
'singleLogoutService' => array(
53+
// Required: Set based on provider's supplied value.
54+
'url' => 'https://idp.u.washington.edu/idp/logout',
55+
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
56+
),
57+
// Required: Contents of the IDP's public x509 certificate.
58+
// Use file_get_contents() to load certificate contents into scope.
59+
'x509cert' => file_get_contents(ABSPATH . '/private/uw-idp-md-cert.pem'),
60+
// Optional: Instead of using the x509 cert, you can specify the fingerprint and algorithm.
61+
'certFingerprint' => '',
62+
'certFingerprintAlgorithm' => '',
63+
),
64+
),
65+
/**
66+
* Path to SimpleSAMLphp autoloader.
67+
*
68+
* Follow the standard implementation by installing SimpleSAMLphp
69+
* alongside the plugin, and provide the path to its autoloader.
70+
* Alternatively, this plugin will work if it can find the
71+
* `SimpleSAML_Auth_Simple` class.
72+
*
73+
* @param string
74+
*/
75+
'simplesamlphp_autoload' => dirname( __FILE__ ) . '/simplesamlphp/lib/_autoload.php',
76+
/**
77+
* Authentication source to pass to SimpleSAMLphp
78+
*
79+
* This must be one of your configured identity providers in
80+
* SimpleSAMLphp. If the identity provider isn't configured
81+
* properly, the plugin will not work properly.
82+
*
83+
* @param string
84+
*/
85+
'auth_source' => 'default-sp',
86+
/**
87+
* Whether or not to automatically provision new WordPress users.
88+
*
89+
* When WordPress is presented with a SAML user without a
90+
* corresponding WordPress account, it can either create a new user
91+
* or display an error that the user needs to contact the site
92+
* administrator.
93+
*
94+
* @param bool
95+
*/
96+
'auto_provision' => true,
97+
/**
98+
* Whether or not to permit logging in with username and password.
99+
*
100+
* If this feature is disabled, all authentication requests will be
101+
* channeled through SimpleSAMLphp.
102+
*
103+
* @param bool
104+
*/
105+
'permit_wp_login' => ($_GET['saml_sso'] === 'false' ? true : false),
106+
/**
107+
* Attribute by which to get a WordPress user for a SAML user.
108+
*
109+
* @param string Supported options are 'email' and 'login'.
110+
*/
111+
'get_user_by' => 'login',
112+
/**
113+
* SAML attribute which includes the user_login value for a user.
114+
*
115+
* @param string
116+
*/
117+
'user_login_attribute' => 'urn:oid:0.9.2342.19200300.100.1.1', // 'uid', 'uwNetID'
118+
/**
119+
* SAML attribute which includes the user_email value for a user.
120+
*
121+
* @param string
122+
*/
123+
'user_email_attribute' => 'urn:oid:0.9.2342.19200300.100.1.3', // 'mail', 'email'
124+
/**
125+
* SAML attribute which includes the display_name value for a user.
126+
*
127+
* @param string
128+
*/
129+
'display_name_attribute' => 'urn:oid:2.5.4.3', // 'cn'
130+
/**
131+
* SAML attribute which includes the first_name value for a user.
132+
*
133+
* @param string
134+
*/
135+
'first_name_attribute' => 'urn:oid:2.5.4.42', // 'givenName'
136+
/**
137+
* SAML attribute which includes the last_name value for a user.
138+
*
139+
* @param string
140+
*/
141+
'last_name_attribute' => 'urn:oid:2.5.4.4', // 'surname'
142+
/**
143+
* Default WordPress role to grant when provisioning new users.
144+
*
145+
* @param string
146+
*/
147+
'default_role' => get_option( 'default_role' ),
148+
);
149+
$value = isset( $defaults[ $option_name ] ) ? $defaults[ $option_name ] : $value;
150+
return $value;
151+
}
152+
add_filter( 'wp_saml_auth_option', 'wpsax_filter_option', 10, 2 );
153+
154+
function custom_query_vars_filter($vars) {
155+
$vars[] .= 'saml_sso';
156+
return $vars;
157+
}
158+
add_filter( 'query_vars', 'custom_query_vars_filter' );
159+
160+
add_action( 'login_form', function() {
161+
if (get_query_var('saml_sso')) {
162+
?><input type="text" name="saml_sso" value="false" /><?php
163+
}
164+
});
165+
166+
167+
/*
168+
* Return an associative array of groups, indexed by role
169+
*/
170+
function site_role_groups() {
171+
$domain = parse_url(site_url(), PHP_URL_HOST);
172+
173+
/**
174+
* reduce the hostname down to just the first section, after removing prefixes like "dev." or "test."
175+
*/
176+
$site = preg_replace('/^((dev|test)\.)/', '', $domain);
177+
$site = preg_replace('/\..*/', '', $site);
178+
179+
$site_stem = WP_SAML_AUTH_UW_GROUP_STEM.'_'.$site;
180+
181+
$role_map = array();
182+
foreach (wp_roles()->role_names as $role => $name) {
183+
$role_map[$role] = $site_stem.'_'.$role;
184+
}
185+
return $role_map;
186+
}
187+
188+
/*
189+
* Return the super admin group
190+
*/
191+
function super_admin_group() {
192+
return WP_SAML_AUTH_UW_GROUP_STEM.'_admin';
193+
}
194+
195+
/*
196+
* Add user to roles according to the groups given in attributes
197+
*/
198+
function add_user_roles( $user, $attributes ) {
199+
$groups_attribute = 'urn:oid:1.3.6.1.4.1.5923.1.5.1.1';
200+
if (!($user_groups = $attributes[$groups_attribute])) {
201+
return;
202+
}
203+
204+
if (in_array('urn:mace:washington.edu:groups:' . super_admin_group(), $user_groups)) {
205+
grant_super_admin($user->ID);
206+
} else {
207+
revoke_super_admin($user->ID);
208+
}
209+
210+
foreach (site_role_groups() as $role => $uw_group) {
211+
if (in_array('urn:mace:washington.edu:groups:'.$uw_group, $user_groups)) {
212+
$user->add_role($role);
213+
} else {
214+
$user->remove_role($role);
215+
}
216+
}
217+
}
218+
add_action( 'wp_saml_auth_existing_user_authenticated', 'add_user_roles', 10, 2);
219+
add_action( 'wp_saml_auth_new_user_authenticated', 'add_user_roles', 10, 2);
220+
221+
add_action( 'admin_menu', function() {
222+
add_options_page(
223+
__( 'WP SAML Auth UW Settings', 'wp-saml-auth-uw' ),
224+
__( 'WP SAML Auth UW', 'wp-saml-auth-uw' ),
225+
'manage_options',
226+
'wp-saml-auth-uw-settings',
227+
function() {
228+
$config = apply_filters( 'wp_saml_auth_option', null, 'internal_config' );
229+
$groups = site_role_groups();
230+
?>
231+
<div class="wrap">
232+
<h2><?php esc_html_e( 'WP SAML Auth UW Settings', 'wp-saml-auth-uw' ); ?></h2>
233+
<h2>Service Provider Settings</h2>
234+
<p>Ensure this metadata is present in the UW Service Provider Registry:</p>
235+
<table class="form-table" role="presentation">
236+
<tr><th scope="row">Entity Id</th>
237+
<td><input readonly="readonly" type="text" class="regular-text" value="<?= $config['sp']['entityId'] ?>" /></td></tr>
238+
<tr><th scope="row">Assertion Consumer Service URL</th>
239+
<td><input readonly="readonly" type="text" class="regular-text" value="<?= $config['sp']['assertionConsumerService']['url'] ?>" /></td></tr>
240+
</table>
241+
<h2>Role Mapping</h2>
242+
<p>Roles will be granted based on membership in these UW Groups:</p>
243+
<table class="form-table" role="presentation">
244+
<tr><th scope="row">Super Admin</th>
245+
<td><input readonly="readonly" type="text" class="regular-text" value="<?= super_admin_group() ?>" /></td></tr>
246+
<?php foreach (wp_roles()->get_names() as $role => $name): ?>
247+
<tr><th scope="row"><?= $name ?></th>
248+
<td><input readonly="readonly" type="text" class="regular-text" value="<?= $groups[$role] ?>" /></td></tr>
249+
<?php endforeach; ?>
250+
</table>
251+
</div>
252+
<?php
253+
}
254+
);
255+
});

0 commit comments

Comments
 (0)