insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery AgentAdapt_Schema::table( 'tokens' ), array( 'token_hash' => hash( 'sha256', $token ), 'session_id' => $session_id, 'kind' => 'session', 'scope' => $scope, 'user_id' => $user_id, 'jkt' => '' === $jkt ? null : $jkt, 'resource' => '' === $jkt && '' !== $resource ? $resource : null, 'expires' => time() + self::SESSION_TTL, ) ); return array( 'token' => $token, 'expires_in' => self::SESSION_TTL ); } /** * A live token record, or null. * * @param string $token Presented token. * @return array|null */ public static function find( string $token ): ?array { global $wpdb; if ( ! str_starts_with( $token, 'agc_st_' ) || strlen( $token ) > 128 ) { return null; } $t = AgentAdapt_Schema::table( 'tokens' ); $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM %i WHERE token_hash = %s", $t, hash( 'sha256', $token ) ), ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery if ( ! $row || (int) $row['expires'] < time() ) { return null; } return $row; } /** * Delete every token of these Sessions (Session, browser and handoff * tokens alike) and every token signed in to the account (WordPress's * personal-data eraser), so nothing keeps working for them. * * @param string[] $session_ids Sessions. * @param int $user_id Account. * @return int Tokens deleted. */ public static function delete_for( array $session_ids, int $user_id ): int { global $wpdb; $t = AgentAdapt_Schema::table( 'tokens' ); $n = $user_id > 0 ? (int) $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE user_id = %d', $t, $user_id ) ) : 0; // phpcs:ignore WordPress.DB.DirectDatabaseQuery foreach ( array_chunk( array_values( array_filter( array_map( 'strval', $session_ids ) ) ), 200 ) as $chunk ) { // phpcs:disable WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,PluginCheck.Security.DirectDB.UnescapedDBParameter -- one %s placeholder per Session; the table name is %i. $n += (int) $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE session_id IN (' . implode( ',', array_fill( 0, count( $chunk ), '%s' ) ) . ')', array_merge( array( $t ), $chunk ) ) ); // phpcs:enable } return $n; } /** * Delete expired tokens. */ public static function purge(): void { global $wpdb; $t = AgentAdapt_Schema::table( 'tokens' ); $wpdb->query( $wpdb->prepare( "DELETE FROM %i WHERE expires < %d", $t, time() ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery } }