User only/protected pages in WordPress

Here is some fairly simple code for restricting pages only to logged in users in WordPress. Just give me the code |

First, you have to set up a template for the page. You create templates for pages by adding some code at the top of the page, like so:

< ? php /* Template Name: NameOfTemplatePage */ ?>
Then toss in the rest of your template and upload it to your site. It should look something like this: template example. Next, you have to assign the template to the page that you want. Edit the page you want to assign the template to. On the right you’ll see a drop down called “Page Template”. It will not show up onscreen until you have created at least one page template and put it in your template directory. In this case, we would choose the template called “NameOfTemplatePage”. Okay, now comes the fun part, we need to restrict access to the content on this page to users who are logged in. First, we need to find out if they are logged in. We can do that fairly simply:
< ? php
// is the user logged in?
global $userdata;
get_currentuserinfo();
//assign it a variable
$validuser = $userdata->ID;
//if the user is logged in, the $validuser variable will have an ID assigned to it, so check to see if it is empty
if ($validuser != '') { ?>

[UPDATE] As Dan MacTough pointed out below, the above code could be replaced with:
< ? php if (is_user_logged_in()) { ?>
I wasn’t aware of that function, so I wrote it using a php variable instead. Either way works so take your pick. (Thanks Dan!)[/UPDATE]

If the user is logged in (i.e. if $validuser has a value and isn’t blank), then show them the logged in user content. We want to choose the name of the content to show them based on the post slug of the page, in this case, “nameoftemplatepage”. You can do this code below to choose the post you want, but only if it is a mainlevel page, it will not work if the page is a sub-page of another page. If you do not use the code below, you can use the template for multiple pages in the event you wanted to protect multiple pages (on the same level).
< ? php
// show them the nameoftemplatepage page
// grab the appropriate page that we want "nameoftemplatepage"
query_posts('pagename=nameoftemplatepage');
?>

Then you toss in the normal loop for grabbing content. I’ve stripped the divs and header tags out of here so it shows up as code.
< ? php if (have_posts()) : ?>
< ? php while (have_posts()) : the_post(); ?>
< ? php the_title(); ?>
< ? php the_content('Read the rest of this entry »'); ?>
< ? php edit_post_link('Edit', '', ''); ?>
< ? php endwhile; ?>
< ? php else : ?>
Not Found Sorry, but you are looking for something that isn't here. < ? php include (TEMPLATEPATH . "/searchform.php"); ?>
< ? php endif; ?>

Then we need to give the alternate content to the user, in my case, I used a login form.
< ? php } else {
// they aren't logged in, so show them the login form
?>
You need to log in to access this content.
Login form goes here
< ? php } ?>

Since WordPress keeps trying to process the form code even though it’s within code tags, you can click on this link to see the full document in php: protected page example.

60 Responses to “User only/protected pages in WordPress”

  1. Benoît says:

    Hi,
    How do you do to display the source code in your post ? You use a plugin ?

  2. Ben says:

    Benoît,

    I use a plugin called Preserve Code Formatting. You can find it here:
    http://www.coffee2code.com/wp-plugins/#preservecodeformatting.

  3. Benoît says:

    OK. Thank you. ;)

  4. matt says:

    What is the difference between protected and private posts/pages?

  5. Ben says:

    Matt,

    The difference is that the page is still accessible in the navigation for people who are not logged in, they just see the login form (or whatever content you put in that place) rather than the nothing they see with a private page. You can see an example of what I’m talking about here:

    Here is a private page I created on my personal/experiment blog:
    http://www.minc.info/?page_id=108

    Here is a page using the example I outlined in the above:
    http://www.minc.info/nameoftemplatepage/

    Even if you log in as a subscriber, you can’t see the link or content of the first page, whereas you can always see the link and some sort of content (even if it’s just a prompt for a login) on the secured page. If you want to check it out fully, you can log in using user: test pass: testing

    I guess you could use the Role Manager plugin to allow people to access those private pages as subscribers. My method doesn’t require that you have that plugin installed though. You could distribute a template with a page template included that would allow people to restrict access to any page on their site to only logged in users without a plugin. I guess this post isn’t about this being the only way to restrict access to a page, there may be others. There are a few plugins out that that restrict access to blog posts, but I couldn’t find one to restrict access to a page, which is why I came up with this.

    [UPDATE]
    Ok, so I just tested it with the Role Manager plugin. You can give access to the private pages, but the private pages aren’t added as links to the navigation (at least in three templates that I tried out) so you’d have to provide a link manually or through some other page or post.

  6. Dan MacTough says:

    I’ve done this, too. Any reason you don’t use is_user_logged_in() or even better yet, auth_redirect()?

  7. Ben says:

    Dan,

    I didn’t use is_user_logged_in() because I didn’t know about that function. It can easily be modified to use that instead.

    I didn’t use the auth_redirect because I was setting it up so a user wouldn’t see the default wordpress login. The WordPress login is fine, unless you want to style it differently. The only way is to alter the actual login page file which makes upgrading the site a pain.

    Another reason not to do it via auth_redirect is that it’s a bit disconcerting for a user to click on a link to a page and suddenly end up at a login, particularly one that looks nothing like your site design. People who are web savvy will probably understand, but noobies and people who don’t know what WordPress is will be confused. In my method, it looks and acts just like your normal site, you can put some intro text explaining why people have to log in, and then present them with a login form.

    And, as I said in a previous comment:
    “I guess this post isn’t about this being the only way to restrict access to a page, there may be others. There are a few plugins out that that restrict access to blog posts, but I couldn’t find one to restrict access to a page, which is why I came up with this.”

  8. Simonne says:

    The code is working great, thank you for sharing it. However, I encounter a problem: in the case of a non logged in visitor, after he provides the credentials and presses Login, instead of being redirected to the current page (now without the login form), he is redirected to /path/wp-login.php (which does not exist, because wp-login.php is in the root directory). Do you know what I do wrong?

    Thank you so much!

  9. David says:

    Hi Ben,

    This is great stuff, but I am having some difficulty implementing it on my site. Perhaps you can help an php novice out?

    I want to restrict my photos page to registered and logged in users. This is perfect. I am using the Flickr Photo Album Plugin by TanTanNoodles, and have been able to insert your code around the template page used for the gallery this plugin produces.

    When I try to login, however, something is not communicating as it doesn’t refresh to the photos page, or indicate anything registered. The login page generated by your code refreshes.

    Am I missing something? I’ll send the code I’m using if that’d help.

    Anyway, great work, and thanks for any help.

    David

  10. Ben says:

    Simonne,

    Make sure you have a hidden input field in your login form that has the redirect back to the page they came from like so:
    < ?php //use a hidden field to return them to the page they came from ?>

    " />

    If you could send me a link to the page you’re working on I’ll be happy to take a look at it.

  11. Ben says:

    David,

    Please send me a url and your code and I’ll be happy to take a look at it. You can email me at ben(-at-)redwingstudio.com.

  12. Simonne says:

    I solved the error meanwhile, thanks for your answer. It was in the beginning of the code: I had to add a series of ../ before wp-login.php, to indicate the relative path to the file. I needed to have the login form only on certain deep pages of the site and not on the front page. Now it is working great. The next step will be to hack the login form, because I need to get a lot of information from subscribers (I very much doubt that anybody will subscribe under these circumstances, but the client is very keen on having a very detailed submission form).

  13. Ben says:

    Simonne,

    Great! Glad to hear that. Good luck with the login form. ;)

  14. Ben says:

    Based on David and Simonne’s experience, I need to post this FYI which is now included in the dowload:

    !!! IMPORTANT !!! If you are using permalinks to rewrite the urls of your site, you will need to adjust the action of the login form. The form will look for the wp-login.php file based on the action. If the rewritten url of your page is:
    http://www.yourdomain.com/your_page_name/,
    you will need to change the action in the form to

    action='../wp-login.php'
    so it will look in the ‘directory’ above /your_page_name/ for the wp-login file. Depending on your url structure, you may have to go up several directories. For instance, if your page is located at:
    http://www.yourdomain.com/some_section/your_page_name/
    you will need to change the action to

    action='../../wp-login.php'

    Ignore the above. To get around the path issue to wp-login.php, just be sure you use this:
    < ?php bloginfo('url'); ?>/wp-login.php
    With that code in there, you won’t have to adjust the path on the action portion of the form.

  15. slamp0 says:

    I might be being dense here. If so please excuse me. But will this code/plugin actually deny access to certain pages? I mean, if someone, anyone, registers and supplies a user name & address then they can read the page contents. Right? Or can you choose to accept or deny registrations?

    Thanks for clearing this up for me.

  16. Ben says:

    slamp0.

    Yes, the code will enable you to deny access to certain pages. Only people who have a username/password will be able to log in and see the page. If you want to choose to accept or deny registrations, you’ll need to change your membership settings on your General options page. Uncheck the ‘Anyone can register’ checkbox and save your settings. Then I’d put something like “If you want to become a member and have access to this page, please email me” or you could put some sort of contact form there for them to fill out. Then go and create their accounts yourself. If you’re looking for a contact form to use, you might try Contact Form ][ available here: http://chip.cuccio.us/projects/contact-form-ii/

    Unfortunately, WP doesn’t have the option for people to submit registrations and then allow you to choose to accept or deny them before they would have access to the members only page. You could open it up so anyone can register and then delete the people you don’t want (of course, they can always register under a different username) or you can do what I mentioned above.

    Hope that answers your question. If not, if you can give me more info about what you’re wanting to do, I’ll be happy to try to help.

  17. Ryan says:

    Does this work in wordpress 2.21?

    I used the full code, gave it a unique template name, changed the page I wanted it to point to (to it’s correct page slug) and assigned it to the other page I want viewers to go to access it.

    Unfortunately I keep getting the “Not Found” spew, instead of showing the page.
    My install is on the root directory, so I dunno… Would it complicate things if the page i want shown is a sub page with a parent?

  18. Ryan says:

    OK, I figured it out it doesn’t like pages that have parents. (e.g. sub pages)

  19. Ben says:

    Ah, was just replying to you. :) I’m guessing you were using permalinks?

  20. Ryan says:

    I think so… (?page_id=#) type system.

  21. Ryan says:

    Is there any way to route the page to display a sub page from page slugs?
    Something like:

  22. Ryan says:

    Oops, sorry for so many comments…
    I left out the last part of my previous post.

    “Is there any way to route the page to display a sub page from page slugs?
    Something like: parent-page — child-page”

  23. Ben says:

    Ryan,

    Do you mean once someone has logged in to route he/she from the login page (parent) to a sub-page (child) automatically? If that’s what you’re trying to do you’ll just need to change the redirect hidden field in the form:
    Change this (which redirects them back to the page they came from):

    " />

    to:

    where /path/to/page is the url that you want to send the user to.

  24. Ben says:

    Ryan,

    I’ve read back through your comments and this may be something you are running into:

    If you are using permalinks to rewrite the urls of your site, you will need to adjust the action of the login form. The form will look for the wp-login.php file based on the action. If the rewritten url of your page is http://www.yourdomain.com/your_page_name/, you will need to change the action in the form to
    action='../wp-login.php'
    so it will look in the ‘directory’ above /your_page_name/ for the wp-login file. Depending on your url structure, you may have to go up several directories.
    For instance, if your page is located at http://www.yourdomain.com/some_section/your_page_name/ you will need to change the action to

    action='../../wp-login.php'
    In your case, if your child page is the one where the login is, you may have to set it to
    action='../../wp-login.php'
    even if you aren’t using permalinks to rewrite your urls to SEO friendly urls.
    SEO friendly permalinks would look something like: http://www.yourdomain.com/category/title/ instead of http://www.yourdomain.com/?p=35
    WordPress may recognize though that because it’s a child page the call to wp-login.php needs to go up two directories anyway.
    If you want to send me the url of the page you’re applying the login form, i’ll be happy to take a look at it.

    Ignore the above. To get around the path issue to wp-login.php, just be sure you use this:
    < ?php bloginfo('url'); ?>/wp-login.php
    With that code in there, you won’t have to adjust the path on the action portion of the form.

    Ben

  25. Ryan says:

    My site is located in the root directory so I have no need to change the wp-login.php action location…

    I’m just saying that this solution does not work with pages that are a child of another page from within wordpress… (You know when you select a parent for a page to the right so that it does not show up in the navigation.)

  26. Ben says:

    Ryan,

    To fix the problem, simply comment out the query_posts('pagename=yourpageslug');

    Wordpress apparently won’t allow you to run the query_posts template tag from a sub-page for some reason. Commenting out that line worked fine for me as you can see here: http://www.minc.info/nameoftemplatepage/moretesting/

    BTW, even if your site is located in the root directory (as it is at http://www.minc.info/nameoftemplatepage/ above) you will still need to adjust the wp-login.php action based on how your permalinks are set up. If you aren’t using the default WordPress page setup where your urls look like http://somesite.com/?p=5 you will need to adjust the wp-login function. For example, my wp-login code for this page: http://www.minc.info/nameoftemplatepage/ is action='../wp-login.php' My wp-login code for http://www.minc.info/nameoftemplatepage/moretesting/ is action='../../wp-login.php'

    Ignore the above. To get around the path issue to wp-login.php, just be sure you use this:
    < ?php bloginfo('url'); ?>/wp-login.php
    With that code in there, you won’t have to adjust the path on the action portion of the form.

  27. Lauren-Noelle says:

    This works soo beautifully. (The site I’m setting it up on is not ready yet, and I don’t have a domain name for my new design “co.” so no link here.)

    I just have to note that it will not work with pages already set to private, I was confused by that. This sets them private themselves, and you do not need the post levels plugin. (Unless you want the teaser that can give, I THINK.)

    Also you can set the link to the login script to include your domain name instead of worrying about ../../, I noticed it had my domain in the main login page code, so I decided to try that for the ease of making more pages.

    I changed the look of the login, too, with the help of the styling I did with two other plugins.

    I plan to come back to show off my work when it’s ready!

    GREAT TEMPLATE PAGE! It’s neat how it’s not even a plugin. GOOD JOB! THANKS!

    –Elle

  28. Lauren-Noelle says:

    Btw, I don’t usually comment on plugin entries, but I’m really impressed here! It’s amazing how simple this is, and it was really necessary, but no one else did it.

    Exceptional!

  29. Ben says:

    Elle,

    I’m glad you’ve found it helpful. Good idea on the login script using the domain name. ;) Please get back to us with a url as I’d love to see it when you’re done.

    Ben

  30. Jeff says:

    Thank you sooo much for this I’d been looking for a simple way to have a page be members only. And after inastalling several different plugins that only protected post, I stubled upon this one and had it running in less then 5 minutes. The only thing that didn’t work was the custom login form you made to display for non users, this is fine cause I meant to modify it anyways.

    A simple and effective solution was to add, login and register links to users who are not looged in.

  31. Felipe says:

    Hi Ben, i’ve been reading through the comments to see if anyone talked about what i’m looking for, but no luck yet, so i’ll ask u directly.

    What i’m trying to do is to have different users (password protected users) and protect some pages. Pretty much what ur plugin does

    The thing is i need to give access only to 1 page per user, without them seeing other users protected pages.

    I need to do this, so I can have a private channel with my clients where we can exchange information, such as pictures (i work doing 3d animations) and commenting them, but i don’t want that every user i give a username / password can see the work i’m doing with other people…

    Hope u can help me…
    thanks.

  32. Ben says:

    Felipe,

    Let me give it some thought and I’ll get back to you.

    Ben

  33. Ben says:

    Felipe,

    Ok, I think I have what you need. You might have to customize it a bit more to do exactly what you want, but here’s the proof of concept example: http://www.ben-huddleston.com/separate-protected-pages/

    Try logging in as user: test, password: testing. It will give you some static html that I wrote into that page template. Then, try logging in as user: blar, password: blah. You’ll get a different page called “photos” that is pulled out of the database (you can see the photos page link in the sidebar as well).

    Here’s how I did it:

    I created the Separate Protected Pages page in the admin and assigned the Separate Protected Pages page template to it (I simply renamed the user only/protected page template I downloaded from above). I put in some dummy text on the Separate Protected page in case I have a user that has a login, but I don’t have anything special for them. You can check that out by logging in as user: homer, password: doh! (include the exclamation point in password).

    Ok, then I needed to add some code to my page template so it would show different content to the different users. In the existing code, you can see the following code:

    get_currentuserinfo();
    //echo('Username: ' . $userdata->user_login . '
    ');

    The echo line that is commented out will tell you who you are logged in as. So, it was fairly simple to assign a variable to the user login info:

    $theuser = $userdata->user_login;

    So, now that I have a variable with the user’s login name, I can do a comparison and then show appropriate content:


    < ?php if ($theuser == 'admin') { ? >

    Welcome Admin, nice to see you. Here's a bunch of content for you. Blah blah blah blah blah.

    < ? php } ? >

    The above code will welcome the admin and spit out that text in the paragraph tags. From there on out, it’s simply a matter of checking against the different user names and sending them different content:

    < ?php
    // admin user
    if ($theuser == 'admin') { ?>

    Welcome Admin, nice to see you. Here's a bunch of content for you. Blah blah blah blah blah.

    < ?php
    // another static html example
    // test user
    ? >
    < ?php } else if ($theuser == 'test') { ? >

    Welcome test, nice to see you as well. Here's your content.

    < ?php } ? >

    Which is all great and good, except what if you want to pull the content out of another WordPress page (that isn’t in your nav links). Well, you can simply add a query_posts call before your normal WordPress loop to pull the content you want. In this example, I’m pulling content from a page with a page slug of “photos”:


    < ?php
    // non-static example that pulls the content from a wordpress page.
    // blar user
    ? >
    < ?php } else if ($theuser == 'blar') { ? >
    < ?php query_posts('pagename=photos'); // pulls the photos page, change to your page slug ? >
    < ?php if (have_posts()) : ? >
    < ?php while (have_posts()) : the_post(); ? >

    < ?php the_title(); ? >

    < ?php the_content('Read the rest of this entry »'); ? >

    < ?php endwhile; ? >
    < ?php else : ? >

    Not Found

    Sorry, but you are looking for something that isn't here.

    < ?php include (TEMPLATEPATH . "/searchform.php"); ? >
    < ?php endif; ? >

    < ?php } ? >

    That’s pretty much it. Here’s a link to the full source code so you can see it:
    http://www.ben-huddleston.com/documents/sep-protected-pages.phps

    And if you want to download it, you can download it here:
    http://www.ben-huddleston.com/documents/sep-protected-pages.php.zip

    Let me know if you have any questions.

    Ben

  34. Felipe says:

    mate! i’ve been working on this all day without success!
    i just try out ‘ur example and what i have to say! THANK YOU!!!!!

    i’ll try it out now on my website and let u now!

    thanks for your time!

  35. Felipe says:

    Ben, it worked out fine!

    didn’t had to make much effort making it to work as u wrote it perfect…

    thanks again for ur time! I’ll link u from my website when it’s done!

    cheers!

  36. Ben says:

    Felipe,

    No problem. Sorry you were working on it all day! Glad I was able to help.

    Cheers,
    Ben

  37. Hey Ben, fantastic info. Cheers.

  38. [...] restricting pages to logged in users only [...]

  39. steve says:

    Hey there, is there a plugin that’s just fully customizeable and I can say which pages I want it to block and what text to show?

  40. admin says:

    steve,

    No, there isn’t a plugin to do this. There’s no real point in doing a plugin since you can determine which pages you want to block by choosing this page template for only the pages you wish to block (see page template area to the right of the WYSIWYG editor in your blog). If you don’t want to block the page, then don’t choose the user protected page template for that page.

    As far as what text to show you can edit the page template to say whatever you wish. That said, if you’d like to write a plugin to do the above, be my guest.

    The page template that you can download above is for the default theme. If you use a different theme, you can edit my page template to work with whatever theme you’re using.

  41. steve says:

    Ok, I’m doing the template thing with the latest version of wordpress, and the selection bar on the left isn’t there.

  42. steve says:

    oh, never mind.

    Thanks a lot!!

  43. Ralphie says:

    Hi, This script works great, but i was wondering if there was a way to only allow certain member groups to see the protected page?

    If possible, this is sort of a work around to not letting just _any_ person register and see the protected content.

    See, new people registering will be put in a group that has no more access to the website than non-registered users, but then once i physically place the persons into a new user group, they will then have access to the protected pages.

    thanks for any help

  44. Ben says:

    Ralphie,

    Sure, the template can fairly easily be modified to work only for certain user groups. First, grab a copy of the Role Manager plugin here:
    http://www.im-web-gefunden.de/wordpress-plugins/role-manager/

    After you’ve installed and activated that plugin, you’ll need to create a new capability called “View My Hidden Posts”. To do that go to Users –> Capabilities and type “View My Hidden Posts” minus the quotes into the New Capability Name input box and click Create Capability.

    Then, you need to create a new role (or use one of the existing ones) and assign it the “View My Hidden Posts” capability by clicking on the check box by the new capability. Go to Users –> Roles to do that. Be sure to assign the capability to all user roles you wish to be able to view them (including admins).

    Then you’ll need an updated version of the template. You can view it here:
    http://www.redwingstudio.com/downloads/user-and-role-protected.phps

    You can download it here: http://www.redwingstudio.com/downloads/user-and-role-protected.php.zip

    The big difference between this one and the old one is this line:
    if ( current_user_can('view_my_hidden_posts') ) {

    That line checks for the View My Hidden Posts capability you created above and will allow users with that capability to view the page. Otherwise it tells them they aren’t authorized to view the post.

    NOTE: I haven’t tested this, but theoretically it should work. Let me know if you have any questions.

  45. juan says:

    How to redirect when the user is not correct to the same page?

  46. Ben says:

    juan, I’ll have to poke around a bit and try to figure that out. I think WordPress automatically redirects you to the wp-login.php page if your login is incorrect. I’m not sure how I would stop that from happening other than hacking around in the core code.

  47. Julio says:

    Great job, congratulations!

    The code works properly.

  48. [...] so off to Google I went! Unfortunately, the solution did not come in a nice packaged plugin. RedwingStudio.com has an article describing the creation of a custom template using PHP in which a function is called [...]

  49. [...] a thread on the WordPress forums that explains how to make a page hidden using Role Manager and a template for hidden pages.  You will have to read it yourself, I am mostly posting it here so I can always find [...]

Leave a Reply