Completed
Push — update-wpcom-block-editor-same... ( 15fe2b )
by Kirk
09:41 queued 03:13
created

samesite-cookies.php ➔ wp_set_auth_cookie()   C

Complexity

Conditions 8
Paths 96

Size

Total Lines 119

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 96
nop 4
dl 0
loc 119
rs 6.7555
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file handles updating authentication cookies to be compatible with the `SameSite=None` attribute.
4
 * https://web.dev/samesite-cookies-explained/
5
 *
6
 * This file is loaded only if connected to WP.com.
7
 *
8
 * @package Jetpack
9
 */
10
11
/**
12
 * A PHP 5.X compatible version of the array argument version of PHP 7.3's setcookie().
13
 *
14
 * Useful for setting SameSite cookies in PHP 7.2 or earlier.
15
 *
16
 * @param string $name    Name of the cookie.
17
 * @param string $value   Value of the cookie.
18
 * @param array  $options Options to include with the cookie.
19
 * @return bool False when error happens, other wise true.
20
 */
21
function jetpack_shim_setcookie( $name, $value, $options ) {
22
	$not_allowed_chars = ",; \t\r\n\013\014";
23
24
	if ( strpbrk( $name, $not_allowed_chars ) !== false ) {
25
		return false;
26
	}
27
28
	$cookie = 'Set-Cookie: ' . $name . '=' . rawurlencode( $value ) . '; ';
29
30
	foreach ( $options as $k => $v ) {
31
		if ( 'expires' === $k && ! empty( $v ) ) {
32
			$cookie_date = gmdate( 'D, d M Y H:i:s \G\M\T', $v );
33
			$cookie     .= sprintf( 'expires=%s', $cookie_date ) . ';';
34
		} elseif ( 'secure' === $k && true === $v ) {
35
			$cookie .= 'secure; ';
36
		} elseif ( 'httponly' === $k && true === $v ) {
37
			$cookie .= 'HttpOnly; ';
38
		} elseif ( 'domain' === $k && is_string( $v ) && ! empty( $v ) ) {
39
			if ( strpbrk( $v, false !== $not_allowed_chars ) ) {
40
				return false;
41
			}
42
			$cookie .= sprintf( 'domain=%s', $v . '; ' );
43
		} elseif ( 'path' === $k && is_string( $v ) && ! empty( $v ) ) {
44
			if ( strpbrk( $v, false !== $not_allowed_chars ) ) {
45
				return false;
46
			}
47
			$cookie .= sprintf( 'path=%s', $v . '; ' );
48
		} elseif ( 'samesite' === $k && is_string( $v ) && ! empty( $v ) ) {
49
			$cookie .= sprintf( 'SameSite=%s', $v . '; ' );
50
		}
51
	}
52
53
	$cookie = trim( $cookie );
54
	$cookie = trim( $cookie, ';' );
55
	header( $cookie, false );
56
57
	return true;
58
}
59
60
if ( ! function_exists( 'wp_set_auth_cookie' ) ) :
61
	/**
62
	 * Sets the authentication cookies based on user ID.
63
	 *
64
	 * The $remember parameter increases the time that the cookie will be kept. The
65
	 * default the cookie is kept without remembering is two days. When $remember is
66
	 * set, the cookies will be kept for 14 days or two weeks.
67
	 *
68
	 * This overrides the `wp_set_auth_cookie` pluggable function in order to support `SameSite` cookies.
69
	 *
70
	 * @param int    $user_id  User ID.
71
	 * @param bool   $remember Whether to remember the user.
72
	 * @param mixed  $secure   Whether the admin cookies should only be sent over HTTPS.
73
	 *                         Default is the value of is_ssl().
74
	 * @param string $token    Optional. User's session token to use for this cookie.
75
	 *
76
	 * @since 8.2
77
	 */
78
	function wp_set_auth_cookie( $user_id, $remember = false, $secure = '', $token = '' ) {
79
		if ( $remember ) {
80
			/** This filter is documented in wp-includes/pluggable.php */
81
			$expiration = time() + apply_filters( 'auth_cookie_expiration', 14 * DAY_IN_SECONDS, $user_id, $remember );
82
83
			/*
84
			 * Ensure the browser will continue to send the cookie after the expiration time is reached.
85
			 * Needed for the login grace period in wp_validate_auth_cookie().
86
			 */
87
			$expire = $expiration + ( 12 * HOUR_IN_SECONDS );
88
		} else {
89
			/** This filter is documented in wp-includes/pluggable.php */
90
			$expiration = time() + apply_filters( 'auth_cookie_expiration', 2 * DAY_IN_SECONDS, $user_id, $remember );
91
			$expire     = 0;
92
		}
93
94
		if ( '' === $secure ) {
95
			$secure = is_ssl();
96
		}
97
98
		// Front-end cookie is secure when the auth cookie is secure and the site's home URL is forced HTTPS.
99
		$secure_logged_in_cookie = $secure && 'https' === wp_parse_url( get_option( 'home' ), PHP_URL_SCHEME );
100
101
		/** This filter is documented in wp-includes/pluggable.php */
102
		$secure = apply_filters( 'secure_auth_cookie', $secure, $user_id );
103
104
		/** This filter is documented in wp-includes/pluggable.php */
105
		$secure_logged_in_cookie = apply_filters( 'secure_logged_in_cookie', $secure_logged_in_cookie, $user_id, $secure );
106
107
		if ( $secure ) {
108
			$auth_cookie_name = SECURE_AUTH_COOKIE;
109
			$scheme           = 'secure_auth';
110
		} else {
111
			$auth_cookie_name = AUTH_COOKIE;
112
			$scheme           = 'auth';
113
		}
114
115
		if ( '' === $token ) {
116
			$manager = WP_Session_Tokens::get_instance( $user_id );
117
			$token   = $manager->create( $expiration );
118
		}
119
120
		$auth_cookie      = wp_generate_auth_cookie( $user_id, $expiration, $scheme, $token );
121
		$logged_in_cookie = wp_generate_auth_cookie( $user_id, $expiration, 'logged_in', $token );
122
123
		/** This filter is documented in wp-includes/pluggable.php */
124
		do_action( 'set_auth_cookie', $auth_cookie, $expire, $expiration, $user_id, $scheme, $token );
125
126
		/** This filter is documented in wp-includes/pluggable.php */
127
		do_action( 'set_logged_in_cookie', $logged_in_cookie, $expire, $expiration, $user_id, 'logged_in', $token );
128
129
		/** This filter is documented in wp-includes/pluggable.php */
130
		if ( ! apply_filters( 'send_auth_cookies', true ) ) {
131
			return;
132
		}
133
134
		/**
135
		 * Filters the SameSite attribute to use in auth cookies.
136
		 *
137
		 * @param string $samesite SameSite attribute to use in auth cookies.
138
		 *
139
		 * @since 8.2
140
		 */
141
		$samesite = apply_filters( 'jetpack_auth_cookie_samesite', 'Lax' );
142
143
		jetpack_shim_setcookie(
144
			$auth_cookie_name,
145
			$auth_cookie,
146
			array(
147
				'expires'  => $expire,
148
				'path'     => PLUGINS_COOKIE_PATH,
149
				'domain'   => COOKIE_DOMAIN,
150
				'secure'   => $secure,
151
				'httponly' => true,
152
				'samesite' => $samesite,
153
			)
154
		);
155
156
		jetpack_shim_setcookie(
157
			$auth_cookie_name,
158
			$auth_cookie,
159
			array(
160
				'expires'  => $expire,
161
				'path'     => ADMIN_COOKIE_PATH,
162
				'domain'   => COOKIE_DOMAIN,
163
				'secure'   => $secure,
164
				'httponly' => true,
165
				'samesite' => $samesite,
166
			)
167
		);
168
169
		jetpack_shim_setcookie(
170
			LOGGED_IN_COOKIE,
171
			$logged_in_cookie,
172
			array(
173
				'expires'  => $expire,
174
				'path'     => COOKIEPATH,
175
				'domain'   => COOKIE_DOMAIN,
176
				'secure'   => $secure_logged_in_cookie,
177
				'httponly' => true,
178
				'samesite' => $samesite,
179
			)
180
		);
181
182
		if ( COOKIEPATH !== SITECOOKIEPATH ) {
183
			jetpack_shim_setcookie(
184
				LOGGED_IN_COOKIE,
185
				$logged_in_cookie,
186
				array(
187
					'expires'  => $expire,
188
					'path'     => SITECOOKIEPATH,
189
					'domain'   => COOKIE_DOMAIN,
190
					'secure'   => $secure_logged_in_cookie,
191
					'httponly' => true,
192
					'samesite' => $samesite,
193
				)
194
			);
195
		}
196
	}
197
endif;
198