Access forbidden
You can use Kirby’s user system to restrict access to parts of your website that should only be available to certain users, for example, a clients’ area.
In this recipe we will guide you through
- creating a login form for the front-end
- providing a logout link
- protecting pages from unauthenticated users
Do not use the file cache for pages with protected content, otherwise your content might be visible to unauthenticated users.
User management
All users, including front-end users, are managed via the Panel.
Creating roles without panel access
By default, Kirby provides a single admin role with access to the Panel and without any restrictions. Front-end users usually shouldn’t have access to the Panel at all so we first need to create a user role without Panel access.
In your /site/blueprints/users
folder, create a new file called client.yml
with the following content:
If you add a new user in the Panel and assign the client
role, this user cannot login to the Panel.
You can create as many roles without Panel access as necessary to determine which part of your front-end should be accessible to which role.
The login page
For the login page, we use an unlisted page with some basic information that gets its own template. Create a /content/login
folder with a login.txt
text file inside it. We use the text file to store the information for the form.
By creating a content file with these fields, we can make the form more dynamic and translate form labels and error messages in a multi-language installation if required. You could also hard-code this in your template instead.
The corresponding blueprint for the Panel
To make this file editable in the Panel, create a blueprint for this page:
The login template
In the login template, create the login form and a container for the error messages:
The controller
To handle the form submission we create a login controller to keep the logic out of the template.
The login will redirect the user back to the homepage if it was successful. Otherwise the error variable is returned to the template as true and the alert is displayed. If you want to redirect the user to a different page, change the path in the go()
method.
The logout
For the logout we don’t need a real page. A simple URL to send logged-in users to is enough.
By adding the code above to your config file, Kirby will register a new route to http://yoursite.com/logout
. When you open that URL, the action method is called and a logged-in user will be logged out. Afterwards the script will redirect the user to the login page.
Adding a logout link to the menu
As soon as the user logged in, we display a logout link in the menu or somewhere else on the page. Here is the menu from Kirby’s Starterkit with an additional li
element that appears when the user has logged in.
Protecting Content
With the login and logout processes in place, we can finally protect our content.
Protecting entire pages
You can protect entire pages from unauthenticated users by adding the following line at the top of a template:
This will redirect all unauthenticated visitors to the home page.
Instead of adding this code to each template, you can also put your logic into a route, for example, when restricting access by other criteria than the template.
Protecting parts of a page
In the same way, you can hide parts of a page from unauthenticated users:
Protecting content by role
The above examples don’t differentiate by user role but grant access to these pages to all logged-in users. If you have multiple front-end user roles and want to restrict access to certain pages or parts of pages to particular roles, you can ask for the current user’s role like this:
Remarks
Note that this recipe only provides a basic example to give you an idea how to handle access restrictions. You can extend this into a powerful user area, with user sign-on, password reset, etc.
The process described here doesn’t prevent access to your assets (images, video, documents etc., which will still be accessible to anyone who guesses the URL to these files). We will deal with this in a separate recipe.