Skip to content
Snippets Groups Projects
description.mdx 6.43 KiB
Newer Older
Bastien DUMONT's avatar
Bastien DUMONT committed
# Description

This section of documentation refers to the Oauth protocols working hand in hand with our custom proxy and the cozy-stack.
To fully understand its whereabouts, you should also look at the [enedis konnector](/docs/konnectors/enedis.md) and [grdf konnector](/docs/konnectors/grdf.md) documentation.
![gitlab](/img/gitlab-logo.svg) [proxy](https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy)
## Oauth Dance

To access customer data, one must first obtain customer authorization. This authorization is materialized by an access token and it must be obtained by the APIs exposed by each energy providers.

These APIs implement Oauth 2.0 protocol, it requires authentication from the customer along with its given consent.

See both **[Enedis](./use_cases/enedis.mdx)** and **[Grdf](./use_cases/grdfadict.md)** use cases before going further.
Bastien DUMONT's avatar
Bastien DUMONT committed

### Cozy Oauth Protocol

:::info cozy oauth flow documentation
https://docs.cozy.io/en/cozy-stack/konnectors-workflow/#reminder-oauth-flow
:::
#### CouchDB
The CouchDB database must hold all information needed for the konnector authentication to work properly.
Hugo NOUTS's avatar
Hugo NOUTS committed
Auth information are stored in the **secrets/io-cozy-account_types** database.
You can create manually the document by entering these parameters for each konnector:

<table>
  <thead>
    <tr class="header">
      <th>Name</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>_id</td>
      <td>Name of your konnector, for instance: enedisgrandlyon</td>
    </tr>
    <tr>
      <td>grant_mode</td>
      <td>authorization_code</td>
    </tr>
    <tr>
      <td>client_id</td>
      <td>Application id given by the API provider</td>
    </tr>
    <tr>
      <td>client_secret</td>
      <td>Secret also given by the API provider</td>
    </tr>
    <tr>
      <td>auth_endpoint</td>
      <td>Authorize endpoint to request when starting the oauth protocol</td>
    </tr>
    <tr>
      <td>token_endpoint</td>
      <td>
        Token endpoint to request, will be called when the auth endpoint
        response reaches the stack
      </td>
    </tr>
    <tr>
      <td>token_mode</td>
      <td>get</td>
    </tr>
  </tbody>
</table>

Once the document is created, when launching the konnector from the cozy-home or inside the running application. The oauth flow will start.

The cozy-stack will request the authorize endpoint, then call the token endpoint with the code received from the auth step.

If the token request is a success. An account/service-name database will be added in CouchDB containing all information needed for authentication and the konnector will be free to work on all endpoints within its scope.
Hugo NOUTS's avatar
Hugo NOUTS committed
The Oauth dance could be easily wrapped up with the two requests seen above. But since all cozy applications are hosted on different personal clouds, following this guideline would mean that we need a **client_id** and a **client_secret** for each one of all the applications running.

To answer this issue, two solutions are possible depending on what the energy supplier is willing to do.

- Providers could allow wildcard subdomains when registering the callback URI, it would parse the subdomain and adapt its redirection when answering **/auth** call.

:::note Example
https//\*.cozygrandlyon.cloud/account/redirect -> parse subdomain before .cozy
xyz.cozygrandlyon.cloud/account/redirect -> redirect to xyz

toto.cozygrandlyon.cloud/account/redirect -> redirect to toto
:::
Bastien DUMONT's avatar
Bastien DUMONT committed
- If the provider (Enedis for instance) is not accepting wildcards, then we put a proxy as a middleware to provide a generic endpoint to cater for all Oauth2 redirection.

#### Result

With that in mind, the proxy is now the one calling the auth and token provider endpoints. The instance name will be contained in redirect_uri, the stack will insert this parameters by itself in the /auth call.

3 endpoints are created in the proxy for **each energy supplier**:

- One for the auth
- One for the token
- One for the redirect uri

#### Proxy flow

```plantuml
  Stack -> Proxy: calls
  Proxy -> Provider: calls
  Proxy <-- Provider: responds with oauth code on proxy/redirect
  Stack <-- Proxy: redirect to user instance
  Stack -> Proxy: calls
  Proxy -> Provider: calls for token or refresh
  Proxy <-- Provider: responds
  Stack <-- Proxy: token
```

## Proxy Code Explained

:::info reminder
Feel free to check the proxy [code](https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy) at all time when reading this documentation.
:::

The proxy is coded in golang.

It is composed of six endpoints as seen above. The first endpoint to be called is **/auth**.

Bastien DUMONT's avatar
Bastien DUMONT committed
### auth
Hugo NOUTS's avatar
Hugo NOUTS committed
Originally called from a cozy-stack trying to setup its konnector. The proxy gets these information from the query:
- redirect_uri (auto inserted by the cozy-stack, except if you specify **skip_redirect_uri:true** in the CouchDB)
- response_type
- state (as it was conceived by the cozy-stack)

![auth_params](enedis-auth-params.png)

The state will be merged with the instance name, then decomposed again when reaching /redirect. This way the proxy is able to keep track of the cozy instance originally calling.

Hugo NOUTS's avatar
Hugo NOUTS committed
With all these information, the proxy can contact the provider **/auth** endpoint to start the oauth dance.
Bastien DUMONT's avatar
Bastien DUMONT committed
#### Enedis
:::warning
See that a new composed state is sent to enedis, it is made of the former state conceived by the cozy-stack + the original instance name. This will be useful when enedis is leading the oauth dance to the next step and we will need the name of the cozy to answer.
:::

Once the call is sent, enedis will point to the **/redirect** endpoint.

Bastien DUMONT's avatar
Bastien DUMONT committed
#### Grdf
Bastien DUMONT's avatar
Bastien DUMONT committed
### redirect
Retrieve the _code_, _usage_point_id_, and _state_ answered by Enedis.

Split the customed state that was modified in the **/auth** process. From this split it creates two variables :

- state
- host

Finally redirect all these parameters in a query to the cozy-stack (the cozy-stack which is still waiting for an answer from its /auth call).

:::warning state / instance
The state must be recovered without the instance name, otherwise the cozy-stack won't recognized it and the handshake will fail.
:::
Bastien DUMONT's avatar
Bastien DUMONT committed
### token

Gathering from query or parameters all params.

Bastien DUMONT's avatar
Bastien DUMONT committed
Sends a post request to the provider /token endpoint.
The stack will store the response params in a _accounts_ CouchDB database.