12.49. DD 49: Authentication

12.49.1. Summary

This design document specifies a simple authentication framework to be used by multiple Taler components that require authentication.

12.49.2. Motivation

SPAs currently store the username and password in locals storage (or at least session storage).

There’s also no way to manage auth tokens third parties (e.g. auditors).

12.49.3. Requirements

  • simple specification

  • simple implementation

  • simple to use

  • must cover two main use cases:

    • SPA login

    • delegating (possibly restricted) access to a third party using a token

12.49.4. Proposed Solution

We define a token endpoint that can be used to obtain access tokens from other forms of authentication, typically HTTP Basic auth.

12.49.4.1. Token Creation

POST /${RESOURCE...}/token

Create an authentification token.

Request:

interface TokenRequest {
  // Service-defined scope for the token.
  // Typical scopes would be "readonly" or "readwrite".
  scope: string;

  // Server may impose its own upper bound
  // on the token validity duration
  duration?: RelativeTime;

  // Is the token refreshable into a new token during its
  // validity?
  // Refreshable tokens effectively provide indefinite
  // access if they are refreshed in time.
  refreshable?: boolean;

  // Optional token description
  // @since v4
  description?: string;
}

Response:

200 Ok:

The response is a TokenSuccessResponse

Details:

interface TokenSuccessResponse {
  // Expiration determined by the server.
  // Can be based on the token_duration
  // from the request, but ultimately the
  // server decides the expiration.
  expiration: Timestamp;

  // Opque access token.
  access_token: string;
}

12.49.4.2. Token Revocation

Clients using session tokens log by forgetting the session token. Tokens can be explicitly revoked by making a DELETE request on the token endpoint.

DELETE /${RESOURCE...}/token

Invalidate the access token that is being used to make the request.

Authentication: The client must authenticate with a valid access token.

12.49.4.3. Token Information

List existing token informations.

GET /${RESOURCE...}/tokens

Request:

Query Parameters:
  • deltaOptional. Takes value of the form N (-N), so that at most N values strictly older (younger) than start are returned. Defaults to -20 to return the last 20 entries.

  • startOptional. Row number threshold, see delta for its interpretation. Defaults to smallest or biggest row id possible according to delta sign.

Response:

200 OK:

Response is a TokenInfos.

204 No content:

No tokens.

Details:

interface TokenInfos {
  tokens: TokenInfo[];
}
interface TokenInfo {
  // Time when the token was created.
  creation_time: Timestamp;

  // Expiration determined by the server.
  // Can be based on the token_duration
  // from the request, but ultimately the
  // server decides the expiration.
  expiration: Timestamp;

  // Service-defined scope for the token.
  // Typical scopes would be "readonly" or "readwrite".
  scope: string;

  // Is the token refreshable into a new token during its
  // validity?
  // Refreshable tokens effectively provide indefinite
  // access if they are refreshed in time.
  refreshable: boolean;

  // Optional token description
  description?: string;

  // Time when the token was last used.
  last_access: Timestamp;

  // Opaque unique ID used for pagination.
  row_id: Integer;
}

12.49.5. Definition of Done

  • DONE: spec reviewed

  • DONE: implemented in merchant backend

  • implemented in libeufin-bank

  • DONE: implemented in the bank webui SPA

  • implemented in the merchant backoffice SPA

12.49.6. Alternatives

  • use something much closer to OAuth2

    • would be unnecessarly generic and complex

12.49.6.1. Session Tokens / Signatures

For performance reasons, OAuth 2.0 uses two types of tokens: Short-lived access tokens and long-lived refresh tokens. The access tokens can be implemented via signatures and the long-lived refresh tokens via server-stored tokens. This allows to cheaply validate access tokens, while still allowing longer expiration times for refresh tokens.

We could do something similar by introducing login and session tokens. A login token is a server-stored token. In addition to being used directly as an access token, a login token can also be converted to a short-lived session token.

Session access tokens should be implemented as “self-encoded tokens”, i.e. as tokens signed by the server without requiring server-side token storage. Session access tokens should have a rather short maximum expiration.

The signature should be over (username, kind, scope, creation_timestamp, expiry).

To revoke session tokens, the server must store the timestamp of the last revocation and only accept tokens with a creation_timestamp larger than the last revocation timestamp. Individual session tokens cannot be revoked, only all issued session tokens can be revoked at once.

However, we decided against doing this because the performance benefits are not significant enough for us and having multiple token types would lead to unnecessary complexity.

12.49.7. Drawbacks

  • still more complex than simple auth tokens or HTTP basic auth

12.49.8. Discussion / Q&A

(This should be filled in with results from discussions on mailing lists / personal communication.)