Allow TFA authentication through REST routes

Created on 13 July 2023, over 1 year ago
Updated 5 January 2024, 11 months ago

Problem/Motivation

Currently in TFA we provide no method to actually authenticate through REST endpoints,

Some authentication methods are more complex than others to protect.

HTTP Digest authentication for example has no standard provisions for providing an OTP code. We could use a secondary REST call or we could use the classic 'append the token to the password' method to provide protection for this service. Both of these might dicate opening a SESSION to keep track of the authentication OR that we provide an authentication endpoint that than provides an API key to be used in all requests after that.

Ultimately our decisions will impact API clients, and we need to figure out what works best for API clients.

Steps to reproduce

N/A

Proposed resolution

Provide a method where session based login can be protected by TFA
Evaluate how we handle other authentication methods.

Remaining tasks

TBD

User interface changes

TBD

API changes

TBD

Data model changes

TBD

✨ Feature request
Status

Closed: outdated

Version

2.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States cmlara

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @cmlara
  • πŸ‡¦πŸ‡ΊAustralia mingsong πŸ‡¦πŸ‡Ί

    In case anyone interested how to make TFA working with REST API at this stage, I would suggest following login process instead your custom REST API login form/page.

    1. Redirect your custom login URL to the Drupal login URL(/user/login) or Drupal login form.
    2. Inject your business logic into the Drupal login form via Drupal form alert hook function. Such as redirecting the user to a API landing page by the following codes.
      // URL string.
      $form_state->setRedirect('route', $args, $options);
      // Or a Drupal URL object.
      $form_state->setRedirectUrl($url);
      

    Once the user has signed in with TFA, then the browser will remember the user session via cookies. After this point, the user will be able to access any API or non-API pages as long as the user has the permission to do so.

  • πŸ‡¦πŸ‡ΊAustralia mingsong πŸ‡¦πŸ‡Ί

    Is the TFA Web Services sub module created for this purpose?

    The /Drupal/services_tfa/Plugin/ServiceDefinition::processRequest() function looks like a solution for it, right?

    https://git.drupalcode.org/project/tfa/-/blob/2.x/services_tfa/src/Plugi...

  • πŸ‡ΊπŸ‡ΈUnited States cmlara

    Is the TFA Web Services sub module created for this purpose?

    To be honest I question if tfa_services was every fully designed and implemented. It appears to have been brought in during Week 7 of the 2016 GSOC with the description of "Add Web Serivces To TFA, Add the missing reset form class". I assume this was a result of a direct conversation with the GSOC mentor as I've been unable to find anything related to it otherwise.
    See: https://github.com/d8-contrib-modules/tfa/pull/57
    See: https://github.com/therealssj/GSoC2016-Final-Report

    A key point is at the moment it only validates a token is valid and provides an answer to the client without using the token to validate or control authentication.

    I've pushed up some code that I was originally working on the 1.x branch in parallel to working on on SA-CONTIRB-2023-030. I've rebased onto the 2.x branch but not tested it on 2.x It is very much a work in progress and shouldn't have an MR opened yet as I recall it had some edge cases that I needed to clean up, though I can't remember what they were at the moment. It also absolutely needed tests written.

    The main design of the code is that it intercepts the user.authentication.cookie service, ensuring that authenticate() only approves sessions that have provided a token, otherwise they cant receive 'authentication' status. In theory by being at the authentication provider we actually should be able to lock down security going forward, issues like πŸ› User login via route user.login.http bypasses TFA Closed: outdated in theory wouldn't be possible for session based authentication anywhere, as if any route provides session authentication it wouldn't get approval from the TFA cookie service.

    I'll note that this only covers SESSION based authentication, we would have to discuss how to handle other methods such as basic_auth and other random authentication (may require that we maintain a whitelist and de-register unknown method, or make it very clear that TFA is not protecting those methods.)

    There are other methods for session as well, instead of using the tfa_services module we could extend/replace the existing user.login.http route and either use the 'password+token" method, there are multiple formats or we could add our own field onto the existing route and decode it for the token.

    This part is really more a "whats the cleanest api"

    ✨ Increase security with single failure for login, password, and tfa Postponed: needs info comes into play as well regarding design on if we choose to use 'multiple requests' or 'single request'. I'm honestly more partial to single request as that prevents knowing if the password or the token was invalid.

  • πŸ‡ΊπŸ‡ΈUnited States cmlara

    Opened πŸ“Œ Decorate the user.auth service Fixed as another possible solution. Discussing in its own issue as it touches on a few more areas than just the REST, however it would allow us to protect known password based authentications without significant overhauls and without interfering with other formats such as API access keys that are not password based.

    A user would authenticate using the ldap/radius style format for the password where the password field becomes a combination of password and token. There are several styles of this such as:

    $password . $token
    $password . '+' . $token // '+' may be any character or even multiple characters in theory)
    // The above two but reversed order.
    $token . $password
    $token .  '+' .  $password
    
  • πŸ‡ΊπŸ‡ΈUnited States cmlara

    Looking at πŸ“Œ Decorate the user.auth service Fixed I believe that is a cleaner method of implementing the authentication validation for REST than what I have submitted into this issue so far.

    I would suggest we adopt πŸ“Œ Decorate the user.auth service Fixed and just use this issue to determine if we want to make any additional changes to REST API, such as adding explicit fields or routes. We may also want to remove tfa_services if it provides no actual security features.

  • πŸ‡΅πŸ‡ΉPortugal jcnventura

    And in a related path, we should deprecate and remove the tfa_services module: πŸ“Œ Deprecate the services_tfa module Active

  • Status changed to Closed: outdated 11 months ago
  • πŸ‡ΊπŸ‡ΈUnited States cmlara

    This was solved by πŸ“Œ Decorate the user.auth service Fixed .

Production build 0.71.5 2024