Skip to content

Commit

Permalink
Document authorization with trigger service (digital-asset#8581)
Browse files Browse the repository at this point in the history
* Docs for trigger-service auth and auth middleware

changelog_begin
changelog_end

* Document OAuth 2.0 authorization middleware

* Explain 401 Unauthorized resonse

* Add JS frontend example

* Update docs/source/tools/auth-middleware/index.rst

Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>

* Update docs/source/tools/auth-middleware/index.rst

Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>

* Update docs/source/tools/auth-middleware/index.rst

Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>

* Update docs/source/tools/auth-middleware/index.rst

Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>

* Update docs/source/tools/auth-middleware/oauth2.rst

Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>

* trigger service don't redirect by default

https://github.com/digital-asset/daml/pull/8581/files/3a5dba7a7040acb51e8fcacfc203d8b7214d5a58#r562497928

* Call it Auth Middleware

digital-asset#8581 (comment)

Co-authored-by: Andreas Herrmann <andreas.herrmann@tweag.io>
Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
  • Loading branch information
3 people authored Jan 22, 2021
1 parent 56c1405 commit 7543c6f
Show file tree
Hide file tree
Showing 9 changed files with 521 additions and 5 deletions.
3 changes: 2 additions & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ Daml Documentation
daml-integration-kit/index
triggers/index
tools/visual
tools/trigger-service
tools/trigger-service/index
tools/auth-middleware/index
concepts/interoperability

.. toctree::
Expand Down
2 changes: 1 addition & 1 deletion docs/source/support/component-statuses.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Runtime components
* - :doc:`Development CLI to start individual triggers in dev environment </triggers/index>` (``daml trigger``)
- Beta
-
* - :doc:`/tools/trigger-service` (``daml trigger-service``)
* - :doc:`/tools/trigger-service/index` (``daml trigger-service``)
- Alpha
-
* - **Extractor**
Expand Down
154 changes: 154 additions & 0 deletions docs/source/tools/auth-middleware/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
.. Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
.. SPDX-License-Identifier: Apache-2.0
Auth Middleware
###############

The auth middleware is currently an :doc:`Early Access Feature in Labs status </support/status-definitions>`.

.. toctree::
:hidden:

./oauth2

Daml ledgers only validate authorization tokens. The issuance of those tokens however is something defined by the ledger operator and can vary significantly even if the same ledger is being used. This poses a challenge for application developers aiming to develop applications that need to be able to acquire and refresh authorization tokens but don’t want to tie themselves to any particular mechanism for token issuance.
The auth middleware aims to address this problem by providing an API that decouples Daml applications from these details.
The ledger operator can provide an auth middleware that is suitable for their authentication and authorization mechanism.
Daml Connect includes an implementation of an auth middleware that supports `OAuth 2.0 Authorization Code Grant <https://oauth.net/2/grant-types/authorization-code/>`_. If this implementation is not compatible with your mechanism for token issuance, you can implement your own auth middleware provided it conforms to the same API.

Features
~~~~~~~~

The auth middleware is designed to fulfill the following goals:

- Be agnostic of the authentication and authorization protocol required by the identity and access management (IAM) system used by the ledger operator.
- Allow fine grained access control via Daml ledger claims.
- Support token refresh for long running clients that should not require user interaction.

Auth Middleware API
~~~~~~~~~~~~~~~~~~~

An implementation of the auth middleware must provide the following API.

Obtain Access Token
*******************

The application contacts this endpoint to determine if the user is authenticated and authorized to access the given claims.
The application must forward any cookies that it itself received in the user's request.
The response will contain an access token and optionally a refresh token if the user is authenticated and authorized.
Otherwise, the response will be 401 Unauthorized.

HTTP Request
============

- URL: ``/auth?claims=:claims``
- Method: ``GET``
- Headers: ``Cookie``

where

- ``claims`` are the requested :ref:`Daml Ledger Claims <auth-middleware-claims>`.

For example::

/auth?claims=actAs:Alice+applicationId:MyApp

HTTP Response
=============

.. code-block:: json
{
"access_token": "...",
"refresh_token": "..."
}
where

- ``access_token`` is the access token to use for Daml ledger commands.
- ``refresh_token`` (optional) can be used to refresh an expired access token on the ``/refresh`` endpoint.

Request Authorization
*********************

The application directs the user to this endoint if the ``/auth`` endpoint returned 401 Unauthorized.
This will request authentication and authorization of the user from the IAM for the given claims.
E.g. in the OAuth 2.0 based implementation included in DAML Connect, this will start an Authorization Code Grant flow.

If authorization is granted this will store the access and optional refresh token in a cookie. The request can define a callback URI, if specified this endpoint will redirect to the callback URI at the end of the flow. Otherwise, it will resepond with a status code that indicates whether authorization was successful or not.

HTTP Request
============

- URL: ``/login?claims=:claims&redirect_uri=:redirect_uri&state=:state``
- Method: ``GET``

where

- ``claims`` are the requested :ref:`Daml Ledger Claims <auth-middleware-claims>`.
- ``redirect_uri`` (optional) redirect to this URI at the end of the flow.
Passes ``error`` and optionally ``error_description`` parameters if authorization failed.
- ``state`` (optional) forward this parameter to the ``redirect_uri`` if specified.

For example::

/login?claims=actAs:Alice+applicationId:MyApp&redirect_uri=http://example.com/cb&state=2b56cc2e-01ad-4e51-a9b3-124d4bbe0a91

Refresh Access Token
********************

The application contacts this endpoint to refresh an expired access token without requiring user input.
Token refresh is available if the ``/auth`` endpoint return a refresh token along side the access token.
This endpoint will return a new access token and optionally a new refresh token to replace the old.

HTTP Request
============

- URL: ``/refresh``
- Method: ``POST``
- Content-Type: ``application/json``
- Content:

.. code-block:: json
{
"refresh_token": "..."
}
where

- ``refresh_token`` is the refresh token returned by ``/auth`` or a previous ``/refresh`` request.

HTTP Response
=============

.. code-block:: json
{
"access_token": "...",
"refresh_token": "..."
}
where

- ``access_token`` is the access token to use for Daml ledger commands.
- ``refresh_token`` (optional) can be used to refresh an expired access token on the ``/refresh`` endpoint.

.. _auth-middleware-claims:

Daml Ledger Claims
******************

A list of claims specifies the set of capabilities that are requested.
These are passed as a URL encoded, space separated list of individual claims of the following form:

`admin`
Access to admin-level services.
`readAs:<Party Name>`
Read access for the given party.
`actAs:<Party Name>`
Issue commands on behalf of the given party.
`applicationId:<Application Id>`
Restrict access to commands issued with the given application Id.

See :ref:`Access Tokens and Claims <authorization-claims>` for further information on Daml ledger capabilities.
197 changes: 197 additions & 0 deletions docs/source/tools/auth-middleware/oauth2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
.. Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
.. SPDX-License-Identifier: Apache-2.0
OAuth 2.0 Auth Middleware
#########################

Daml Connect includes an implementation of an auth middleware that supports `OAuth 2.0 Authorization Code Grant <https://oauth.net/2/grant-types/authorization-code/>`_.
The implementation aims to be configurable to support different OAuth 2.0 providers and to allow custom mappings from Daml ledger claims to OAuth 2.0 scopes.

OAuth 2.0 Configuration
~~~~~~~~~~~~~~~~~~~~~~~

`RFC 6749 <https://tools.ietf.org/html/rfc6749#section-3>`_ specifies that OAuth 2.0 providers offer two endpoints:
The `authorization endpoint <https://tools.ietf.org/html/rfc6749#section-3.1>`_
and the `token endpoint <https://tools.ietf.org/html/rfc6749#section-3.2>`_.
The URIs for these endpoints can be configured independently using the following flags:

- ``--oauth-auth``
- ``--oauth-token``

The OAuth 2.0 provider may require that the application identify itself using a client identifier and client secret.
These can be specified using the following environment variables:

- ``DAML_CLIENT_ID``
- ``DAML_CLIENT_SECRET``

The auth middleware assumes that the OAuth 2.0 provider issues JWT access tokens.
The ``/auth`` endpoint will validate the token, if available, and ensure that it grants the requested claims.
The auth middleware accepts the same command-line flags as the :ref:`Daml Sandbox <sandbox-authorization>` to define the public key for token validation.

Request Templates
*****************

The exact format of OAuth 2.0 requests may vary between providers.
Furthermore, the mapping from Daml ledger claims to OAuth 2.0 scopes is defined by the IAM operator.
For that reason OAuth 2.0 requests made by auth middleware can be configured using user defined `Jsonnet <https://jsonnet.org/>`_ templates.
Templates are parameterized configurations expressed as top-level functions.

Authorization Request
=====================

This template defines the format of the `Authorization request <https://tools.ietf.org/html/rfc6749#section-4.1.1>`_.
Use the following command-line flag to use a custom template:

- ``--oauth-auth-template``

Arguments
^^^^^^^^^

The template will be passed the following arguments:

- ``config`` (object)
- ``clientId`` (string) the OAuth 2.0 client identifier
- ``clientSecret`` (string) the OAuth 2.0 client secret
- ``request`` (object)
- ``claims`` (object) the requested claims
- ``admin`` (bool)
- ``applicationId`` (string or null)
- ``actAs`` (list of string)
- ``readAs`` (list of string)
- ``redirectUri`` (string)
- ``state`` (string)

Returns
^^^^^^^

The query parameters for the authorization endpoint encoded as an object with string values.

Example
^^^^^^^

.. code-block:: none
local scope(claims) =
local admin = if claims.admin then "admin";
local applicationId = if claims.applicationId != null then "applicationId:" + claims.applicationId;
local actAs = std.map(function(p) "actAs:" + p, claims.actAs);
local readAs = std.map(function(p) "readAs:" + p, claims.readAs);
[admin, applicationId] + actAs + readAs;
function(config, request) {
"audience": "https://daml.com/ledger-api",
"client_id": config.clientId,
"redirect_uri": request.redirectUri,
"response_type": "code",
"scope": std.join(" ", ["offline_access"] + scope(request.claims)),
"state": request.state,
}
Token Request
=============

This template defines the format of the `Token request <https://tools.ietf.org/html/rfc6749#section-4.1.3>`_.
Use the following command-line flag to use a custom template:

- ``--oauth-token-template``

Arguments
^^^^^^^^^

The template will be passed the following arguments:

- ``config`` (object)
- ``clientId`` (string) the OAuth 2.0 client identifier
- ``clientSecret`` (string) the OAuth 2.0 client secret
- ``request`` (object)
- ``code`` (string)
- ``redirectUri`` (string)

Returns
^^^^^^^

The request parameters for the token endpoint encoded as an object with string values.

Example
^^^^^^^

.. code-block:: none
function(config, request) {
"client_id": config.clientId,
"client_secret": config.clientSecret,
"code": request.code,
"grant_type": "authorization_code",
"redirect_uri": request.redirectUri,
}
Refresh Request
===============

This template defines the format of the `Refresh request <https://tools.ietf.org/html/rfc6749#section-6>`_.
Use the following command-line flag to use a custom template:

- ``--oauth-refresh-template``

Arguments
^^^^^^^^^

The template will be passed the following arguments:

- ``config`` (object)
- ``clientId`` (string) the OAuth 2.0 client identifier
- ``clientSecret`` (string) the OAuth 2.0 client secret
- ``request`` (object)
- ``refreshToken`` (string)

Returns
^^^^^^^

The request parameters for the authorization endpoint encoded as an object with string values.

Example
^^^^^^^

.. code-block:: none
function(config, request) {
"client_id": config.clientId,
"client_secret": config.clientSecret,
"grant_type": "refresh_code",
"refresh_token": request.refreshToken,
}
.. _oauth2-middleware-deployment:

Deployment Notes
~~~~~~~~~~~~~~~~

The auth middleware API relies on sharing cookies between the auth middleware and the Daml application.
One way to enable this is to expose the auth middleware and the Daml application under the same domain, e.g. through a reverse proxy.
Note that you will need to specify the external callback URI in that case using the ``--callback`` command-line flag.

For example, assuming the following nginx configuration snippet:

.. code-block:: nginx
http {
server {
server_name example.com
location /auth/ {
proxy_pass http://localhost:3000/;
}
}
}
You would invoke the OAuth 2.0 auth middleware with the following flags:

.. code-block:: shell
oauth2-middleware \
--callback https://example.com/auth/cb \
--port 3000
Some browsers reject ``Secure`` cookies on unencrypted connections even on localhost.
You can pass the command-line flag ``--cookie-secure no`` for testing and development on localhost to avoid this.

.. TODO[AH]: Add an example Auth0 configuration as described in triggers/service/auth/src/main/scala/com/daml/auth/middleware/oauth2/README.md .
Loading

0 comments on commit 7543c6f

Please sign in to comment.