Skip to content

Commit

Permalink
chore: prepare release (#9)
Browse files Browse the repository at this point in the history
* add readme.txt (for WordPress plugin)
* init README.md (for GitHub)
* use semver
* fix security warnings detected by WrodPress Plugin Check
  • Loading branch information
gao-sun authored Feb 13, 2025
1 parent ee34120 commit f6b4a01
Show file tree
Hide file tree
Showing 14 changed files with 731 additions and 51 deletions.
373 changes: 373 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<p align="center">
<a href="https://logto.io" target="_blank" align="center" alt="Logto Logo">
<img src="https://github.com/logto-io.png" width="100">
</a>
<br/>
<span><i><a href="https://logto.io" target="_blank">Logto</a> is the better auth and identity infrastructure.</i></span>
</p>

# Logto WordPress plugin

This is the official WordPress plugin for [Logto](https://logto.io). It helps you integrate your WordPress site with Logto to enable a single sign-on (SSO) experience for your users.

## Get started

TBD

## Resources

[![Website](https://img.shields.io/badge/website-logto.io-8262F8.svg)](https://logto.io/)
[![Docs](https://img.shields.io/badge/docs-logto.io-green.svg)](https://docs.logto.io/)
[![Discord](https://img.shields.io/discord/965845662535147551?logo=discord&logoColor=ffffff&color=7389D8&cacheSeconds=600)](https://discord.gg/UEPaF3j5e6)
Binary file added assets/screenshot-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshot-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
"autoload": {
"psr-4": {
"Logto\\WpPlugin\\": "src/"
}
},
"files": [
"src/Helpers.php"
]
},
"require": {
"logto/sdk": "^0.3.0"
Expand Down
2 changes: 1 addition & 1 deletion logto.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/*
* Plugin Name: Logto - User Authentication and Authorization
* Description: Enable beautiful and secure user authentication, including passwordless, social login, single sign-on (SSO), multi-factor authentication (MFA). Generic OAuth2, OpenID Connect, SAML are also supported. Use role-based access control (RBAC) to manage user permissions.
* Version: 1.0
* Version: 1.0.0
* Author: Logto
* Author URI: https://logto.io/
* License: MPL-2.0
Expand Down
89 changes: 89 additions & 0 deletions readme.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
=== Logto - User Authentication and Authorization ===
Contributors: logto
Tags: login,sso,saml,oauth,oidc
Requires at least: 6.0.0
Tested up to: 6.7.1
Requires PHP: 8.1
License: MPL-2.0
Stable tag: 1.0.0

Enable beautiful and secure user authentication, including passwordless, social login, single sign-on, multi-factor authentication (MFA), and more.

== Description ==
Thank you for choosing Logto! By integrating Logto into your WordPress site, you are not only enhancing the security and user experience of your site, but also enabling a unified login experience across all your applications.

## Why Logto?

Logto is an open-source Auth0 alternative and a modern authentication and authorization solution for all your applications, including your WordPress sites. With Logto, you can:

- Enable passwordless login, social login, single sign-on (SSO), and multi-factor authentication (MFA) for your WordPress site.
- Use role-based access control (RBAC) to manage user permissions.
- Support generic OAuth2, OpenID Connect, and SAML protocols.
- Customize the login and registration pages to match your brand.

In addition, Logto offers dozens of out-of-the-box integrations with popular social login providers, including Google, GitHub, Entra ID (Azure AD), Facebook, and more. Check out the [full list of built-in integrations and social login providers](https://docs.logto.io/integrations).

## Get started

If you are new to Logto, we recommend checking out our [introduction page](https://docs.logto.io/) to have a quick overview of Logto concepts and features.

If you are looking for a step-by-step guide to set up Logto, please refer to our [WordPress plugin quick start guide](https://docs.logto.io/quick-start/wordpress-plugin).

If you have any questions or feedback, please feel free to:

- [Join our Discord server](https://discord.com/invite/UEPaF3j5e6) to get help from the community.
- [Open an issue on GitHub](https://github.com/logto-io/wordpress/issues) to report bugs or request features.
- [Subscribe to a paid plan](https://logto.io/) to get access to official support and more features.

== Installation ==

## From WordPress admin panel

1. Go to **Plugins** > **Add New**.
2. Search for "Logto".
3. Click **Install Now**.
4. Click **Activate**.
5. Go to **Settings** > **Logto** to configure the plugin.
6. Follow the [quick start guide](https://docs.logto.io/quick-start/wordpress-plugin) to set up Logto.

## From WordPress.org

1. Search for "Logto" in the [WordPress.org plugin directory](https://wordpress.org/plugins/).
2. Download the plugin ZIP file.
3. Go to **Plugins** > **Add New** in your WordPress admin panel.
4. Click **Upload Plugin**.
5. Select the downloaded ZIP file and click **Install Now**.
6. Click **Activate**.
7. Go to **Settings** > **Logto** to configure the plugin.
8. Follow the [quick start guide](https://docs.logto.io/quick-start/wordpress-plugin) to set up Logto.

== Frequently Asked Questions ==

= How to enable passwordless login? =

To enable passwordless login, ensure you have configured one of the passwordless login methods (email or SMS) in the Logto Console and enabled them in the sign-in experience page. For more information, refer to our [Sign-in and sign-up documentation](https://docs.logto.io/end-user-flows/sign-up-and-sign-in).

= How to enable social login? =

To enable social login, ensure you have configured one of the social connectors in the Logto Console and enabled them in the sign-in experience page. For more information, refer to our [Social sign-in documentation](https://docs.logto.io/end-user-flows/sign-up-and-sign-in/social-sign-in).

= How to add an enterprise SSO connection? =

To add an enterprise SSO connection, head to the Logto Console and click on "Enterprise SSO" in the left sidebar. Then, click on "Add enterprise connector" and follow the instructions to configure the connector.

= How to enable multi-factor authentication (MFA)? =

To enable multi-factor authentication (MFA), head to the Logto Console and click on "Multi-factor auth" in the left sidebar. Then, enable the desired MFA methods and configure them as needed.

= How to customize the login and registration pages? =

To customize the login and registration pages, head to the Logto Console and click on "Sign-in experience" in the left sidebar. Then, you can customize the appearance and behavior of the pages as needed.

== Screenshots ==

1. Logto feature overview.
2. Logto sign-in experience configuration.

== Changelog ==

See [Releases](https://github.com/logto-io/wordpress/releases).
15 changes: 15 additions & 0 deletions src/Helpers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php declare(strict_types=1);
namespace Logto\WpPlugin;

function write_log($data): void
{
if (true === WP_DEBUG) {
if (is_array($data) || is_object($data)) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log, WordPress.PHP.DevelopmentFunctions.error_log_print_r
error_log(print_r($data, true));
} else {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
error_log($data);
}
}
}
52 changes: 43 additions & 9 deletions src/LogtoPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Logto\Sdk\LogtoClient;
use Logto\Sdk\Constants\UserScope;
use Logto\WpPlugin\Settings\SettingsSection;

class LogtoPlugin
{
Expand Down Expand Up @@ -69,8 +70,10 @@ function handleLoginForm(): void

parse_str($config->extraParams, $extraParams);

// Overwrite first screen parameter if it's lost password form
// Not processing form, just applying params before redirect.
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if (isset($_GET['action']) && $_GET['action'] === 'lostpassword') {
// Overwrite first screen parameter if it's lost password form
$extraParams['first_screen'] = 'reset_password';
}

Expand All @@ -93,6 +96,8 @@ function handleCallback(): void
return;
}

// Not processing form, `code` is from Logto
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if (isset($_GET["code"])) {
try {
$client = $this->buildClient();
Expand All @@ -116,13 +121,23 @@ function handleCallback(): void
protected function shouldShowWordPressLoginForm(): bool
{
$config = LogtoPluginSettings::get();

// Not processing form, only checking for the parameter
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
return $config->wpFormLogin === WpFormLogin::query->value && isset($_GET['form']) && $_GET['form'] === '1';
}

protected function handleCallbackError(): void
{
$error = $_GET["error"] ?? _x('Unknown error', 'Error title when error is unknown', 'logto');
$errorDescription = $_GET["error_description"] ?? _x('Please try again later or contact the site administrator.', 'Default error description for login failure', 'logto');
// Not processing form, just extracting error
// phpcs:disable WordPress.Security.NonceVerification.Recommended
$error = sanitize_text_field(wp_unslash(
$_GET["error"] ?? _x('Unknown error', 'Error title when error is unknown', 'logto')
));
$errorDescription = sanitize_text_field(wp_unslash(
$_GET["error_description"] ?? _x('Please try again later or contact the site administrator.', 'Default error description for login failure', 'logto')
));
// phpcs:enable WordPress.Security.NonceVerification.Recommended

$this->handleError(
sprintf(
Expand All @@ -138,12 +153,27 @@ protected function handleError(string $title, string $content): void
{
$body = str_starts_with($content, '<') ? $content : "<p>$content</p>";
wp_die(
"<h1>$title</h1><p>$body</p>" .
"<a href='" . wp_login_url() . "'>" . _x('Login again', 'logto') . '</a><br/>' .
"<a href='" . home_url() . "'>" . _x('Back to home', 'logto') . '</a>',
$title,
wp_kses(
sprintf(
'<h1>%s</h1><p>%s</p><a href="%s">%s</a><br/><a href="%s">%s</a>',
wp_kses($title, SettingsSection::allowedTextHtml),
wp_kses($body, SettingsSection::allowedTextHtml),
esc_url(wp_login_url()),
esc_html(_x('Login again', 'Error page', 'logto')),
esc_url(home_url()),
esc_html(_x('Back to home', 'Error page', 'logto'))
),
[
'h1' => [],
'p' => [],
'a' => ['href' => true],
'br' => []
]
),
esc_html($title),
['response' => 400]
);

}

protected function upsertUser(LogtoClient $client): \WP_User
Expand Down Expand Up @@ -171,7 +201,7 @@ protected function upsertUser(LogtoClient $client): \WP_User
) {
$this->handleError(
_x('Unauthorized', 'Error title', 'logto'),
_x('You must be in the specified organization to complete login. Please contact the site administrator.', 'logto')
_x('You must be in the specified organization to complete login. Please contact the site administrator.', 'Error page', 'logto')
);
}

Expand Down Expand Up @@ -253,15 +283,19 @@ function handleProfileUpdateErrors($errors, $update, $user)
{
$pendingEmail = get_user_meta($user->ID, '_new_email', true);

// No need to check nonce, since this function only does the sanity check for the
// profile update form.
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ($pendingEmail) {
$errors->add('email', 'Email cannot be updated.');
delete_user_meta($user->ID, '_new_email');
} else if ($update && isset($_POST['email']) && $_POST['email'] !== $user->user_email) {
$errors->add('email', 'Email cannot be updated.');
}

if ($update && isset($_POST['pass1']) && $_POST['pass1']) {
if ($update && isset($_POST['pass1']) && boolval($_POST['pass1'])) {
$errors->add('password', 'Password cannot be updated.');
}
// phpcs:enable WordPress.Security.NonceVerification.Missing
}
}
25 changes: 16 additions & 9 deletions src/LogtoPluginAdminDashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ public function initMenu(): void
$slug = LogtoConstants::MENU_SLUG;
$settings_page_title = __('Logto Settings', 'logto');
$settings_menu_title = __('Settings', 'logto');
$settings_callback = [$this, 'renderMenu'];
$settings_callback = [$this, 'renderSettings'];
$help_page_title = __('Logto Help', 'logto');
$help_menu_title = __('Help', 'logto');
$help_callback = [$this, 'renderMenu'];
$help_callback = [$this, 'renderHelp'];

add_menu_page(
$settings_page_title,
Expand Down Expand Up @@ -65,13 +65,20 @@ public function initMenu(): void
});
}

public function renderMenu(): void
public function renderSettings(): void
{
include LogtoConstants::PLUGIN_DIR . 'pages/Settings.php';
}

public function renderHelp(): void
{
include LogtoConstants::PLUGIN_DIR . 'pages/Help.php';
}

public function initSettings(): void
{
// Maybe false positive: https://github.com/WordPress/plugin-check/pull/854#issuecomment-2631500035
// phpcs:ignore PluginCheck.CodeAnalysis.SettingSanitization.register_settingDynamic
register_setting(LogtoConstants::OPTION_GROUP, LogtoConstants::OPTION_NAME, [$this, 'validateSettings']);

// Add plain css from string
Expand Down Expand Up @@ -102,8 +109,8 @@ public function initSettings(): void

add_action('admin_notices', [$this, 'renderSettingsErrors']);

error_log('Init settings');
error_log(print_r($this->settings, true));
write_log('Init Logto settings:');
write_log($this->settings);

$basicSettings = new Settings\SettingsSection(
LogtoConstants::MENU_SLUG,
Expand Down Expand Up @@ -148,7 +155,7 @@ public function initSettings(): void
LogtoConstants::MENU_SLUG,
LogtoConstants::OPTION_NAME,
'logto_authentication_settings',
__('Authentication settings'),
__('Authentication settings', 'logto'),
_x('Settings related to user authentication. These settings may affect the user experience.', 'Authentication settings description', 'logto'),
);
$authenticationSettings->render();
Expand Down Expand Up @@ -245,8 +252,8 @@ public function initSettings(): void

public function validateSettings(array $input): array|false
{
error_log('Validating settings');
error_log(print_r($input, true));
write_log('Validating Logto settings:');
write_log($input);

$oldValue = get_option(LogtoConstants::OPTION_NAME, []);

Expand Down Expand Up @@ -282,7 +289,7 @@ public function validateSettings(array $input): array|false
LogtoConstants::OPTION_NAME,
'logto_settings_updated',
__('Settings updated.', 'logto'),
'updated'
'success'
);

return $input;
Expand Down
4 changes: 3 additions & 1 deletion src/LogtoPluginSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ static function get(): self
...get_option(LogtoConstants::OPTION_KEY, [])
);
} catch (\Throwable $e) {
error_log('Failed to get Logto settings: ' . $e->getMessage());
write_log('Failed to get Logto settings: ' . $e->getMessage());
return new self();
}
}
Expand All @@ -45,6 +45,8 @@ public function __construct(
public bool $syncProfile = true,
public string $wpFormLogin = WpFormLogin::query->value,
public string $usernameStrategy = WpUsernameStrategy::smart->value,
// Ignored
...$extra
) {
}

Expand Down
32 changes: 32 additions & 0 deletions src/pages/Help.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php use Logto\WpPlugin\Settings\SettingsSection; ?>
<div class="wrap" style="max-width: 800px;">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<p>
<?php echo wp_kses(_x('Thank you for choosing Logto! By integrating Logto into your WordPress site, you are not only enhancing the security and user experience of your site, but also enabling a unified login experience across all your applications.', 'help', 'logto'), SettingsSection::allowedTextHtml); ?>
</p>
<p>
<?php echo wp_kses(_x('If you are new to Logto, we recommend checking out our <a href="https://docs.logto.io/" target="_blank" rel="noopener">introduction page</a> to have a quick overview of Logto concepts and features.', 'help', 'logto'), SettingsSection::allowedTextHtml); ?>
</p>
<p>
<b>
<?php echo wp_kses(_x('If you are looking for a step-by-step guide to set up Logto, please refer to our <a href="https://docs.logto.io/quick-start/wordpress-plugin" target="_blank" rel="noopener">WordPress plugin quick start guide</a>.', 'help', 'logto'), SettingsSection::allowedTextHtml); ?>
</b>
</p>
<p>
<?php echo wp_kses(_x('If you have any questions or feedback, please feel free to:', 'help', 'logto'), SettingsSection::allowedTextHtml); ?>
</p>
<ul style="list-style: disc; padding-left: 20px;">
<li>
<?php echo wp_kses(_x('<a href="https://discord.com/invite/UEPaF3j5e6" target="_blank" rel="noopener">Join our Discord server</a> to get help from the community.', 'help', 'logto'), SettingsSection::allowedTextHtml); ?>
</li>
<li>
<?php echo wp_kses(_x('<a href="https://github.com/logto-io/wordpress/issues" target="_blank" rel="noopener">Open an issue on GitHub</a> to report bugs or request features.', 'help', 'logto'), SettingsSection::allowedTextHtml); ?>
</li>
<li>
<?php echo wp_kses(_x('<a href="https://logto.io/" target="_blank" rel="noopener">Subscribe to a paid plan</a> to get access to official support and more features.', 'help', 'logto'), SettingsSection::allowedTextHtml); ?>
</li>
</ul>
<p>
<?php echo wp_kses(_x('Hope you enjoy using Logto!', 'help', 'logto'), SettingsSection::allowedTextHtml); ?>
</p>
</div>
Loading

0 comments on commit f6b4a01

Please sign in to comment.