147 | getEnabledProvidersList(); ;
229 |
230 | foreach($enabled as $driver) {
231 |
232 | $id = $this->getProviderClientId($driver);
233 | $secret = $this->getProviderClientSecret($driver);
234 |
235 | if ($id && $secret) {
236 |
237 | $services[$driver] = [
238 | 'name' => $this->getProviderName($driver),
239 | 'client_id' => $id,
240 | 'client_secret' => $secret,
241 | 'redirect' => home_url('fp-auth/socialite/' . strtolower($driver) . '/callback'),
242 | 'icon' => $this->getProviderIcon($driver),
243 | ];
244 |
245 | }
246 |
247 | }
248 |
249 | return $services;
250 | }
251 |
252 | /**
253 | * Add the given authenticated socialiate user to the given or current
254 | * WordPress user; if the given socialite user is already associated
255 | * with a different user account, move it to the given/current one.
256 | * @param String the socialite driver name
257 | * @param Laravel\Socialite\AbstractUser
258 | * @param int Optionally, a user id of a user to attach the social data to
259 | * @return void
260 | * @throws Exception If no user is specified and the current WordPress
261 | * session is not authenticated
262 | */
263 | function addSocialiteUserToWordPressUser($driver, AbstractUser $socialiteUser, $user_id = null)
264 | {
265 | $user = null;
266 | if (empty($user_id)) {
267 | if (!is_user_logged_in()) {
268 | throw new \Exception("WordPress session is not authenticated.");
269 | }
270 | $user = wp_get_current_user();
271 | $user_id = $user->ID;
272 | } else {
273 | if (!$user = get_user_by('ID', $user_id)) {
274 | throw new \Exception("No WordPress user found for given ID");
275 | }
276 | }
277 |
278 | $user_meta_key = $this->getSocialiteUserMetaKey($driver, $socialiteUser);
279 |
280 | $connected = $this->db->table('usermeta')
281 | ->whereNotNull('meta_value')
282 | ->where('user_id', '<>', $user->ID)
283 | ->whereMetaKey($user_meta_key)
284 | ->first();
285 |
286 | if ($connected) {
287 | delete_user_meta($connected->user_id, $user_meta_key);
288 | }
289 |
290 | update_user_meta($user->ID, $user_meta_key, $socialiteUser);
291 | }
292 |
293 | /**
294 | * @return string
295 | */
296 | function getSocialiteUserMetaKey($driver, AbstractUser $socialiteUser)
297 | {
298 | return "_socialite_{$driver}_{$socialiteUser->id}";
299 | }
300 |
301 | /**
302 | * Use the given socialite user to log in an existing WordPress user;
303 | * finding none, create a registration session and return a token for
304 | * retrieving the socialite user later.
305 | * @param String the socialite driver name
306 | * @param Laravel\Socialite\AbstractUser
307 | * @return mixed Either a WP_User or a string: the token for the registration session
308 | * @throws Exception If current WordPress session is already authenticated
309 | */
310 | function loginSocialiteUser($driver, AbstractUser $socialiteUser)
311 | {
312 | if (is_user_logged_in()) {
313 | throw new \Exception("WordPress session is already authenticated.");
314 | }
315 |
316 | // build the meta key from the driver name and the
317 | // the remove unique identifier
318 | $user_meta_key = $this->getSocialiteUserMetaKey($driver, $socialiteUser);
319 |
320 | // look for an existing connection
321 | $connected = $this->db->table('usermeta')
322 | ->whereNotNull('meta_value')
323 | ->whereMetaKey($user_meta_key)
324 | ->first();
325 |
326 | // if already connected, we'll just login
327 | if ($connected) {
328 | // if the user doesn't exist, we need to clean it up
329 | if (!$user = get_user_by('ID', $connected->user_id)) {
330 | delete_user_meta($connection->user_id, $user_meta_key);
331 | return $this->saveSocialiteUserForLater($driver, $socialiteUser);
332 | // otherwise, we log the user in
333 | } else {
334 | wp_set_auth_cookie($user->ID);
335 | do_action('wp_login', $user->user_login, $user);
336 | return $user;
337 | }
338 | // and if they're not connected, we save the session for later
339 | // and (presumably) send the user along to registration
340 | } else {
341 | return $this->saveSocialiteUserForLater($driver, $socialiteUser);
342 | }
343 | }
344 |
345 | /**
346 | * Look for a socialite token in the request; finding one,
347 | * look up the user and attach it to the newly created WordPress
348 | * user account. Also, attach any other meta data from the
349 | * registration form.
350 | *
351 | * @return void
352 | */
353 | function onUserRegister($user_id)
354 | {
355 | if ($token = $this->request->input('socialite')) {
356 | if ($session = $this->getSavedSocialiteUser($token)) {
357 | $this->addSocialiteUserToWordPressUser($session['driver'], $session['user'], $user_id);
358 | }
359 | }
360 | }
361 |
362 | /**
363 | * TODO: add filter
364 | * @return string
365 | */
366 | protected function getSocialiteTransientName($token)
367 | {
368 | return "_socialite_saved_{$token}";
369 | }
370 |
371 | /**
372 | * @return String the session token
373 | */
374 | function saveSocialiteUserForLater($driver, AbstractUser $socialiteUser)
375 | {
376 | $token = wp_generate_password( 43, false, false );
377 |
378 | set_transient($this->getSocialiteTransientName($token), [ 'driver' => $driver, 'user' => $socialiteUser ]);
379 |
380 | return $token;
381 | }
382 |
383 | /**
384 | * @return array with two elements: the driver, and the AbstractUser object
385 | */
386 | function getSavedSocialiteUser($token)
387 | {
388 | return get_transient($this->getSocialiteTransientName($token));
389 | }
390 |
391 |
392 | function forgetSavedSocialiteUser($token)
393 | {
394 | delete_transient($this->getSocialiteTransientName($token));
395 | }
396 |
397 | /**
398 | * This function will be invoked when your plugin is activated.
399 | * @see https://codex.wordpress.org/Function_Reference/register_activation_hook
400 | */
401 | function onActivate()
402 | {
403 |
404 | }
405 |
406 | /**
407 | * This function will be invoked when your plugin is deactivated.
408 | * @see https://codex.wordpress.org/Function_Reference/register_deactivate_hook
409 | */
410 | function onDeactivate()
411 | {
412 |
413 | }
414 |
415 | }
--------------------------------------------------------------------------------
/src/routes.php:
--------------------------------------------------------------------------------
1 | rewrite('/fp-auth/socialite/cancel/{token?}', function($token = null) use ($plugin) {
3 | if (is_null($token)) {
4 | $token = $plugin->request->input('token');
5 | }
6 | $plugin->forgetSavedSocialite($token);
7 | wp_redirect(home_url());
8 | });
9 |
10 | /**
11 | * Provide an endpoint for receiving and processing
12 | * the response from the OAuth service.
13 | */
14 | $router->rewrite('/fp-auth/socialite/{driver}/callback', function($driver) use ($plugin) {
15 | // make sure we're configured to handle this driver
16 | if (!$plugin['config']["services.{$driver}"]) {
17 | // if we're not, tell the user they need to go back and login
18 | wp_die(sprintf(__('