OAuth ===== The Planviewer Maps API implements an OAuth 2.0 client as per `RFC6749 `_. When under 'Beveiliging en toegang' an OAuth configuration is set, all ``/maps_api/v2/embed`` calls require authentication via OAuth (contrary to being publicly accessible). Planviewer Maps API acts as an OAuth client, and tries to get authorization for the user from an OAuth provider to view and edit the maps associated with the application. .. important:: Any user that is succesfully authenticated gains access to the application. The Planviewer Maps API does not check for roles associated with the user to determine if a user has access to the application or a specific map. Once authenticated, the authorization (see *Access Token*) is stored in the server side session of Planviewer. Glossary -------- .. glossary:: OAuth provider The party to which Planviewer tries to authenticate the user. The provider typically also implements the Planviewer Maps API. OAuth client Planviewer Maps API acts as an OAuth client in this scheme. The Planviewer 'application' tries to get authorization for the user to use the maps associated with the application. OAuth user The user visiting an embed call (i.e. a viewer or an editor). This user needs to be authenticated by the OAuth provider, so that the OAuth client knows that the assets should be available to the user. Client Id Public identifier of Planviewer which it uses to authenticate itself to the OAuth provider as an OAuth client application. Client Secret The private secret Planviewer uses to authenticate itself. See *Client Id*. Authorisatie URL The provider URL to which the first authorization request is made. Access Token URL The provider URL to generate an *Access Token*. Resource URL The provider URL to fetch the resources associated with the user. Currently this is not actively used by Planviewer, but the OAuth 2.0 specification requires its existence. Access Token An unique string generated by the OAuth provider identifying the user on the provider side. It does not defacto identify *who* the user is, only that is *an* authorized user. How to implement ---------------- Any standards compliant OAuth provider should automagically work with the Planviewer Maps API. Note that only `Bearer `_ and `MAC `_ token types are supported as of yet. For concrete instructions we refer to `RFC6749 `_. .. In order to speed up the implementation we provide a NodeJS reference implementation on `Github `_. Step-by-step example -------------------- For your convenience we will now go through an authentication routine step-by-step. .. warning:: This walkthrough is not a substitute for the standard. We suggest using a reputable open source implementation of OAuth for your OAuth provider. If you intend to implement the provider yourself refer to `RFC6749 `_. .. image:: images/oauth2sequencediagram.png Request application page ```````````````````````` .. http:get:: https://www.planviewer.nl/maps_api/v2/embed/viewer/(string:identifier) Browser requests a map from an application which has OAuth enabled. The browser is redirected to the OAuth providers' authorization server. :resheader Set-Cookie: *PHPSESSID* If not yet the case, a session cookie is set. :resheader Location: Redirect to *Authorisatie URL*: ``https://provider/authorize/?state=...&client_id=...&redirect_uri=...&...`` Request login ````````````` .. http:get:: https://provider/authorize/?state=...&client_id=...&redirect_uri=...&... Browser follows the redirect to the authorization server, where a login page might be shown. The method by which the provider authenticates the browser is not defined. The browser could also be authenticated using a previously set session cookie, or an IP whitelist. :query string state: State string as defined by the OAuth client :query string response_type: Defaults to ``code``, see the standard for more information :query string approval_prompt: Defaults to ``auto``, see the standard for more information :query string client_id: As set in the OAuth configuration page, see *Client Id* :query string redirect_uri: Callback URL to return to after authorization is completed (or failed) After the authentication is completed, the browser is redirected back to the OAuth client: :resheader Location: Redirect to the *Callback URL*: ``https://www.planviewer.nl/maps_api/v2/oauth/1/callback?code=...`` User valid and authorized access ```````````````````````````````` .. http:get:: https://www.planviewer.nl/maps_api/v2/oauth/1/callback?code=... :query string code: *Authorization Code* :statuscode 200: no error, page is served :statuscode 403: authorization code does not yield a valid *Access Token* The *Authorization Code* is used to retrieve an *Access Token* from the Authorization server. The OAuth client performs several requests in the background to validate this *Authorization Code*. Get Access Token '''''''''''''''' This request is performed by the OAuth client to the *Access Token URL* as set in the OAuth configuration page. The RFC6749 2.3.1 specifies that the client secret must be provided in the HTTP Basic Authorization header. Contrary to what the standard specifies, most implementations require the client secret to be provided in the HTTP POST body instead. Therefore Maps API provides the client secret in the POST JSON object *and* in the Authorization header. This way we cater to the most OAuth provider implementations. .. http:post:: https://provider/access_token :form string grant_type: Set to ``authorization_code``. :form string code: *Authorization Code* :form string redirect_uri: Original ``redirect_uri`` as set during the *Request login* phase. :form string client_id: As set in the OAuth configuration page, see *Client Id*. :form string client_secret: As set in the OAuth configuration page, see *Client Secret*. :>json string access_token: *Access Token* issued by the authorization server :>json string token_type: token type as per standard :>json integer expires_in: *(recommended)* the lifetime in seconds of the *Access Token*. :>json string refresh_token: Can be used to obtain new access tokens using the ``refresh_token`` authorization grant. **Example response**: .. sourcecode:: json { "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":"example", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", } Get data '''''''' This request is performed by the OAuth client to the *Resource URL* as set in the OAuth configuration page. The contents of the response is currently not used by the OAuth client. However the resources are still retrieved. The resource server should check whether the *Access Token* is valid. .. http:get:: https://provider/resource The method in which the OAuth client utilizes the *Access Token* to authenticate with the resource server depends on the ``token_type``. Typically, it involves using the HTTP "Authorization" request header field. Currently we only support the "Bearer" and "MAC" token types. **Example request**: .. sourcecode:: http GET /resource Host: provider Authorization: Bearer mF_9.B5f-4.1JqM