PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 4.16.3
GiveWP – Donation Plugin and Fundraising Platform v4.16.3
4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / src / DonorDashboards / Routes / LoginRoute.php
give / src / DonorDashboards / Routes Last commit date
Captcha 4 years ago LoginRoute.php 3 weeks ago LogoutRoute.php 4 years ago PasswordResetRoute.php 2 years ago VerifyEmailRoute.php 4 years ago
LoginRoute.php
154 lines
1 <?php
2
3 namespace Give\DonorDashboards\Routes;
4
5 use Give\API\RestRoute;
6 use WP_REST_Request;
7 use WP_REST_Response;
8
9 /**
10 * @since 2.10.0
11 */
12 class LoginRoute implements RestRoute
13 {
14
15 /** @var string */
16 protected $endpoint = 'donor-dashboard/login';
17
18 /**
19 * @inheritDoc
20 */
21 public function registerRoute()
22 {
23 register_rest_route(
24 'give-api/v2',
25 $this->endpoint,
26 [
27 [
28 'methods' => 'POST',
29 'callback' => [$this, 'handleRequest'],
30 'permission_callback' => '__return_true',
31 ],
32 'args' => [
33 'login' => [
34 'type' => 'string',
35 'required' => true,
36 'sanitize_callback' => 'sanitize_text_field',
37 ],
38 'password' => [
39 'type' => 'string',
40 'required' => true,
41 'sanitize_callback' => 'sanitize_text_field',
42 ],
43 ],
44 ]
45 );
46 }
47
48 /**
49 * Handles login request.
50 *
51 * Authentication is delegated to wp_signon() so that the request runs
52 * through WordPress's `authenticate` filter chain. This lets brute-force
53 * protection plugins (Wordfence, Login LockDown, Jetpack Protect, Solid
54 * Security, etc.) intercept and block attempts, and ensures the core
55 * `wp_login_failed` action fires on failure so plugins that hook it (Limit
56 * Login Attempts, etc.) can count the attempt. Core authentication failures
57 * (wrong password, unknown username/email) return a single generic response
58 * so the endpoint cannot be used to enumerate valid accounts. A lockout from
59 * a protection plugin is surfaced as a 429 with that plugin's message so a
60 * rate-limited user understands why the login was refused.
61 *
62 * @since 4.15.5 Route through wp_signon() and return a generic failure
63 * response to prevent brute-force-protection bypass (CWE-307)
64 * and user enumeration (CWE-204); surface lockout messages as 429.
65 * @since 2.10.0
66 *
67 * @param WP_REST_Request $request
68 *
69 * @return WP_REST_Response
70 */
71 public function handleRequest(WP_REST_Request $request)
72 {
73 $login = $request->get_param('login');
74 $password = $request->get_param('password');
75
76 // wp_signon() runs the `authenticate` filter chain (so lockout plugins
77 // can intercept and block), fires `wp_login_failed` on failure, and sets
78 // the auth cookie on success.
79 $user = wp_signon(
80 [
81 'user_login' => $login,
82 'user_password' => $password,
83 'remember' => false,
84 ]
85 );
86
87 if (is_wp_error($user)) {
88 // Core authentication errors (wrong password, unknown username/email)
89 // are collapsed into a single generic message so the endpoint cannot
90 // be used to enumerate accounts. Any other error code originates from
91 // a brute-force protection plugin (lockout) — surface its message so
92 // a locked-out user understands why the login was refused.
93 $coreAuthErrorCodes = [
94 'incorrect_password',
95 'invalid_username',
96 'invalid_email',
97 'empty_username',
98 'empty_password',
99 ];
100
101 $isLockout = ! in_array($user->get_error_code(), $coreAuthErrorCodes, true);
102
103 // Note: the logical result is returned in the body `status` field and
104 // the HTTP status is left at 200, matching the endpoint's original
105 // contract. The Donor Dashboard front-end reads the result from the
106 // body; returning a non-2xx HTTP status would make its Axios request
107 // reject and leave the form stuck in a loading state.
108 if ($isLockout) {
109 $lockoutMessage = wp_strip_all_tags($user->get_error_message());
110
111 return new WP_REST_Response(
112 [
113 'status' => 429,
114 'response' => 'too_many_attempts',
115 'body_response' => [
116 'message' => '' !== $lockoutMessage
117 ? $lockoutMessage
118 : __('Too many failed login attempts. Please try again later.', 'give'),
119 ],
120 ]
121 );
122 }
123
124 return new WP_REST_Response(
125 [
126 'status' => 401,
127 'response' => 'login_failed',
128 'body_response' => [
129 'message' => __('The provided credentials are invalid.', 'give'),
130 ],
131 ]
132 );
133 }
134
135 // wp_signon() sets the auth cookie and fires `wp_login`, but does not set
136 // the current user for the active request. Set it so the rest of this
137 // request is authenticated, then fire only GiveWP's own hook so existing
138 // integrations keep working, without duplicating the cookie or `wp_login`.
139 wp_set_current_user($user->ID, $user->user_login);
140 do_action('give_log_user_in', $user->ID, $user->user_login, $password);
141
142 return new WP_REST_Response(
143 [
144 'status' => 200,
145 'response' => 'login_successful',
146 'body_response' => [
147 'login' => $user->user_login,
148 'id' => $user->ID,
149 ],
150 ]
151 );
152 }
153 }
154