Problems verifying user registration by E-Mail | Create User from temporary page content

Heyho,

I’ve got a question regarding user authentication and authentication challenges.
I’m currently trying to get a user registration with an E-Mail authentication going.

I’ve seen that there are auth challenges, but to be quite honest, I have no idea how or where to use them.

So instead I have tried creating a temporary page with the user data and sending out my own link to the user. Once the user enters their password correctly, the user would be created and in the end, I’d delete this page.
In doing so however, I have run into difficulties creating the user once again. It seems to me like the $page values are not being accepted for the user creation. But I am unsure as to where the issue lies.

can anyone help me out?

My registration controller:

<?php

return function ($kirby, $site, $page) {

  // don't show the login screen to already logged in users
  // if ($kirby->user()) {
  //   go('/');
  // }

  $error = false;

  // handle the form submission
  if ($kirby->request()->is('POST') && get('registration') && !$page->isChildOf('registration')) {

    $email = get('email');
    $forename = get('firstname');
    $surname = get('lastname');
    $company = get('company_name');

    // try to create the user with the provided credentials
    try {

      if(get('type') == 'client-company'):
      $newUser = [
        'email' => $email,
        'role' => 'client-company',
        'language' => 'de',
        'password' => get('password'),
        'name' => $company,
        'company_name' => $company,
        'tel' => get('tel'),
        'fax' => get('fax'),
        'street' => get('street'),
        'housenumber' => get('housenumber'),
        'plz' => get('plz'),
        'city' => get('city'),
        'verified' => false
      ];

      elseif(get('type') == 'client'):
        $newUser = [
          'email' => $email,
          'role' => 'client',
          'language' => 'de',
          'password' => get('password'),
          'name' => $forename.' '.$surname,
          'firstname' => $forename,
          'lastname' => $surname,
          'tel' => get('tel'),
          'fax' => get('fax'),
          'street' => get('street'),
          'housenumber' => get('housenumber'),
          'plz' => get('plz'),
          'city' => get('city'),
          'occupation' => get('occupation'),
          'verified' => false
        ];

      else:
          throw new Exception();
  
      endif;

    } 
    catch (Exception $e) {
      $error = true;
    } 
    finally {


      $authCode = md5(uniqid("", true).random_bytes(20));

      $confirmlink = $site->url()."/registration/{$authCode}/";

      $site->find('registration')->createChild([
        'content' => $newUser,
        'template' => 'confirm',
        'slug' => $authCode,
        'draft' => false
      ]);

          if(get('type') == 'client-company'):

            $body = "{$site->find('registration')->email_company()->value()}\n\n";

            $body = str_replace("%link", $confirmlink, $body);
                
            $body = str_replace("%company", $company, $body);

            kirby()->email([
              "to" => get('email'),
              "from" => "{$site->find('registration')->emailsender()->value()}",
              "subject" => "{$site->find('registration')->email_companysubject()->value()}",
              "body" => $body
            ]);

          elseif(get('type') == 'client'):
            
            $body = "{$site->find('registration')->email_client()->value()}\n\n";

            $body = str_replace("%link", $confirmlink, $body);
                
            $body = str_replace("%forename", $forename, $body);
            $body = str_replace("%surname", $surname, $body);

            kirby()->email([
              "to" => get('email'),
              "from" => "{$site->find('registration')->emailsender()->value()}",
              "subject" => "{$site->find('registration')->email_clientsubject()->value()}",
              "body" => $body
            ]);


          else:
            return;

          endif;


    }

  }

  return [
    'error' => $error
  ];

};

My chaotic attempt at the confirmation controller:

<?php

return function ($kirby, $page, $site) {

  // don't show the login screen to already logged in users
  // if ($kirby->user()) {
  //   go('/');
  // }

  $error = false;

  // handle the form submission
  if ($kirby->request()->is('POST') && $page->template('confirm')) {

    try {

        if(get('authPassword') === $page->password()->value()):

          if($page->role()->value() == 'client_company'):

            $kirby->users()->create([
              'email' => $page->email()->value(),
              'role' => 'client-company',
              'language' => 'de',
              'password' => $page->password()->value(),
              'name' => $page->name()->value(),
              'content' => [
                'company_name' => $page->name()->value(),
                'tel' => $page->tel()->value(),
                'fax' => $page->fax()->value(),
                'street' => $page->street()->value(),
                'housenumber' => $page->housenumber()->value(),
                'plz' => $page->plz()->value(),
                'city' => $page->city()->value()
              
              ]
            ]);

            elseif($page->role()->value() === 'client'):

            $kirby->users()->create([
              'email' => $page->email()->value(),
              'role' => 'client',
              'language' => 'de',
              'password' => $page->password()->value(),
              'name' => $page->name()->value(),
              'content' => [
                'firstname' => $page->firstname()->value(),
                'lastname' => $page->lastname()->value(),
                'tel' => $page->tel()->value(),
                'fax' => $page->fax()->value(),
                'street' => $page->street()->value(),
                'housenumber' => $page->housenumber()->value(),
                'plz' => $page->plz()->value(),
                'city' => $page->city()->value(),
                'occupation' => $page->occupation()->value()
              
              ]
            ]);


          endif;

            
          // else:
          //   throw new Exception('Das eingegebene Passwort ist falsch. Bitte versuchen Sie es erneut.');

        endif;
      // redirect to the homepage if the login was successful
      // go('/');
    } catch (Exception $e) {
      $error = true;
    }

  }

  return [
    'error' => $error
  ];

};

My confirm template:

<?php snippet('header', array("default" => true)) ?>

    <?php 
    if($error): ?>
        <div class="alert"><?= $page->authAlert()->html() ?> hoi</div>
    <?php endif ?>

    <?php dump($page->errors())?>
    <?php dump(get('authPassword')) ?>
	<article class="viewDefault">
        <?php dump(get('registration')) ?>
        <form class="authentication" method="post" action="<?= $page->url() ?>">
    
            <div >
                <label for="authPassword"><?= $page->parent()->authPassword()->html() ?></label>
                <input required type="password" id="authPassword" name="authPassword" value="<?= get('authPassword') ? esc(get('authPassword'), 'attr') : '' ?>">
            </div>

            <div>
                <input type="submit" name="authentication" value="<?= $page->parent()->authButton()->html() ?>" onsubmit="">
            </div>

        </form>
	</article>

<?php snippet('footer') ?>

The most important issue here is that to be able to create a user or page etc., you need to authenticate, e.g. with $kirby->impersonate('kirby');

should be

$page->template()->name() === 'confirm'

This won’t output anything because there is no registration field in this form.

To enable login via an authentication challenge, the following steps are necessary:

  1. enable login via code in your config

  2. create a user when the registration form is submitted

  3. send an authentication challenge with

    $status = $kirby->auth()->createChallenge($email, false, 'login');
    
  4. Redirect the user to a confirmation page where they can enter the login code (the $status object is stored in the users session)

  5. On the confirmation page, check the status with

    $kirby->auth()->status()
    

Wonderful, now it works like a charm!
Thanks for the quick help!

If I have the time, I’ll try my hands at the auth challenge as well.
It seems like a way smarter way to handle the verification process.