Kal Kal - 9 days ago 6
PHP Question

Drupal 8 external/custom authentication provider

I am experimenting with Drupal 8 as our customer websites. Our customers authenticate through our own authentication application at the moment which speaks to our document store (instead of MySQL) to authenticate a user and provide them with a unique session ID (JWT eventually but that's another day and conversation) which we can use to then query a REST API and get user data in any of our other self apps.

We are moving over from an old JSP based websites to drupal as our apps are now written in Symfony 3 but want our customer websites to be Drupal 8.

Here's the bit I am trying to work out. If I authenticate in our old website I want to be able to redirect to the Drupal 8 website with the session ID we have in our hand and use that to fetch a object back of our logged in user. I have this bit working fine but I now am in a position to say... Ok I have the user object back, the 3rd party service has said that session ID is valid so we know we are authenticated.

Please refer to the below flow chart. I want to be able to also authenticate in Drupal 8 manually. Is this possible (I am sure it is) and if so can someone point me in the right direction as to what I need/should be doing, API's I should be calling?

enter image description here

Thank you kindly and good day :)

Kal Kal
Answer

Ok so it turned out not to be that tricky in the end. I thought I would have to extend and implement various class and create my own provider (which is probably the best practice) but for KISS sake I found another way.

Create a user first if one does not exists based on the user data I get back from my external service. Then pass that created user to the user_login_finalize method (why are a lot of methods underscored Drupal...) which then authenticated my user.

public function inbound(Request $request)
{
    // Point the guzzle client to our external session service.
    $client = new GuzzleHttpClient([
        'base_uri' => 'https://myexternalservice.com/apps/authentication/2/',
    ]);

    // Attempt to send to request with the session ID from the parameters.
    try {
        $response = $client->request('GET', 'api/v1/user/' . $request->get('session_id'));
    } catch (\Exception $e) {
        throw new \HttpException($e->getMessage());
    }

    // Convert the response to an array.
    $result = json_decode((string) $response->getBody(), true);

    // Convert our array to a user entity.
    if ($user = $this->convertResponseToUser($result['user'])) {
        try {
            // Attempt to load the user. If the user does not exist then create them first.
            if (!$assumeUser = user_load_by_mail($user->getEmail())) {
                // Create a Drupal user object.
                $assumeUser = $this->createUser([
                    'name' => $user->getFirstName() . ' ' . $user->getLastName(),
                    'mail' => $user->getEmail()
                ]);

                $assumeUser->save();
            }

            // Authenticate the user.
            user_login_finalize($assumeUser);
        } catch (\Exception $e) {
            drupal_set_message(t('An unhandled exception occurred during authentication.'), 'error');
            return $this->redirect('user.login');
        }
    }

    return $this->redirect('mymodule.route');
}