🗒️
notes
  • Journal
  • URLs
  • Java Card
    • SCP02
    • Rapid Notes
    • _FIXVALS_
    • Mifare
    • Chain Of Trust
  • Encoding
    • CBEFF
    • Bytes
  • Snippets
    • JNI_OnLoad
  • float to byte[]
  • Protobuf
  • C/C++
    • Containers
    • Basics
    • JNI
    • gcov
    • Castings
  • chess
    • Untitled
  • Compression
    • Untitled
  • Snippets
    • Untitled
  • Build Systems
    • Maven
    • Windows
  • Gradle
  • CMake
  • Java
    • Untitled
    • Certificates
  • Android
    • Mifare
  • Python
    • ctypes
  • WebSub
    • References
  • Spring Boot
    • Form-based Authentication
    • Basic Access Authentication
    • JWT Authentication
  • QR Code
    • Denso QR Code
  • Philosophical Inquiry
    • First
  • XML
    • xmlstarlet
Powered by GitBook
On this page
  • Form-based Login
  • Step#2
  • Step#3
  • Step#4

Was this helpful?

  1. Spring Boot

Form-based Authentication

No formal RFC standard

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

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.

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.

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:

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 .

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.

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:

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.

This completes our trace of Form-based Authentication.

PreviousReferencesNextBasic Access Authentication

Last updated 4 years ago

Was this helpful?