<commit_before>[Table of contents](./README.md#table-of-contents)

Authentication and access delegations
=====================================

Introduction
------------

In this document, we will cover how to protect the usage of the cozy-stack.
When the cozy-stack receives a request, it checks that the request is
authorized, and if yes, it processes it and answers it.


What about OAuth2?
------------------

OAuth2 is about delegating an access to resources on a server to another
party. It is a framework, not a strictly defined protocol, for organizing the
interactions between these 4 actors:

- the resource owner, the "user" that can click on buttons
- the client, the website or application that would like to access the
  resources
- the authorization server, whose role is limited to give tokens but is
  central in OAuth2 interactions
- the resources server, the server that controls the resources.

For cozy, both the authorization server and the resources server roles are
played by the cozy-stack. The resource owner is the owner of a cozy instance.
The client can be the cozy-desktop app, cozy-mobile, or many other
applications.

OAuth2, and its extensions, is a large world. At its core, there is 2 things:
letting the client get a token issued by the authorization server, and using
this token to access to the resources. OAuth2 describe 4 flows, called grant
types, for the first part:

- Authorization code
- Implicit grant type
- Client credentials grant type
- Resource owner credentials grant type.

On cozy, only the most typical one is used: authorization code. To start this
flow, the client must have a `client_id` and `client_secret`. The Cozy stack
implements the OAuth2 Dynamic Client Registration Protocol (an extension to
OAuth2) to allow the clients to obtain them.

OAuth2 has also 3 ways to use a token:

- in the query-string (even if the spec does not recommended it)
- in the POST body
- in the HTTP Authorization header.

On cozy, only the HTTP header is supported.

OAuth2 has a lot of assumptions. Let's see some of them and their consequences
on Cozy:

- TLS is very important to secure the communications. in OAuth 1, there was a
  mechanism to sign the requests. But it was very difficult to get it right
  for the developers and was abandonned in OAuth2, in favor of using TLS. The
  Cozy instance are already accessible only in HTTPS, so there is nothing
  particular to do for that.

- There is a principle called TOFU, Trust On First Use. It said that if the
  user will give his permission for delegating access to its resources when
  the client will try to access them for the first time. Later, the client
  will be able to keep accessing them even if the user is no longer here to
  give his permissions.

- The client can't make the assumptions about when its tokens will work. The
  tokens have no meaning for him (like cookies in a browser), they are just
  something it got from the authorization server and can send with its
  request. The access token can expire, the user can revoke them, etc.

- OAuth 2.0 defines no cryptographic methods. But a developer that want to use
  it will have to put her hands in that.

If you want to learn OAuth 2 in details, I recommend the [OAuth 2 in Action
book](https://www.manning.com/books/oauth-2-in-action).


The cozy stack as an authorization server
-----------------------------------------

### GET /auth/login

Display a form with a password field to let the user authenticates herself to
the cozy stack.

This endpoint accepts a `redirect` parameter. If the user is already logged
in, she will be redirected immediately. Else, the parameter will be transfered
in the POST. This parameter can only contain a link to an application
installed on the cozy (thus to a subdomain of the cozy instance). To protect
against stealing authorization code with redirection, the fragment is always
overriden:

```http
GET /auth/login?redirect=https://contacts.cozy.example.org/foo?bar#baz HTTP/1.1
Host: cozy.example.org
Cookies: ...
```

**Note**: the redirect parameter should be URL-encoded. We haven't done that
to make it clear what the path (`foo`), the query-string (`bar`), and the
fragment (`baz`) are.

```http
HTTP/1.1 302 Moved Temporarily
Location: https://contacts.cozy.example.org/foo?bar#_=_
```

If the `redirect` parameter is invalid, the response will be `400 Bad
Request`. Same for other parameters, the redirection will happen only on
success (even if OAuth2 says the authorization server can redirect on errors,
it's very complicated to do it safely, and it is better to avoid this trap).

### POST /auth/login

After the user has typed her password and clicked on `Login`, a request is
made to this endpoint.

The `redirect` parameter is passed inside the body. If it is missing, the
redirection will be made against the default target: the home application of
this cozy instance.

```http
POST /auth/login HTTP/1.1
Host: cozy.example.org
Content-type: application/x-www-form-urlencoded

password=<PASSWORD>&redirect=https%3A%2F%2Fcontacts.cozy.example.org
```

```http
HTTP/1.1 302 Moved Temporarily
Set-Cookie: ...
Location: https://contacts.cozy.example.org/foo
```

### DELETE /auth/login

This can be used to log-out the user. A private context must be passed in the
query-string, to protect against CSRF attack on this (this can part of bigger
attacks like session fixation).

```http
DELETE /auth/login?CtxToken=token-for-a-private-context HTTP/1.1
Host: cozy.example.org
```

### POST /auth/register

This route is used by OAuth2 clients to dynamically register them-selves.

See [OAuth 2.0 Dynamic Client Registration
Protocol](https://tools.ietf.org/html/rfc7591) for the details.

It gives to the client these informations:

- `client_id`
- `client_secret`
- `registration_access_token`

### GET /auth/register/:client-id
### PUT /auth/register/:client-id
### DELETE /auth/register/:client-id

These routes follow the [OAuth 2.0 Dynamic Client Registration Management
Protocol RFC](https://tools.ietf.org/html/rfc7592). They allow an OAuth2
client to get back its metadata, update them, and unregister itself.

The client has to sent its registration access token to be able to use this
endpoint.

### GET /auth/authorize

When an OAuth2 client wants to get access to the data of the cozy owner, it
starts the OAuth2 dance with this step. The user is shown what the client asks
and has an accept button if she is OK with that.

The parameters are:

- `client_id`, that identify the client
- `redirect_uri`, it has be exactly the same of the one used in registration
- `state`, it's a protection against CSRF on the client (a random string
  generated by the client, that it can check when the user will be redirected
  with the authorization code. It can be used as a key in local storage for
  storing a state in a SPA).<commit_msg>Give an example of POST /auth/register in doc<commit_after>[Table of contents](./README.md#table-of-contents)

Authentication and access delegations
=====================================

Introduction
------------

In this document, we will cover how to protect the usage of the cozy-stack.
When the cozy-stack receives a request, it checks that the request is
authorized, and if yes, it processes it and answers it.


What about OAuth2?
------------------

OAuth2 is about delegating an access to resources on a server to another
party. It is a framework, not a strictly defined protocol, for organizing the
interactions between these 4 actors:

- the resource owner, the "user" that can click on buttons
- the client, the website or application that would like to access the
  resources
- the authorization server, whose role is limited to give tokens but is
  central in OAuth2 interactions
- the resources server, the server that controls the resources.

For cozy, both the authorization server and the resources server roles are
played by the cozy-stack. The resource owner is the owner of a cozy instance.
The client can be the cozy-desktop app, cozy-mobile, or many other
applications.

OAuth2, and its extensions, is a large world. At its core, there is 2 things:
letting the client get a token issued by the authorization server, and using
this token to access to the resources. OAuth2 describe 4 flows, called grant
types, for the first part:

- Authorization code
- Implicit grant type
- Client credentials grant type
- Resource owner credentials grant type.

On cozy, only the most typical one is used: authorization code. To start this
flow, the client must have a `client_id` and `client_secret`. The Cozy stack
implements the OAuth2 Dynamic Client Registration Protocol (an extension to
OAuth2) to allow the clients to obtain them.

OAuth2 has also 3 ways to use a token:

- in the query-string (even if the spec does not recommended it)
- in the POST body
- in the HTTP Authorization header.

On cozy, only the HTTP header is supported.

OAuth2 has a lot of assumptions. Let's see some of them and their consequences
on Cozy:

- TLS is very important to secure the communications. in OAuth 1, there was a
  mechanism to sign the requests. But it was very difficult to get it right
  for the developers and was abandonned in OAuth2, in favor of using TLS. The
  Cozy instance are already accessible only in HTTPS, so there is nothing
  particular to do for that.

- There is a principle called TOFU, Trust On First Use. It said that if the
  user will give his permission for delegating access to its resources when
  the client will try to access them for the first time. Later, the client
  will be able to keep accessing them even if the user is no longer here to
  give his permissions.

- The client can't make the assumptions about when its tokens will work. The
  tokens have no meaning for him (like cookies in a browser), they are just
  something it got from the authorization server and can send with its
  request. The access token can expire, the user can revoke them, etc.

- OAuth 2.0 defines no cryptographic methods. But a developer that want to use
  it will have to put her hands in that.

If you want to learn OAuth 2 in details, I recommend the [OAuth 2 in Action
book](https://www.manning.com/books/oauth-2-in-action).


The cozy stack as an authorization server
-----------------------------------------

### GET /auth/login

Display a form with a password field to let the user authenticates herself to
the cozy stack.

This endpoint accepts a `redirect` parameter. If the user is already logged
in, she will be redirected immediately. Else, the parameter will be transfered
in the POST. This parameter can only contain a link to an application
installed on the cozy (thus to a subdomain of the cozy instance). To protect
against stealing authorization code with redirection, the fragment is always
overriden:

```http
GET /auth/login?redirect=https://contacts.cozy.example.org/foo?bar#baz HTTP/1.1
Host: cozy.example.org
Cookies: ...
```

**Note**: the redirect parameter should be URL-encoded. We haven't done that
to make it clear what the path (`foo`), the query-string (`bar`), and the
fragment (`baz`) are.

```http
HTTP/1.1 302 Moved Temporarily
Location: https://contacts.cozy.example.org/foo?bar#_=_
```

If the `redirect` parameter is invalid, the response will be `400 Bad
Request`. Same for other parameters, the redirection will happen only on
success (even if OAuth2 says the authorization server can redirect on errors,
it's very complicated to do it safely, and it is better to avoid this trap).

### POST /auth/login

After the user has typed her password and clicked on `Login`, a request is
made to this endpoint.

The `redirect` parameter is passed inside the body. If it is missing, the
redirection will be made against the default target: the home application of
this cozy instance.

```http
POST /auth/login HTTP/1.1
Host: cozy.example.org
Content-type: application/x-www-form-urlencoded

password=<PASSWORD>&redirect=https%3A%2F%2Fcontacts.cozy.example.org
```

```http
HTTP/1.1 302 Moved Temporarily
Set-Cookie: ...
Location: https://contacts.cozy.example.org/foo
```

### DELETE /auth/login

This can be used to log-out the user. A private context must be passed in the
query-string, to protect against CSRF attack on this (this can part of bigger
attacks like session fixation).

```http
DELETE /auth/login?CtxToken=token-for-a-private-context HTTP/1.1
Host: cozy.example.org
```

### POST /auth/register

This route is used by OAuth2 clients to dynamically register them-selves.

See [OAuth 2.0 Dynamic Client Registration
Protocol](https://tools.ietf.org/html/rfc7591) for the details.

The client must send a JSON request, with at least:

- `redirect_uris`, an array of strings with the redirect URIs that the client
  will use in the authorization flow
- `client_name`, human-readable string name of the client to be presented to
  the end-user during authorization
- `software_id`, an identifier of the software used by the client (it should
  remain the same for all instances of the client software, whereas
  `client_id` varies between instances).

It can also send the optional fields:

- `client_kind` (possible values: web, desktop, mobile, browser, etc.)
- `client_uri`, URL string of a web page providing information about the client
- `logo_uri`, to display an icon to the user in the authorization flow
- `policy_uri`, URL string that points to a human-readable privacy policy
  document that describes how the deployment organization collects, uses,
  retains, and discloses personal data
- `software_version`, a version identifier string for the client software.

The server gives to the client the previous fields and these informations:

- `client_id`
- `client_secret`
- `registration_access_token`

Example:

```http
POST /auth/register HTTP/1.1
Host: cozy.example.org
Content-Type: application/json
Accept: application/json

{
  "redirect_uris": ["https://client.example.org/oauth/callback"],
  "client_name": "Client",
  "software_id": "github.com/example/client",
  "software_version": "2.0.1",
  "client_kind": "web",
  "client_uri": "https://client.example.org/",
  "logo_uri": "https://client.example.org/logo.svg",
  "policy_uri": "https://client/example.org/policy"
}
```

```http
HTTP/1.1 201 Created
Content-Type: application/json

{
  "client_id": "64ce5cb0-bd4c-11e6-880e-b3b7dfda89d3",
  "client_secret": "<KEY>[...omitted for brevity...]",
  "client_secret_expires_at": 0,
  "registration_access_token": "<PASSWORD>[...omitted for brevity...]",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "redirect_uris": ["https://client.example.org/oauth/callback"],
  "client_name": "Client",
  "software_id": "github.com/example/client",
  "software_version": "2.0.1",
  "client_kind": "web",
  "client_uri": "https://client.example.org/",
  "logo_uri": "https://client.example.org/logo.svg",
  "policy_uri": "https://client/example.org/policy"
}
```

### GET /auth/register/:client-id
### PUT /auth/register/:client-id
### DELETE /auth/register/:client-id

These routes follow the [OAuth 2.0 Dynamic Client Registration Management
Protocol RFC](https://tools.ietf.org/html/rfc7592). They allow an OAuth2
client to get back its metadata, update them, and unregister itself.

The client has to sent its registration access token to be able to use this
endpoint.

### GET /auth/authorize

When an OAuth2 client wants to get access to the data of the cozy owner, it
starts the OAuth2 dance with this step. The user is shown what the client asks
and has an accept button if she is OK with that.

The parameters are:

- `client_id`, that identify the client
- `redirect_uri`, it has be exactly the same of the one used in registration
- `state`, it's a protection against CSRF on the client (a random string
  generated by the client, that it can check when the user will be redirected
  with the authorization code. It can be used as a key in local storage for
  storing a state in a SPA).
{'fraction_non_alphanumeric': 0.08671713695801789, 'fraction_numerical': 0.009259838578489644, 'mean_word_length': 4.005950516755402, 'pattern_counts': {'":': 22, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 20, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6382837', 'n_tokens_mistral': 4554, 'n_tokens_neox': 4327, 'n_words': 2237}