Display Password Protected external RSS in wordpress template

I assume you mean fetching an external feed with an HTTP authentication.

Fetching feeds with HTTP Authentication

Note that fetch_rss() uses the MagPie library, that’s deprecated in WordPress.

Use instead fetch_feed() that uses the SimplePie library.

It looks though it doesn’t support this kind of url:

http://user:[email protected]/feed/

like we can use with curl in command-line, e.g.:

# curl -i http://user:[email protected]/feed/

The fetch_feed() function calls the wp_safe_remote_request() function, to fetch the feed. This is happens in the WP_SimplePie_File class, that’s an extension of the SimplePie_File class.

That’s good news, because it means we can use the http_request_args filter, to modify the request headers. If we check out the Codex page on the HTTP API, we see that in the external references, that there’s a link to John Blackbourn’s short but informative post about Basic Authentication with the WordPress HTTP API. There he gives the following example:

$args = array(
    'headers' => array(
        'Authorization' => 'Basic ' . base64_encode( YOUR_USERNAME . ':' . YOUR_PASSWORD )
    )
);
wp_remote_request( $url, $args );

to send the correct authentication header with the request.

Demo plugin

We can now add a support for the following url type:

$rss = fetch_feed( 'http://user:[email protected]/feed/' );

with the this demo plugin:

<?php
/**
 * Plugin Name: Fetch Feeds with http authentication
 * Description: Allows feeds urls like http://user:[email protected]/feed/
 * Plugin URI:  http://wordpress.stackexchange.com/a/199101/26350
 */    
add_action( 'wp_feed_options', function( $feed, $url )
{
    $user = parse_url( $feed->feed_url, PHP_URL_USER );
    $pass = parse_url( $feed->feed_url, PHP_URL_PASS );

    // Nothing to do
    if( ! $user || ! $pass )
        return;

    // Remove the user:pass@ part from the feed url
    $feed->feed_url = str_replace( 
        sprintf( '%s:%s@', $user, $pass ), 
        '', 
        $feed->feed_url
    );

    add_filter( 'http_request_args', function( $r, $url ) use ( $user, $pass )
    {
        // Add the user & pass to the request's header
        if( $user && $pass )
            $r['headers']['Authorization'] = 'Basic ' . base64_encode(  $user . ':' . $pass );
        return $r;
    }, 10, 2 );     

}, 10, 2 );

Update:

This is how the error looks like:

WP HTTP Error: A valid URL was not provided.

when we run:

$rss = fetch_feed( 'http://user:[email protected]/feed/' );

It comes from the WP_Http::request() method:

if ( empty( $url ) || empty( $arrURL['scheme'] ) )
    return new WP_Error('http_request_failed', __('A valid URL was not provided.'));

Here’s how the wp_safe_remote_request() function is defined:

function wp_safe_remote_request( $url, $args = array() ) {
        $args['reject_unsafe_urls'] = true;
        $http = _wp_http_get_object();
        return $http->request( $url, $args );
}

I was just playing with it and tested:

$args['reject_unsafe_urls'] = false;

through:

add_action( 'wp_feed_options', function( $feed )
{
    $user = parse_url( $feed->feed_url, PHP_URL_USER );
    $pass = parse_url( $feed->feed_url, PHP_URL_PASS );

    if( ! $user || ! $pass )
        return;

    add_filter( 'http_request_args', function( $r, $url ) use ( $user, $pass )
    {
        if( $user && $pass )
            $r['reject_unsafe_urls'] = false;
        return $r;
    }, 10, 2 );     
} );

and then this worked:

$rss = fetch_feed( 'http://user:[email protected]/feed/' );

Inside the WP_Http::request() method we got this condition:

if ( $r['reject_unsafe_urls'] )
    $url = wp_http_validate_url( $url );

so it looks like wp_http_validate_url() is not validating this url:

http://user:[email protected]/feed/

By setting reject_unsafe_urls to false, we skip that check.

There’s actually a filter available for this: http_request_reject_unsafe_urls, but I wouldn’t recommend using:

add_filter( `http_request_reject_unsafe_urls`, '__return_false' );

I think the demo plugin above, would in general be a better choice, because it still uses the wp_http_validate_url() on the auth stripped url.

Note:

This part:

if ( isset( $parsed_url['user'] ) || isset( $parsed_url['pass'] ) )
    return false;

within the wp_http_validate_url() function , seems to be the show-stopper for fetch_feed() for urls with user:pass.