[[authentication]]
== Authentication

In [yada]#yada#, resources are self-contained and are individually protected from unauthorized access:

[quote,RFC 7231 Section 2]
____
One design goal of HTTP is to separate resource identification from request semantics.
____

Authentication is part of the semantics of a resource, so is part of resource itself, rather than coupled to the URI and routing. This approach improves the https://en.wikipedia.org/Cohesion_(computer_science)[cohesion] of the web resource, which can be tested independently.

As in all other areas, [yada]#yada# aims for 100% compliance with core HTTP standards when it comes to security, notably https://tools.ietf.org/html/rfc7235[RFC 7235]. Also, since HTTP APIs are nowadays used to facilitate transactional integration between systems via the user's browser, it is important that [yada]#yada# fully supports systems that offer APIs to other applications, across origins, as standardised by http://www.w3.org/TR/cors/[CORS].

It is worth taking some time to understand what is involved in
processing an HTTP request in [yada]#yada# that relate to
authentication and authorization. <<figure-security-flow>> shows a
simplified portion of the sequence of steps.

[[figure-security-flow]]
.The relevant portion of the default request-processing interceptor chain in [yada]#yada#, showing the order of processing.
[plantuml,security-flow,svg]
....
skinparam monochrome true
(*) --> "parse-parameters"
note right
Query, path parameters,
request header & body
parsed. ❶
end note
"parse-parameters" --> "authenticate"
note right
Request credentials verified
(e.g. roles). ❷
end note
"authenticate" --> "get-properties"
note right
Resource properties established,
(e.g. resource owner). ❸
end note
"get-properties" --> "authorize"
note right
Request authorized by checking
credentials against resource's
properties. ❹
end note
"authorize" --> (*)
note right
Request processing
continues ❺
end note
....
<1> First, the values of declared _parameters_ (query, path, header, form
& body) are taken from the request and checked for validity. These
parameters may be used later, both in the identification of the user
and the resource being addressed. Invalid parameters would cause a
response with a `400 Bad Request` status.

<2> Next, the request is authenticated according to an _authentication
scheme_. This involves inspecting the request for claims about the
identity of the user (and verifying that these claims are genuine and
trustworthy). Unless there is something suspicious about the request's
claims, such as the detection of a forgery attempt, *no decision is
made at this stage about whether the request should be accepted or
rejected*.

<3> Next, the resource's _properties_ are determined, such as
existence, last modification time and, in particular, attributes
governing ownership and required access conditions. These may be
ascertained solely from the request or might involve one or more
requests to other sources, such as databases.

<4> After this, an _authorization_ step is carried out to determine
whether the credentials carried by the request, if any, are sufficient
to allow access to the resource. If not, a response is returned with a
401 or 403 status code--a `401 Unauthorized` if no credentials are
present, and a `403 Forbidden` if they are. A 401 gives the user-agent
the hint that it should attempt to capture authentication data from
the user and retry the request.

<5> The request processing proceeds. Any response generated may depend
on information established by these steps. For example, certain
information might be filtered out of a response to requests that don't
have sufficient authorization.

Note that this design supports all of the following cases:

. A resource is publicly accessible.

. A resource is publicly accessible but is rendered differently for a
authenticated user.

. A resource cannot be accessed without authentication.

. A resource cannot be accessed without authentication and the user
having sufficient access rights.

.A tale of two bank accounts
****
To understand the reasons why requests are processed in this way,
here's a practical example.

Imagine tasked with the problem of securing a banking website.

A bank has decided that the URL for accessing account balance
information should be
\https://bigbank.com/accounts/<account-number>/balances.html.

All requests are checked to ensure that the request is from a properly
logged-in user.

Let's say Alice's bank account number is 12345678. By this design, as
long as Alice is logged in, Alice can access her account balance via a
GET request to \https://bigbank.com/accounts/12345678/balances.html.

_Can you spot a security issue here?_

The problem is that Alice can also access Bob's bank account balances.

This may seem like an obvious mistake but this type of vulnerability
has historically been extremely common and responsible for a great
many hacks footnote:[It is surprising that the simple editing of a URL
in the browser by the user should be considered 'hacking' at all]. It
is still a common contributor to OWASP 2017's #5 most critical
security issue:
https://www.owasp.org/index.php/Top_10-2017_A5-Broken_Access_Control[Broken
Access Control].

One of the causes is that many web frameworks don't provide good
support for this example use-case, and still rely on declarative
security on the URL itself. This is another reason why it's important
to understand security in terms of a resource rather than a URI
pattern. It's only once you have fully identified a web resource that
you can determine whether access to it should be granted to a request.
****

[[authentication-schemes]]
=== HTTP authentication

[.lead]
In HTTP, authentication is the act of establishing the credentials of a user,
by checking the claims made in the `Authorization` header of the request.

HTTP authentication is described in
https://tools.ietf.org/html/rfc7235[RFC 7235].

Authentication is achieved by declaring one (or more) _authentication
schemes_ on the resource. An authentication scheme determines how the
request's credentials are established. Credentials contain information
such as the user's identity, roles and privileges, which can be used
to deny the request, or if approved, may affect the nature of the
response. IANA maintains a
link:https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml[registry]
of HTTP authentication schemes, which include
https://tools.ietf.org/html/rfc7617[Basic],
https://tools.ietf.org/html/rfc7616[Digest],
https://tools.ietf.org/html/rfc6750[Bearer],
https://tools.ietf.org/html/rfc7486[HOBA] and others.

<<example-basic-auth>> demonstrates how a resource might be protected
using Basic Authentication.

[[example-basic-auth]]
.Protecting a [yada]#yada# resource with Basic Authentication
====
To declare a resource will be protected with Basic Authentication:

[source,clojure]
----
include::../dev/src/yada/dev/examples.clj[tag=basic]
----
<1> The resource contains an`:authentication` entry
<2> The scheme is set to `Basic`
<3> Any non-blank user is considered a success. Real-world cases would most likely check the password too.
<4> A value is returned that will be bound as the context's `:authentication` entry.
<5> Optionally, a realm value can be specified. The support for, and semantics of a realm value depends on the authentication scheme.
<6> The response to a GET request prints a string containing the user field.
====

Other authentication schemes work in a similar way to that shown in <<example-basic-auth>>.

==== The `:authenticate` function

The `:authenticate` function takes 3 arguments:

* the [yada]#yada# context.
* the credentials found in the value of the request's `Authorization header`. For some schemes, this is pre-processed for convenience. For example, in the case of Basic Authentication, the header is decoded into a vector containing the user and password sent by the user-agent.
* the value of the authentication scheme, allowing for extra data to be specified on a per-resource basis.

The `:authenticate` function MUST return one of the following:

* A truthy value, indicating successful authentication, which will be bound to the [yada]#yada# context as the `:authentication` entry.
* Nil, indicating authentication has not be satisfied, for example, due to a bad password or illegal submission. No `:authentication` entry is bound to the [yada]#yada# context.
* The [yada]#yada# context, augmented as appropriate with a `:authentication` entry.
* Partial credentials, with a new authentication scheme to try (TBD)

Return values from the `:authenticate` function MAY be
https://github.com/ztellman/manifold/blob/master/docs/deferred.md[deferred]
values. Since authentication often involves database or network calls it can be made asychronous to avoid blocking the request thread.

==== Multiple authentication schemes

If a resource has multiple authentication schemes, use the
`:authentication-schemes` entry instead, with a collection of auth
schemes.

[source,clojure]
----
{
 :authentication-schemes
 [{:scheme "Basic" …}
  {:scheme "Digest" …}]
}
----

Challenges will be sent to the user-agent with each possible scheme,
allowing the user-agent to pick the best one.

[[form-based-logins]]
=== Cookie authentication

Basic Authentication has a number of weaknesses, such as the difficulty
of logging out and the lack of control that a website has over the
fields presented to a human. Therefore, the vast majority of websites
prefer to use a custom login form generated in HTML.

<<cookies>> described [yada]#yada#'s support for cookies, which can be
used to store security information (such as a login session
identifier) which will be passed in each request. We will use this
support when creating a login form and for securing resources.

==== Creating a login form

You can think of a login form as a resource that lets the user present
one set of credentials in order to acquire additional ones. The
credentials the user presents, via a form, are verified and if they are
true, a cookie is generated that certifies this. This cookie provides
this 'certificate' to subsequent requests in which it is sent.

Let's start by building this login resource that will provide a login
form page to browsers and verify the form data when that form is
submitted.

Here's a simplistic but viable resource model for the two methods
involved:

[source,clojure]
----
(require
 '[schema.core :as s]
 '[hiccup.core :refer [html]]
 '[yada.yada :as yada])

{:cookies
 ;; Let's define the session cookie
 {:session
  {:name "session"
   :max-age 3600
   :domain "example.com"
   :path "/"
   :secure true
   :http-only true
   :consumer (fn [ctx cookie v]
               (let [user-details (db/retrieve-session v)]
                 (cond-> ctx
                   session (assoc :authentication user-details))))}}

 :methods
 {:get
  ;; Here is the login form
  {:produces "text/html"
   :response (html
              [:form {:method :post}
               [:input {:name "user" :type :text}]
               [:input {:name "password" :type :password}]
               [:input {:type :submit}]])}

  :post
  {:consumes "application/x-www-form-urlencoded"
   :parameters {:form
                {:user s/Str :password s/Str}}

   :response
   (fn [ctx]
     (let [{:keys [user password]} (get-in ctx [:parameters :form])]
       (if (valid-user user password)
         (let [session-id (str (java.util.UUID/randomUUID))]
	   (db/new-session session-id {:user user})
           (yada/set-cookie ctx :session session-id))

         "Try again!")))}}}
----

The POST method method consumes incoming URL-encoded data (the classic
way a browser sends form data). It de-structures the two parameters
(user and password) from the form parameters.

We then determine if the user and password are valid (we don't explain
here how this is done, but assume a `valid-user` function exists that
can tell us). If the user is valid we associate a new cookie called
"session" with the response.

The other method, GET, simply produces a form for user-agents that can
render HTML (browsers, typically) to post back. For reasons of cohesion,
it's a good idea to provide these two methods in the same resource to
encapsulate and dedupe the fields which are relevant to both the GET and
the POST.

[[logout]]
==== Logout

The recommended way of logging out is to remove the cookie. This can
be achieved with `(yada/unset-cookie)`.
