Skip to content
Snippets Groups Projects
description.md 10.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • Hugo NOUTS's avatar
    Hugo NOUTS committed
    !!! warning ""
        :construction: Section under Construction :construction:
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    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](../konnectors/enedis.md) and [grdf konnector](../konnectors/grdf.md) documentation.
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    !!! info "proxy code source"
        Feel free to check the proxy [code](https://forge.grandlyon.com/pocs/cozy/cozy-oauth-proxy) at all time when reading this documentation.
    
    ## Oauth Dance
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    In order for Ecolyo 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.
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    These APIs implement Oauth 2.0 protocol, it requires authentication from the customer along with its given consent.
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    ### Enedis Data Connect
    
    !!! info "enedis documentation"
        Create an account on https://datahub-enedis.fr/ to explore all the services exposed by Enedis.
        > [Authorize API](https://datahub-enedis.fr/data-connect/documentation/authorize-v1/) swagger
    
    Regarding Enedis, two endpoints are exposed:
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    #### /dataconnect/v1/oauth2/authorize
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    <table>
      <colgroup>
        <col width="30%">
        <col width="70%">
      </colgroup>
      <thead>
        <tr class="header">
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          <th>Paramater</th>
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          <th>Description</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>client_id</td>
          <td>Unique identifier of the Application</td>
        </tr>
        <tr>
          <td>response_type</td>
          <td>Authorization scenario requested. It will always be "code" as Enedis implemented a code grant authorization</td>
        </tr>
        <tr>
          <td>state</td>
          <td>Security parameter allowing to maintain the state between the request and the redirection. ** Maximum length of 100 characters ! **</td>
        </tr>
        <tr>
          <td>duration</td>
          <td>Duration of the consent requested by the application, ISO 8601 format. It cannot exceed 3 years</td>
        </tr>
      </tbody>
    </table>
    
    !!! important "Important"
        The response targets the redirect-uri registered with Enedis (the redirect-uri is our proxy and the response will be explained in details further below when explaining the proxy endpoints mechanics).
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    #### /v1/oauth2/token
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    <table>
      <colgroup>
        <col width="30%">
        <col width="70%">
      </colgroup>
      <thead>
        <tr class="header">
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          <th>Paramater</th>
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          <th>Description</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>redirect_uri</td>
          <td>URI defined when the application was created. Must be secured in https</td>
        </tr>
        <tr>
          <td>content-type</td>
          <td>application/json</td>
        </tr>
        <tr>
          <td>grant_type</td>
          <td>Authorization type to get an access token. This must be set to “authorization_code” when using an authorization code, and to “refresh_token” when using a refresh token</td>
        </tr>
        <tr>
          <td>client_id</td>
          <td>Unique identifier of the Application</td>
        </tr>
        <tr>
          <td>client_secret</td>
          <td>Secret of the client application, associated with its client_id</td>
        </tr>
        <tr>
          <td>refresh_token</td>
          <td>Refresh token returned to the previous POST request to the /token endpoint</td>
        </tr>
        <tr>
          <td>code</td>
          <td>Authorization code returned to the GET request of /authorize endpoint</td>
        </tr>
      </tbody>
    </table>
    
    On success, response will contain **access_token** or **refresh_token**, **usage_point_id** among other things. All informations will be stored by the cozy-stack in a cozy-accounts database.
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    !!! info "grdf documentation"
        Visit https://site.grdf.fr/web/grdf-adict/technique to explore all the services exposed by Grdf.
        > Prod endpoints are: https://sofit-sso-oidc.grdf.fr/openam/
    
    Regarding Grdf Adict Oauth connexion, two endpoints are exposed:
    
    !!! warning "Oauth connexion still in Beta"
        Grdf Adict Oauth service is called Client Connect and is still in early beta. It is currently lacking a *state* parameter in the Oauth dance.
    
    #### /oauth2/realms/externeGrdf/authorize
    
    #### /oauth2/realms/externeGrdf/access_token
    
    
    The */access_token* endpoint can be called with two different *grant_type* parameter.
    
      - *authorization_code* gives an access token and will also retrieve the consents list given by the user in session.
      - *client_credentials* gives only the access token allowing us to request the data service.
    
      The grdf Konnector would only need to call the *client_credentials* to get a refresh token.
    
    #### Optional: Revoke Consent
    
    It is possible to cancel a consent that was given from the user to our service (for test or development purpose for instance).
    
    api.grdf.fr/adict/v1/droit_acces/{id_accreditation}
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    ### Cozy Oauth Protocol
    
    
    !!! info "cozy oauth flow documentation" 
        [https://docs.cozy.io/en/cozy-stack/konnectors-workflow/#reminder-oauth-flow](https://docs.cozy.io/en/cozy-stack/konnectors-workflow/#reminder-oauth-flow)
    
    #### Couchdb
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    The couchdb database must hold all informations needed for the konnector authentication to work properly.
    
    
    Auth informations are stored in the **secrets/io-cozy-account_types** database.
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    You can create manually the document by entering these parameters for each konnector:
    
    
    <table>
      <colgroup>
        <col width="30%">
        <col width="70%">
      </colgroup>
      <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 informations needed for authentication and the konnector will be free to work on all endpoints within its scope.
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    ### Why we Need a Proxy
    
    The Oauth dance could be easily wrapped up with the two requests seen above. But since Ecolyo is an application hosted on multiple personnal 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.
    
    
    Exemple:
    
        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
    
    
    - 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 redirections. 
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    #### Result
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    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.
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    3 endpoints are created in the proxy for **each energy supplier**:
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    - One for the auth
    - One for the token
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    - One for the redirect uri
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    #### Proxy flow
    
    
    stack -> proxy/auth -> provider/auth -> proxy/redirect -> stack -> proxy/token -> provider/token
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    ## Proxy Code Explained
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    !!! 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.
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    It is composed of six endpoints as seen above. The first endpoint to be called is **/auth**.
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    #### auth
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    Originally called from a cozy-stack trying to setup its konnector. The proxy gets these informations from the query:
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    - client_id
    - duration
    - redirect_uri (auto inserted by the cozy-stack, except if you specify **skip_redirect_uri:true** in the couchdb)
    - response_type
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    - state (as it was conceived by the cozy-stack)
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    ![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 informations, the proxy can contact the provider **/auth** endpoint to start the oauth dance.
    
    ##### Enedis
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    !!! warning "note"
        See that a new composed state is sent to enedis, it is made of the former state conceived by the cozy-stack + the cozyOrigin instance name. This will be usefull 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.
    
    
    ##### Grdf
    
    > To be redacted
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    #### redirect
    
    
    Retrieve the *code*, *usage_point_id*, and *state* answered by Enedis.
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    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).
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    !!! 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.
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    #### token
    
    Gathering from query or parameters all params.
    
    
    Sends a post request to the provider /token endpoint. 
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    The stack will store the response params in a *accounts* couchdb database.
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    ## What Happens Next