Stripe customer authentication layer in kirby

hi forum!

i am figuring out what’s a good way to implement an authentication layer for Stripe, on a website running on Kirby:

the website has a subscription option, managed by Stripe; i need to add an option to allow users change their subscription options.

to do this there must be an authentication layer to verify that the email you fill in to change options for that customer account on Stripe, does belong to you.

my first idea was to use a simple one-time-password mechanism, where an email is sent to the subscriber with a temporary code that must be fill out on the website, before clicking Submit and tell Stripe this user is in fact who they say they are.

this would work, but i feel it’s not particularly robust, as it is the only authentication mechanism put in place, and using emails means plain-text. usually people suggest to use an app for this, like Authy, where you scan a QR code at the beginning and then you receive the pin code on your phone directly. this would be better in fact, but it requires users to download an app and set it up as a necessary step.

one way to use kirby would be by creating user accounts on it and set password for each of them, and then apply the OTP email mechanism for “double” security, but somehow we tried to avoid to make users create yet another password.

what do you think? anyone had already any experience with this?


Sending one-time auth codes via email is actually a pattern that is already used in the real world. For example Notion uses it and it works quite well.

As long as each code only works for one time, the impact on security is rather low – it is not possible to use codes an attacker has dug out from an email archive somewhere.

You can use Kirby’s session management to securely generate and verify such one-time auth codes:

  1. After the user has entered their email address, you would manually generate a session that is not transmitted to the browser. You can do this with $kirby->sessionHandler()->createManually().
  2. Place the email address and a special value that marks this type of session in the session data: ['email' => $email, 'type' => 'login-link']
  3. Send an email to the user with a link that contains the $session->token().
  4. Once the user opens the link, you can manually load the session object with $kirby->sessionHandler()->getManually($token). If you get a valid object back (= if no Exception is thrown), verify the type of the session. If that matches as well, you have a valid login and you can redirect the user to Stripe.
  5. Make sure to destroy the session with $session->destroy() before the redirect takes place.

thanks @lukasbestle! i was plotting a more complex scheme, but maybe i am over-thinking.

i’ll give this a try and will report back, thanks again for listing each step out :slight_smile:

Long delay before managing to get back to this, but I at last did.

Thanks @lukasbestle again for the detailed step by step explanation.

I have only one noob question left: I am sending the confirmation email through Mailchimp. This implies that I am sending the session token to Mailchimp, and then I use it as a Merge Tag in the automatic, API-based email workflow.

Is this dumb and defeating the whole point of making a custom session that does not get saved to the browser in the first place?

Of course this depends on your security requirements, also in the context of payment data being involved.

The general question with authentication schemes like this is: How can you ensure that the only person who can successfully authenticate is the user? In the end, there is never a definite answer to this question, you can only try to make the process as secure as possible (for example even with two-factor authentication it could be possible for an attacker to get access to both factors, even though it’s unlikely).

Sending the email via Mailchimp means that Mailchimp gets access to the tokens, so the question now becomes whether Mailchimp itself can be trusted for this and whether it is ensured that Mailchimp sends the email to the correct recipient. But in general it’s no different than using any other email provider.

So this risk is something you need to evaluate based on your requirements.

Thanks, makes sense.

We could rely on the in-built email server from the hosting provider and cut one extra party in the process. But as you said, these are evaluations to do on a project basis!