Protecting Content
Control who can or can't see each page of content. Or, even protect your whole site in one fell swoop.
Overview
As of 2.6, you may protect your content from unwanted visitors with the protect
variable. By setting this variable, you can allow or deny people based on their logged-in status, IP address, passwords, and more.
There are a number of schemes used for protecting content:
ip_address
for allowing specific IP addresses.logged_in
for only allowing authenticated users.password
will force users to enter a specified password.
Whichever of these you choose, know that protect
is designed to help you out. We’ve tried to keep the syntax as simple as possible while allowing for flexibility. Because of this, if Statamic sees that you’ve set protect
, but it’s invalid, all users will always be denied.
Basic Usage
To protect a page, add a protect
array to the front-matter, with the corresponding scheme’s configuration inside it.
For example, to use the password scheme, you might do something like this:
---
title: Top Secret
protect:
type: password
allowed: ['secret']
form_url: /password-entry
---
Some top secret content.
You may protect an entire folder of pages by adding the protect
variable to a folder.yaml
.
If you are familiar with this feature from v1, take note that the syntax has been simplified.
Configuration
If you are protecting multiple pages, you can set common values for each schema type into your settings, which will cascade down to each page usage. You may add these to the protect
variable inside your site/settings/system.yaml
file.
Take the following settings for example:
protect:
password:
form_url: /password-entry
logged_in:
login_url: /login
Since the password
’s form_url
has been set here, you won’t need to define it on any pages that should be password protected.
---
title: Top Secret
protect:
type: password
allowed: ['secret']
# form_url is not necessary now, since it'll cascade from your configuration.
---
Some top secret content.
Shorthand Usage
If you’d like to protect a page, and have provided enough configuration for that scheme in your settings file, you may simply reference the scheme name as a string:
title: My Secret Page
protect: password
IP Address Protection
Add the IP address(es) you wish to allow to the aptly named allowed
array.
protect:
type: ip_address
allowed:
- 127.0.0.1
- 192.168.0.10
Logged In Protection
Adding this scheme to a page will redirect to a login page unless the user is already logged in.
protect:
type: logged_in
login_url: /login
append_redirect: true
If the login_url
has not been defined, the user will see an “Access Denied” page instead of a login screen. In this case, the user could log in through the Control Panel.
The append_redirect
setting will add ?redirect=/the-protected-url
to your login_url
. This pairs with the user:login_form tag’s allow_request_redirect parameter which will redirect the user to the intended page once logging in.
Password Protection
There will be times when you want to password-protect one or more files, but don’t want to bother with having people create member accounts just to access a page. That is where using the password scheme comes in. This scheme does not relate to member accounts in any way, only one-off password entry.
The setup for this would look something like the following:
---
title: My Secret Content
protect:
type: password
allowed:
- secret
- confidential
form_url: /password-entry
---
You can only see me if you have the password.
And since you're reading this, you obviously do.
The password form
Next, you’ll need to provide a way for people to enter passwords for URLs. In the above example, form_url
is pointing to /password-entry
, but this can be anywhere on your site.
You can either create a page, or a route for this. In the corresponding template, you should create something like this:
{{ protect:password_form }}
{{ if no_token }}
No token has been provided.
{{ /if }}
{{ if error }}
{{ error }}
{{ /if }}
<input type="password" name="password" />
<button>Submit</button>
{{ /protect:password_form }}
The protect:password_form
tag is going to wrap everything between the tags in an HTML form tag that’s pointing to the appropriate place. Note that the HTML of the form itself is up to you. The only requirements of this form are that the user is entering passwords into a field named password
. Other than that you can do anything you’d like.
Token
When visiting a password protected page, Statamic will generate a token and append it to the form’s URL. Without a token, the form cannot function correctly. In the example above, you can see that the no_token
boolean will be populated for you. This may happen if you visit the form URL directly.
Invalid Passwords
If someone submits a password and it isn’t valid, Statamic will redirect the user back to the form, populating the error
tag with an error message. In the example above, you can see that we’re printing it out if it’s there. Valid passwords can vary from piece of content to piece of content. This one form is smart enough to handle all password management between password-protected URLs.
Valid Passwords
A valid password is one that matches any of the passwords in the allowed
list as configured on the page (or sitewide). This means that you can send three people three different passwords to access the same URL, each having their own way in. Additionally, you could also set just one password and send that to 100 people and they can all use the same password.
It should go without saying, but for the sake of completeness here be careful in how you set and give out passwords.
Password Expiration
Each user’s passwords will expire once their session has expired. To manually invalidate a password, simply remove it from the list of allowed passwords on the page. The next time a user with that password visits this page, they’ll be redirected to the password form just like everyone else.
Complete “Whole Hog” Protection
If you want to protect a page from anyone - regardless of authentication status, IP address, time of day, weather, or beverage preference - you can simply add protect: true
to the front-matter.
One may find this useful to quickly disable something.
Site-wide Protection
To protect your whole site at once, you can simply add type: [scheme name]
into the protect
configuration variable mentioned above.
For example, to make sure your whole site is only accessible to a single IP address, you could add type: ip_address
to your system.yaml
like so:
protect:
type: ip_address
ip_address:
allowed: [127.0.0.1]
This feature affects only the front-end of your site. Site-wide protection will not apply to the Control Panel.