Adding auth to your application
Published: 2024-02-22 19:48:33

## Adding auth

In earlier sections, we have talked about routings, plugins and views and touched controllers.

Now we will add security so we can try our login view.

Security is managed within our routing file, that will point to a security module and function. We have our routing file `my_first_nova_router.erl` looking like this:

```erlang
-module(my_first_nova_router).
-behaviour(nova_router).

-export([
         routes/1
        ]).

%% The Environment-variable is defined in your sys.config in {nova, [{environment, Value}]}
routes(_Environment) ->
  [#{prefix => "",
      security => false,
      routes => [
                 {"/", { my_first_nova_main_controller, index}, #{methods => [get]}},
                 {"/login", { my_first_nova_main_controller, login}, #{methods => [get]}},
                 {"/assets/[...]", "assets"}
                ]
      }].

```

We will now re-arragne some of the routing so we can add the security, ususally we store things as auth tokens and use that to do next api call. But this is just an simple example so I will just add auth to our path and let our view make a post to it. We will show the Username in our homepage.

We will start with adding a new Route map into the list, and move the endpoint `/` this one will use a security module that we will create that will be called `my_first_nova_auth.erl` this module will have a function called `username_password`. The new route map will look like this:

```erlang
    #{prefix => "",
      security => {my_first_nova_auth, username_password},
      routes => [{"/", { my_first_nova_main_controller, index}, #{methods => [post]}}]
     }
```
Here we have added the security `{my_first_nova_auth, username_password}` so this will be called before the request hits the controller.

Lets create our security module, in `src` directory you can create `my_first_nova_auth.erl`, when we talked about plugins we configured our plugin to hand urlencoded body, this is what our form will give us.

```erlang
-module(my_first_nova_auth).

-export([username_password/1]).

username_password(#{params := Params}) ->
    case Params of
        #{<<"username">> := Username,
          <<"password">> := <<"password">>} -> {true, #{username => Username}};
        _ -> false
    end.
```

This code will authenticate the user and check if the password is password. If it is true we will store `#{username => Username}` in the Req object as a map with the key `auth_data`.

```erlang
-module(my_first_nova_main_controller).
-export([
         index/1,
         login/1
        ]).

index(#{auth_data := #{username := Username}}) ->
    {ok, [{message, <<"Hello ", Username/binary>>}]}.

login(_Req) ->
    {ok, [], #{view => login}}.
```

We now can use this `auth_data` to get the Username that we want to display on our page.


```erlang
-module(my_first_nova_router).
-behaviour(nova_router).

-export([
         routes/1
        ]).

%% The Environment-variable is defined in your sys.config in {nova, [{environment, Value}]}
routes(_Environment) ->
  [#{prefix => "",
      security => false,
      routes => [
                 {"/login", { my_first_nova_main_controller, login}, #{methods => [get]}}
                ]
      },
    #{prefix => "",
      security => {my_first_nova_auth, username_password},
      routes => [{"/", { my_first_nova_main_controller, index}, #{methods => [post]}}]
     }
   ].

```

Now we can try this out, start the node `rebar3 nova serve` then we can go to `localhost:8080/login` this will show us our view with username and password form. Try any username and the password is `password`. If everything works you will see the start page with starts and Nova loggo saying `Hello USERNAME`.