# Form-based Authentication

### Form-based Login

We are going to describe the sequence of `http` events when we are accessing a `spring boot` server endpoint that is protected by `form-based authentication`. I divided the `http` conversations into series of talks based on the varying values of `JSESSIONID`.

#### Step#1

On browser, access url `http://localhost:8080`&#x20;

The browser sends an `http GET` request:

```
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9        
```

The server responds with an `http redirect` , and advising the browser to redirect the request to the url indicated in the `location` field in the response. The `server` is also advising to use the value in `JSESSIONID` field.

```
HTTP/1.1 302 
Set-Cookie: JSESSIONID=F315E46786EF5AFDE6FFBCBAAD55F855; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Location: http://localhost:8080/login
Content-Length: 0
Date: Sun, 13 Sep 2020 15:13:42 GMT
```

The browser follows the redirect advise, and issues another `http GET` request with:

```
GET /login HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=F315E46786EF5AFDE6FFBCBAAD55F855
```

Following the server's advice, the browser follows the redirect URL and uses the `JSESSIONID`.

The server responds with an OK or `http 200` containing the `html` page in the body payload. **This ends the first conversation.**&#x20;

```
HTTP/1.1 200 
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: text/html;charset=UTF-8
Content-Length: 1406
Date: Sun, 13 Sep 2020 15:13:42 GMT

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>Please sign in</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
    <link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
  </head>
  <body>
     <div class="container">
      <form class="form-signin" method="post" action="/login">
        <h2 class="form-signin-heading">Please sign in</h2>
        <p>
          <label for="username" class="sr-only">Username</label>
          <input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
        </p>
        <p>
          <label for="password" class="sr-only">Password</label>
          <input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
        </p>
<input name="_csrf" type="hidden" value="1af9457a-516d-4ca3-aaa8-3272cee19f6e" />
        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
      </form>
</div>
</body></html>
```

The second conversation shall use a new value of `JSESSIONID` given by the server.&#x20;

The browser renders the `html content` and this completes the request. The browser, shows a login form for the user to input username and password. The user then, inputs his username and password, and clicks the `Sign in` button. This is a `POST` request that is sent to the server. The browser is able to do this `POST` action because of the form's `method` attribute which is marked as `post` in the above. You will also notice that inside this form is a `csrf` hidden field, this is used by the server to verify that the login credentials is coming from the user who initiated this request.  The browser sends the following `http POST` content which forms the second conversation.

### Step#2

Browser sends a `POST` request to the server:&#x20;

```
POST /login HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 102
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/login
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=F315E46786EF5AFDE6FFBCBAAD55F855

username=user&password=40402e88-2aec-4125-ab55-ef0ad759bdc1&_csrf=1af9457a-516d-4ca3-aaa8-3272cee19f6e
```

You will noticed the username and password is in the `header` fields, along with an accompanyng `_csrf` field. This `POST` request is sort of another request, because the first request that returns the login page uses the same value in the `JSESSIONID` to track it. However, this second request made by browser when doing the `POST` is now another request and needs a new `JSESSIONID` .

&#x20;The `server` responds with, and notice the new value in `JSESSIONID` because the first `http` talk is completed, and this second one starts a a new conversation and tracked by this new value in `JSESSIONID`. The `server`, therefore, advices the `browser` from now on to use this new value of `JSESSIONID`:

```
HTTP/1.1 302 
Set-Cookie: JSESSIONID=0A5195BF8C1281606FC017ECBD1EDE1E; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Location: http://localhost:8080/
Content-Length: 0
Date: Sun, 13 Sep 2020 15:14:03 GMT
```

The browser, again, following the 2nd advice, does another `http GET` (or redirect advise) to `/` location and sends below, using the new value of `JSESSIONID` as advised:

```
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/login
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=0A5195BF8C1281606FC017ECBD1EDE1E
```

The `server` responds below content:

```
HTTP/1.1 200 
Last-Modified: Sun, 13 Sep 2020 13:30:53 GMT
Accept-Ranges: bytes
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Content-Length: 35
Date: Sun, 13 Sep 2020 15:14:03 GMT

<h1>Hello Spring Boot Security</h1>
```

and this completes the 2nd talk.&#x20;

### Step#3

The second `JSESSIONID` the browser has, shall now become his token to access the protected resource in the server. The browser, now access the protected resource and is successfully retrieves the `json` response. Take note, no more `username/password` is passed in this request. Below is the browser's `GET` request which succeeds:&#x20;

```
GET /api/v1/students/1 HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=0A5195BF8C1281606FC017ECBD1EDE1E
```

The `server` seeing the `JSESSIONID` allows the request to the `/api/v1/students/1` and returns the `json` response. The `server` response with:

```
HTTP/1.1 200 
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 13 Sep 2020 15:14:32 GMT

{"studentId":1,"studentName":"James Bond"}
```

According to `Nelson`, the `JSESSIONID` has a valid time period of 30 minutes? So, the browser can make more request and only needing this `JSESSIONID` and his requests will be granted.

### Step#4

Form-based authentication is an improvement to `Basic Access Authentication` in its ability to do `/logout` which clears the browser. The last part of the talk is when the browser logs off and sends below:

```
GET /logout HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=0A5195BF8C1281606FC017ECBD1EDE1E
```

The `server` sends a logout confirmation html page with a button:

```
HTTP/1.1 200 
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: text/html;charset=UTF-8
Content-Length: 1015
Date: Sun, 13 Sep 2020 16:47:22 GMT

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>Confirm Log Out?</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
    <link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
  </head>
  <body>
     <div class="container">
      <form class="form-signin" method="post" action="/logout">
        <h2 class="form-signin-heading">Are you sure you want to log out?</h2>
<input name="_csrf" type="hidden" value="272ccc79-e918-44b1-aaf4-2bfb5e098818" />
        <button class="btn btn-lg btn-primary btn-block" type="submit">Log Out</button>
      </form>
    </div>
  </body>
</html>
```

The browser confirms the logout and sends a `POST` request below:

```
POST /logout HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 42
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/logout
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=0A5195BF8C1281606FC017ECBD1EDE1E

_csrf=272ccc79-e918-44b1-aaf4-2bfb5e098818
```

The server responds with a redirect advise below:

```
HTTP/1.1 302 
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Location: http://localhost:8080/login?logout
Content-Length: 0
Date: Sun, 13 Sep 2020 16:47:57 GMT
```

The browser follows the advice and does an `HTTP GET`:

```
GET /login?logout HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/logout
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=0A5195BF8C1281606FC017ECBD1EDE1E
```

The server sends html content of redirected page after logout,  and it has new `JSESSIONID` value:

```
HTTP/1.1 200 
Set-Cookie: JSESSIONID=7137C6BC2DE2C95AA9BCA510EA93199B; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: text/html;charset=UTF-8
Content-Length: 1482
Date: Sun, 13 Sep 2020 16:47:57 GMT

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>Please sign in</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
    <link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
  </head>
  <body>
     <div class="container">
      <form class="form-signin" method="post" action="/login">
        <h2 class="form-signin-heading">Please sign in</h2>
<div class="alert alert-success" role="alert">You have been signed out</div>        <p>
          <label for="username" class="sr-only">Username</label>
          <input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
        </p>
        <p>
          <label for="password" class="sr-only">Password</label>
          <input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
        </p>
<input name="_csrf" type="hidden" value="34573348-f14f-4abc-ac1d-b3ce3acac2c6" />
        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
      </form>
</div>
</body></html>
```

The browser, renders this redirection page.&#x20;

This completes our trace of `Form-based Authentication`.&#x20;
