source: http-authentication/trunk/http-authentication.php @ 487647

Revision 487647, 7.4 KB checked in by dwc, 4 weeks ago (diff)

Update CSS to correctly center login button on WordPress 3.3

Line 
1<?php
2/*
3Plugin Name: HTTP Authentication
4Version: 4.4
5Plugin URI: http://danieltwc.com/2011/http-authentication-4-0/
6Description: Authenticate users using basic HTTP authentication (<code>REMOTE_USER</code>). This plugin assumes users are externally authenticated, as with <a href="http://www.gatorlink.ufl.edu/">GatorLink</a>.
7Author: Daniel Westermann-Clark
8Author URI: http://danieltwc.com/
9*/
10
11require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'options-page.php');
12
13class HTTPAuthenticationPlugin {
14        var $db_version = 1;
15        var $option_name = 'http_authentication_options';
16        var $options;
17
18        function HTTPAuthenticationPlugin() {
19                $this->options = get_option($this->option_name);
20
21                if (is_admin()) {
22                        $options_page = new HTTPAuthenticationOptionsPage(&$this, $this->option_name, __FILE__, $this->options);
23                        add_action('admin_init', array(&$this, 'check_options'));
24                }
25
26                add_action('login_head', array(&$this, 'add_login_css'));
27                add_action('login_footer', array(&$this, 'add_login_link'));
28                add_action('check_passwords', array(&$this, 'generate_password'), 10, 3);
29                add_action('wp_logout', array(&$this, 'logout'));
30                add_filter('login_url', array(&$this, 'bypass_reauth'));
31                add_filter('show_password_fields', array(&$this, 'allow_wp_auth'));
32                add_filter('allow_password_reset', array(&$this, 'allow_wp_auth'));
33                add_filter('authenticate', array(&$this, 'authenticate'), 10, 3);
34        }
35
36        /*
37         * Check the options currently in the database and upgrade if necessary.
38         */
39        function check_options() {
40                if ($this->options === false || ! isset($this->options['db_version']) || $this->options['db_version'] < $this->db_version) {
41                        if (! is_array($this->options)) {
42                                $this->options = array();
43                        }
44
45                        $current_db_version = isset($this->options['db_version']) ? $this->options['db_version'] : 0;
46                        $this->upgrade($current_db_version);
47                        $this->options['db_version'] = $this->db_version;
48                        update_option($this->option_name, $this->options);
49                }
50        }
51
52        /*
53         * Upgrade options as needed depending on the current database version.
54         */
55        function upgrade($current_db_version) {
56                $default_options = array(
57                        'allow_wp_auth' => false,
58                        'auth_label' => 'HTTP authentication',
59                        'login_uri' => htmlspecialchars_decode(wp_login_url()),
60                        'logout_uri' => remove_query_arg('_wpnonce', htmlspecialchars_decode(wp_logout_url())),
61                        'auto_create_user' => false,
62                        'auto_create_email_domain' => '',
63                );
64
65                if ($current_db_version < 1) {
66                        foreach ($default_options as $key => $value) {
67                                // Handle migrating existing options from before we stored a db_version
68                                if (! isset($this->options[$key])) {
69                                        $this->options[$key] = $value;
70                                }
71                        }
72                }
73        }
74
75        function add_login_css() {
76?>
77<style type="text/css">
78p#http-authentication-link {
79        width: 100%;
80    height: 4em;
81    text-align: center;
82    margin-top: 2em;
83}
84p#http-authentication-link a {
85    margin: 0 auto;
86    float: none;
87}
88</style>
89<?php
90        }
91
92        /*
93         * Add a link to the login form to initiate external authentication.
94         */
95        function add_login_link() {
96                global $redirect_to;
97
98                $login_uri = $this->_generate_uri($this->options['login_uri'], wp_login_url($redirect_to));
99                $auth_label = $this->options['auth_label'];
100
101                echo "\t" . '<p id="http-authentication-link"><a class="button-primary" href="' . htmlspecialchars($login_uri) . '">Log In with ' . htmlspecialchars($auth_label) . '</a></p>' . "\n";
102        }
103
104        /*
105         * Generate a password for the user. This plugin does not require the
106         * administrator to enter this value, but we need to set it so that user
107         * creation and editing works.
108         */
109        function generate_password($username, $password1, $password2) {
110                if (! $this->allow_wp_auth()) {
111                        $password1 = $password2 = wp_generate_password();
112                }
113        }
114
115        /*
116         * Logout the user by redirecting them to the logout URI.
117         */
118        function logout() {
119                $logout_uri = $this->_generate_uri($this->options['logout_uri'], home_url());
120
121                wp_redirect($logout_uri);
122                exit();
123        }
124
125        /*
126         * Remove the reauth=1 parameter from the login URL, if applicable. This allows
127         * us to transparently bypass the mucking about with cookies that happens in
128         * wp-login.php immediately after wp_signon when a user e.g. navigates directly
129         * to wp-admin.
130         */
131        function bypass_reauth($login_url) {
132                $login_url = remove_query_arg('reauth', $login_url);
133
134                return $login_url;
135        }
136
137        /*
138         * Can we fallback to built-in WordPress authentication?
139         */
140        function allow_wp_auth() {
141                return (bool) $this->options['allow_wp_auth'];
142        }
143
144        /*
145         * Authenticate the user, first using the external authentication source.
146         * If allowed, fall back to WordPress password authentication.
147         */
148        function authenticate($user, $username, $password) {
149                $user = $this->check_remote_user();
150
151                if (! is_wp_error($user)) {
152                        // User was authenticated via REMOTE_USER
153                        $user = new WP_User($user->ID);
154                }
155                else {
156                        // REMOTE_USER is invalid; now what?
157
158                        if (! $this->allow_wp_auth()) {
159                                // Bail with the WP_Error when not falling back to WordPress authentication
160                                wp_die($user);
161                        }
162
163                        // Fallback to built-in hooks (see wp-includes/user.php)
164                }
165
166                return $user;
167        }
168
169        /*
170         * If the REMOTE_USER or REDIRECT_REMOTE_USER evironment variable is set, use it
171         * as the username. This assumes that you have externally authenticated the user.
172         */
173        function check_remote_user() {
174                $username = '';
175
176                foreach (array('REMOTE_USER', 'REDIRECT_REMOTE_USER') as $key) {
177                        if (isset($_SERVER[$key])) {
178                                $username = $_SERVER[$key];
179                        }
180                }
181
182                if (! $username) {
183                        return new WP_Error('empty_username', '<strong>ERROR</strong>: No REMOTE_USER or REDIRECT_REMOTE_USER found.');
184                }
185
186                // Create new users automatically, if configured
187                $user = get_userdatabylogin($username);
188                if (! $user)  {
189                        if ((bool) $this->options['auto_create_user']) {
190                                $user = $this->_create_user($username);
191                        }
192                        else {
193                                // Bail out to avoid showing the login form
194                                $user = new WP_Error('authentication_failed', __('<strong>ERROR</strong>: Invalid username or incorrect password.'));
195                        }
196                }
197
198                return $user;
199        }
200
201        /*
202         * Create a new WordPress account for the specified username.
203         */
204        function _create_user($username) {
205                $password = wp_generate_password();
206                $email_domain = $this->options['auto_create_email_domain'];
207
208                require_once(WPINC . DIRECTORY_SEPARATOR . 'registration.php');
209                $user_id = wp_create_user($username, $password, $username . ($email_domain ? '@' . $email_domain : ''));
210                $user = get_user_by('id', $user_id);
211
212                return $user;
213        }
214
215        /*
216         * Fill the specified URI with the site URI and the specified return location.
217         */
218        function _generate_uri($uri, $redirect_to) {
219                // Support tags for staged deployments
220                $base = $this->_get_base_url();
221
222                $tags = array(
223                        'host' => $_SERVER['HTTP_HOST'],
224                        'base' => $base,
225                        'site' => home_url(),
226                        'redirect' => $redirect_to,
227                );
228
229                foreach ($tags as $tag => $value) {
230                        $uri = str_replace('%' . $tag . '%', $value, $uri);
231                        $uri = str_replace('%' . $tag . '_encoded%', urlencode($value), $uri);
232                }
233
234                // Support previous versions with only the %s tag
235                if (strstr($uri, '%s') !== false) {
236                        $uri = sprintf($uri, urlencode($redirect_to));
237                }
238
239                return $uri;
240        }
241
242        /*
243         * Return the base domain URL based on the WordPress home URL.
244         */
245        function _get_base_url() {
246                $home = parse_url(home_url());
247                $base = str_replace(array($home['path'], $home['query'], $home['fragment']), '', home_url());
248
249                return $base;
250        }
251}
252
253// Load the plugin hooks, etc.
254$http_authentication_plugin = new HTTPAuthenticationPlugin();
255?>
Note: See TracBrowser for help on using the repository browser.