Limit amout of sessions on user-by-user basis?

One user account per person would definitely be easier, but I think you could kind of get this done by playing with the user sessions, which are stored as user_meta with the session_tokens key. Something along these lines maybe.

add_action('template_redirect', 'check_max_num_sessions');
function check_max_num_sessions() {
    // Only check for logged in users
    if ( is_user_logged_in() ) {
        $current_user_id = get_current_user_id();

        // Get user sessions from user_meta
        $user_sessions = user_sessions($current_user_id);

        // Count sessions
        $ongoing_sessions = count_ongoing_sessions(
            $user_sessions
        );

        // Get max num of allowed sessions
        $max_sessions = max_num_sessions(
            $current_user_id
        );

        // Check, if limit exceeded
        if ( $ongoing_sessions > $max_sessions ) {

            // Destroy latest session
            destroy_latest_user_session(
                $current_user_id,
                $user_sessions
            );

            // Or destroy the current session, which may or may not be the latest
            // $session_manager = WP_Session_Tokens::get_instance(
            //  $current_user_id
            // );
            // $session_manager->destroy(
            //  wp_get_session_token()
            // );

            // Redirect user to an error page?
            // wp_redirect(
            //  max_num_sessions_error_page(),
            //  302
            // );
            // exit;
        }
    }

}

function user_sessions(int $user_id) {
    $meta = get_user_meta( $user_id, 'session_tokens', true );
    return is_array($meta) ? $meta : array();
}

function destroy_latest_user_session(int $user_id, array $sessions) {
    array_pop(
        $sessions
    );
    return update_user_meta( $user_id, 'session_tokens', $sessions );
}

function count_ongoing_sessions( array $sessions ) {
    // Time to compare sessions against
    $now = current_time('timestamp');
    // Session counter
    $ongoing_sessions = 0;
    /**
        * Loop current user's sessions
        *
        * @var array $session
        * expiration int timestamp
        * ip string
        * ua (user agent) string
        * login int timestamp
        */
    foreach ($sessions as $session) {
        // Skip expired sessions
        if ( $session['expiration'] < $now ) {
            continue;
        }
        // maybe some user agent checking here, if needed
        // code..
        // Increment counter
        $ongoing_sessions++;
    }
    return $ongoing_sessions;
}

function max_num_sessions( int $user_id ) {
    // Get from database?
    return 15;
}

function max_num_sessions_error_page() {
    return 'http://example.com';
}

I didn’t see a direct way to destroy latest session with WP_Session_Tokens. That’s why I’m getting and updating the meta directly.

There probably should be a redirect after kicking the latest session, because the user will seem to be logged in, after the session meta has been updated, until the user navigates to another page or refreshes the current page and WP checks again the user’s login status.