This is more or less straight-forward in its approach, but first a little back up documentation:

You might want to take a moment to read through the above links …

The basic concept here is to create a function which will return the login form as a string and then use that as the callable function of the shortcode.

Let’s start with the callable function and the add_shortcode call:

function wpfa_login_form() {
    /** ... */
} /** End function - WPFA login form */
add_shortcode( 'wpfa_login', 'wpfa-Login_form' );

OK, now let’s add in the wp_login_form call (using the defaults as shown in the codex … feel free to go back and read the linked page above if you need a refresher):

function wpfa_login_form( $args ) {

    $args = array(
        'echo'              => true,
        'redirect'          => site_url( '/wp-admin/' ),
        'form_id'           => 'loginform',
        'label_username'    => __( 'Username' ),
        'label_password'    => __( 'Password' ),
        'label_remember'    => __( 'Remember Me' ),
        'label_log_in'      => __( 'Log In' ),
        'id_username'       => 'user_login',
        'id_password'       => 'user_pass',
        'id_remember'       => 'rememberme',
        'id_submit'         => 'wp-submit',
        'remember'          => true,
        'value_username'    => NULL,
        'value_remember'    => false
    );

    wp_login_form( $args );

} /** End function - WPFA login form */
add_shortcode( 'wpfa_login', 'wpfa_login_form' );

This is fine but no where near finished. We still need to add the shortcode attributes and also have the wp_login_form parameters be available as shortcode parameters. Let’s add some code to our function:

function wpfa_login_form( $args ) {

    $defaults = shortcode_atts( array(
        'echo'              => true,
        'redirect'          => site_url( '/wp-admin/' ),
        'form_id'           => 'loginform',
        'label_username'    => __( 'Username' ),
        'label_password'    => __( 'Password' ),
        'label_remember'    => __( 'Remember Me' ),
        'label_log_in'      => __( 'Log In' ),
        'id_username'       => 'user_login',
        'id_password'       => 'user_pass',
        'id_remember'       => 'rememberme',
        'id_submit'         => 'wp-submit',
        'remember'          => true,
        'value_username'    => NULL,
        'value_remember'    => false
    ), $args, 'wpfa_login' );

    $login_args = wp_parse_args( $args, $defaults );

    wp_login_form( $login_args );

} /** End function - WPFA login form */
add_shortcode( 'wpfa_login', 'wpfa_login_form' );

So, what did we just do? We added the shortcode attributes functionality (shortcode_atts); the wp_login_form parameters where written to $defaults which was parsed into $login_args which in turn was passed to the wp_login_form function.

OK, were done … or, are we? Go ahead and give the above a try. You should be able to copy and paste this into a basic plugin or the functions.php file of your active (test site?) theme. Use the [wpfa_login] shortcode in either a text widget (see the Extra Code below if your theme or current plugins do not offer support for the use of a shortcode in text widgets … applying it will be your challenge) or a post/page of your choice.

Now, if you are testing this in a post with existing content you will see the login form is being displayed at the top of the “post”. This is due to the add_shortcode function behaving in the same manner as a call made by the add_filter function. So, let’s tweak this code one more time by first changing the default echo parameter to false and then we will return the wp_login_form output so the shortcode can do the heavy lifting of properly outputting the form. We will also add in relatively appropriate textodmain information to more correctly implement i18n standards.

function wpfa_login_form( $args ) {

    $defaults = shortcode_atts( array(
        'echo'              => false,
        'redirect'          => site_url( '/wp-admin/' ),
        'form_id'           => 'loginform',
        'label_username'    => __( 'Username', 'wpfa-textdomain' ),
        'label_password'    => __( 'Password', 'wpfa-textdomain' ),
        'label_remember'    => __( 'Remember Me', 'wpfa-textdomain' ),
        'label_log_in'      => __( 'Log In', 'wpfa-textdomain' ),
        'id_username'       => 'user_login',
        'id_password'       => 'user_pass',
        'id_remember'       => 'rememberme',
        'id_submit'         => 'wp-submit',
        'remember'          => true,
        'value_username'    => NULL,
        'value_remember'    => false
    ), $args, 'wpfa_login' );

    $login_args = wp_parse_args( $args, $defaults );

    return wp_login_form( $login_args );

} /** End function - WPFA login form */
add_shortcode( 'wpfa_login', 'wpfa_login_form' );

Now, each of the parameters of the wp_login_form will work as a parameter of the [wpfa_login] shortcode, for example, if you wanted to change the submit button label from Log In to Show Me The Way then you would simply use the following shortcode [wpfa_login label_log_in="Show Me The Way"].

You can also get a copy of this code snippet here: https://gist.github.com/Cais/5522696

You can also get this code as part of the BNS Login plugin from the WordPress Extend Plugins repository, too.

To see the Extra Code click here.To hide the Extra Code click here.
        /** Add Shortcode functionality to text widgets */
        add_action( 'widget_text', 'do_shortcode' );


To see the Correction click here.To hide the Correction click here.
Thanks to Georgios Pyrgiotakis for noticing the typo in the code. A correction has been made to the examples.

To see the Update click here.To hide the Update click here.
Updated July 29, 2013 to add new shortcode dynamic filter parameter to the `shortcode_atts()` function call.