# User Administration with the "adm.l" library

Typically, a web application also requires some kind of user administration: Who has access to the data, who can modify or delete? In order to not re-invent the wheel every time, we can use the pre-installed ``adm.l`` library. You can find it in the ``lib/`` folder of your PicoLisp installation. 

Passwords and user data are very sensitive topics, and I think it's important that the developer understands also the cryptographic basics. So let's take a few minutes to dive a little bit into the ``adm.l`` library.


----------------

### Password handling

First of all, we can see four functions related to **passwords**: ``passwd``, ``salt``, ``randpw``, ``auth``. 

Generally, passwords should only be stored as **hashes**, never in cleartext. A hash is a "one-way" function, which means that it is easy to calculate the hash value of a value, but not the other way around. Why is this so important?

Hashing is the most basic protection against the case that the database is  compromised and the data is obtained by someone else. If the hash is strong enough, it is computationally infeasible to reverse a hash back to the original string. 

-------------------

Nevertheless, it is well known that many users are still using extremely weak passwords (like "password123", "12345678", and so on). If the user has a weak password and the password hash gets leaked, it is likely that the attacker with brute-force methods (hashing a list of common passwords and comparing the results) or prefabricated hash dictionary, so-called *rainbow tables*.

Now in order to prevent this, we can add a **salt** to the hash calculation - a random string that is added to the hash calculation. Both hashes and salt are stored in plaintext in the database. Because of the hash value, it is close to impossible to use rainbow tables for deciphering the hashes.

------------------

### Defining the Salt

In the ``adm.l`` library, the "salt" is created by the ``(salt)`` function which uses the shape defined in the global variable ``*Salt``. In order to understand what the library is doing, let's open it in the REPL to make some tests.

```
$ pil +
: (load "@lib/adm.l")
-> T  
: (pool "test.db")
-> T
```

Let's set ``*Salt`` to the value proposed in the comment section and run ``(salt)``: 

```
: (setq *Salt (16 . "$6$@1$"))
-> (16 . "$6$@1$")
: (salt)
-> "$6$dfEjiLwaLKE44..A$"
```

We get the number ``6`` and a 16 characters string, each divided by ``$``delimitors.

--------------

What did we do here?

The CAR of ``*Salt`` defines the **length** of the salt value, in this case 16 characters. The CDR has two parts, divided by the delimitor ``$``: ``6`` and ``@1``. This shape is defined in the [``crypt(3)`` function](https://man7.org/linux/man-pages/man3/crypt.3.html). 

-``6`` defines the **hashing algorithm**, in case of 6 it's the [SHA-512](https://en.wikipedia.org/wiki/SHA-2) hash function,  

-``@1`` is replaced by a random 16-characters string in the ``salt`` function:


   ```
# <adm.l>

(de salt ()
   (text (cdr *Salt) (randpw (car *Salt))) )
```

where ``randpw``  returns a random password of a defined length.

-------------------


### Hashing a password

Any password can be hashed using the function ``passwd`` which takes a string as argument. Let's test it:

```
: (passwd "mySecretPassword")
-> "$6$BUZxYCJ7UMMD/Y59$Uh/AwZyuUNlZw9kKVoWbNflGZDO4TXAfVb3cmtPWRbvhhafjsYsjaIE3UuVWh.Alaupp84b543EmXQeAegkJ61"
```

We receive back three values, each delimited by the ``$``symbol.
- ``$6``: SHA-512 algorithm,
- ``$BUZxYCJ7UMMD/Y59``: the salt,
-``$Uh/AwZyuUNlZw9kKVoWbNflGZDO4TXAfVb3cmtPWRbvhhafjsYsjaIE3UuVWh.Alaupp84b543EmXQeAegkJ61``: the actual password hash.


The ``(salt)`` function is called each time a password is hashed. 

------------------------


### The User Model

The ``adm.l`` defines a basic user model ``+User`` and role model ``+Role`:

```
### Role ###
(class +Role +Entity)

(rel nm (+Need +Key +String))          # Role name
(rel perm (+List +Symbol))             # Permission list
(rel usr (+List +Joint) role (+User))  # Associated users

...

### User ###
(class +User +Entity)

(rel nm (+Need +Key +String))          # User name
(rel pw (+Swap +String))               # Password
(rel role (+Joint) usr (+Role))        # User role
(rel nam (+String))                    # Full Name
(rel tel (+String))                    # Phone
(rel em (+String))                     # EMail
```


The "name" property ``nm`` of the user model inherits from the classes ``+Need`` (name is required) and ``+Key`` (name is unique), which means there can't be two users with the same name.

----------------------------

Let's try to add a user to our database. To keep it simple, we only use password and name.

```
: (request '(+User) 'nm "TestUser" 'pw (passwd "abcd1234"))
-> {6}
: (commit)
-> T
```

As you can see, we only store the **hash value** of the password in the database, not the cleartext!

-------------

Now we can try to **authenticate** this user using the ``auth`` function, which takes name and plaintext password as arguments:

```
: (auth "TestUser" "abcd1234")
-> {6}
```

The function returns the correct database entry. How does it work? ``auth`` first finds the user from the database by their name. Then the provided password is hashed using the salt and algorithm of the stored password. if these are equal, the function returns the user object, otherwise NIL:


```
: (auth "TestUser" "wrongPassword")
-> NIL
```

----------------------------


### The ``login`` and ``logout`` functions

The library also defines the functions ``login`` and ``logout``. When a user logs in (for example with username and password), the global variable ``*Login`` is set to this object, and the process-ID and timestamp are printed to the terminal:

```
: (login "TestUser" "abcd1234")
6165 * 2021-11-13 12:49:59 TestUser
-> {6}

: *Login
{6}
```

The function ``logout`` sets ``*Login`` back to ``NIL``.

```
: (logout)
6165 / 2021-11-13 13:05:35
-> NIL
: *Login
-> NIL
```

------------------


``6165`` is our current process id, that we can also check with ``*Pid``:

```
: *Pid
6165
```

Not only the current process, but also all of its family members (i.e. all children of the current process, and all other children of the parent process) are informed about the login and logout using the function ``tell``.

-------------------

### ``must`` and ``may``

The ``adm.`` library defines two methods for the permission management: ``must`` and ``may``. 

``must`` is called at the beginning of a function and checks:
- if the address in the browser fits to the session,
- if the user is logged in to the sessions,
- if at least one of the permissions is set for the current user.

If any of these conditions is not fulfilled, the client receives a "403 NO PERMISSION" status code response.

-----------------------

``may`` is defined **within** the code and returns ``NIL`` if the permission is not fulfilled.

----------------------

In the next post, we will add a simple user administration with roles to our todo app example.

-------------------

# Sources

https://software-lab.de/doc/index.html   
https://man7.org/linux/man-pages/man3/crypt.3.html   




