## Security

In a web application it is often required to limit access to certain URI's to authorized users. To facilitate this in libzeep, the `zeep::http::server` object can use a `security_context`. The `security_context` itself uses a `user_service` to provide `user_details` structs containing the actual data for a user.

The `user_details` structure contains the `username`, encrypted `password` and a list of `roles` this user can play. The roles are simple text strings and should preferrably be very short, like `'USER'` or `'ADMIN'`.

The `user_service` class returns `user_details` based on a `username` via the pure virtual method `load_user`. A `simple_user_service` class is available to create very simple user services based on static data. In a real world application you should implement your own user_service and store user information in e.g. a database.

#### example

Let us walk through an example of an application using security. This web application will have two pages, a landing page at the URI `/` (but also at `/index` and `/index.html`) and an admin page at `/admin`. The latter of course will only be accessible by our admin who is called scott and he uses the password tiger.

| Note
The code for all example code used in this documentation can be found in the doc/examples subdirectory of the libzeep distribution.

First start by writing some template code. For this example we will have a common menu template and two templates for the two pages respectively. The interesting part of the menu template is this:

    <div z:fragment="menu" class="w3-bar w3-border w3-light-grey">
      <a href="/" class="w3-bar-item w3-button">Home</a>
      <a href="/admin" class="w3-bar-item w3-button"
      	 z:classappend="${#security.hasRole('ADMIN') ? '' : 'w3-text-grey w3-hover-none w3-hover-text-grey'}">Admin</a>
      <a z:if="${not #security.authorized()}" href="/login" class="w3-bar-item w3-button w3-green w3-right">Login</a>
      <a z:if="${#security.authorized()}" href="/logout" class="w3-bar-item w3-button w3-green w3-right">Logout</a>
    </div>

We're using W3.CSS as CSS library, albeit we have stored a copy in our own docroot. The two last links in this navigation bar have the `z:if`"..."= argument checking whether the current user is authorized. These attributes help in select which of the two will be visible, login or logout, based on the current authentication state. The `#security` class in our `el` library has two more methods called `username` and `hasRole`. The last one returns true when a user has the role asked for.

Next we define a simple `html_controller` that handles the two pages and also serves stylesheets and scripts.

    class hello_controller : public zeep::http::html_controller
    {
      public:
        hello_controller()
        {
            // Mount the handler `handle_index` on /, /index and /index.html
            mount("{,index,index.html}", &hello_controller::handle_index);

            // This admin page will only be accessible by authorized users
            mount("admin", &hello_controller::handle_admin);

            // scripts & css
            mount("{css,scripts}/", &hello_controller::handle_file);
        }

        void handle_index(const zeep::http::request& req, const zeep::http::scope& scope, zeep::http::reply& rep)
        {
            get_template_processor().create_reply_from_template("security-hello.xhtml", scope, rep);
        }

        void handle_admin(const zeep::http::request& req, const zeep::http::scope& scope, zeep::http::reply& rep)
        {
            get_template_processor().create_reply_from_template("security-admin.xhtml", scope, rep);
        }
    };

Nothing fancy here, just a simple controller returning pages based on templates. In the template we add a salutation:

    <p>Hello, <span z:text="${#security.username() ?: 'world'}"></span>!</p>

And here we see the call to `#security.username()`. Note also the use of the elvis operator, if username is not set, 'world' is used instead.

Now, in the `main` of our application we first create a `user_service`.

    // Create a user service with a single user
    zeep::http::simple_user_service users({
        {
            "scott",
            zeep::http::pbkdf2_sha256_password_encoder().encode("tiger"),
            { "USER", "ADMIN" }
        }
    });

We use the `simple_user_service` class and provide a static list of users. The `user_service` should return `user_details` with an encrypted password and therefore we encrypt the plain text password here. Normally you would store this password encrypted of course. For encrypting password we use the `pbkdf2_sha256_password_encoder` class. You can add other password encoders based on other algorithms like bcrypt but you then have to register these yourself using `security_context::register_password_encoder`;

Now we can create the security context. This context will be passed to the `zeep::http::server` class as a pointer and the `zeep::http::server` will take ownership.

    // Create a security context with a secret and users
    std::string secret = zeep::random_hash();
    auto sc = new zeep::http::security_context(secret, users, false);

The secret passed to the security_context is used in creating signatures for the JWT token. If you store this secret, the sessions of your users will persist reboots of the server. But in this case we create a new secret after each launch and thus the tokens will expire.

Now we add access rules.

    // Add the rule,
    sc->add_rule("/admin", "ADMIN");
    sc->add_rule("/", {});

A rule specifies for a glob pattern which users can access it based on the roles these users have. If the list of roles is empty, this means all users should be able to access this URI. When a request is received, the rules are checked in order of which they were added. The first match will be used to check the roles.

In this example `/admin` is only accessible by users having role ADMIN. All other URI's are allowed by everyone. Note that we could have also created the `security_context` with the parameter defaultAccessAllowed as `true`, we then would not have needed that last rule.

And now we can create the `zeep::http::server`, add some controller and start it.

    zeep::http::server srv(sc, "docroot");

    srv.add_controller(new hello_controller());
    srv.add_controller(new zeep::http::login_controller());

    srv.bind("::", 8080);
    srv.run(2);

| Use the server constructor that takes the path to a docroot so it will construct a template processor

Note that we add the default `login_controller`. This controller takes care of handling `/login` and `/logout` requests. It will also add the required rule for `/login` to the `security_context` using `add_rule("/login", {});` since otherwise the login page would not be reachable. Make sure you do not add your own rules that prevent access to this page.

And that's all. You can now start this server and see that you can access `/` and `/login` without any problem but `/admin` will give you an authentication error. When you login using the credentials `scott/tiger` you can access the `/admin` page and you can now also click the Logout button.