hasura-auth icon indicating copy to clipboard operation
hasura-auth copied to clipboard

Webhooks

Open sean-nicholas opened this issue 2 years ago • 3 comments

I wanted to discuss webhooks with you and would love to hear your thoughts.

Exemplarily scenarios

  • Send magic link via slack / teams instead of email
  • Add http based email services like sendgrid / MailChimp
  • Send sms with other providers
  • Customize mail templates conditionally (users from domain X get another mail than users from domain Y)
  • Add custom claims conditionally
  • Custom oAuth providers
  • Check custom password block list (e.g. contains company name)
  • Disable sign up / login conditionally (could solve #157 & #85)
  • Conditional redirect urls (could solve #53)

How to provide the webhook config?

  • The simple way: Just add an env var with an URL.
  • The advanced way: Env var with URL and additional config (like maxRetries) as JSON.
  • The even more advanced way: Save the config in hasura and add a dashboard to nhost cloud.

Pros

  • 🔧 Highly customisable
  • 🫶 Natural fit with nhost functions
  • 🧑‍🤝‍🧑 Community could develop extension & share them (nhost could create a store in the long term)
  • 📉 Less issues because users can implement features themself
  • 😌 Simple implementation of webhooks is easy

Cons

  • 😫 Sophisticated implementation of webhooks is hard (but could be fun 😁). For example: retries, rate limits, security
  • ⏳ Additional roundtrips for every request (could be "slow" in combination with lambda cold starts or if the function is timing out)

sean-nicholas avatar May 26 '22 21:05 sean-nicholas

I'm not sure I understand exactly what you mean here. Could you explain a scenario from start to finish and how webhooks would be involved?

elitan avatar Jun 01 '22 18:06 elitan

Here are a few use cases:

Send magic link via slack / teams instead of email

  • You are creating an app for a single company only that uses it inhouse. For easy access the users should get a passwordless magic link. But the requirement from the company is that the link should be send by slack not by mail (for example because mail is always delayed by 5 mins due to spam filtering)
  • You set the AUTH_WEBHOOK_BEFORE_SEND_PASSWORDLESS_LINK to
    {
      "url": "https://your-lambda/auth-webhooks/beforeSendPasswordlessLink",
      "timeout": 5000
    }
    
  • nhost/hasura-auth/src/routes/signin/passwordless/email.ts calls the webhook with the user and the link and waits for the response:
    // Existing code:
    const template = 'signin-passwordless';
    const link = createEmailRedirectionLink(
      EMAIL_TYPES.SIGNIN_PASSWORDLESS,
      ticket,
      redirectTo
    );
    // New Webhook Code:
    const webhookResponse = await webhookLib.beforeSendPasswordlessLink({ user, link })
    
  • The lambda gets the user and link via post. It queries the slack information from hasura (with admin secret) and posts the link to the user in a private slack message. The lambda returns the following response:
    {
      "continue": false
    }
    
  • signInPasswordlessEmailHandler then checks the response if it has to send the link or not:
    if (webhookResponse.continue === false) return
    
    • It stops because it does not need to send the link via mail anymore

Add http based email services like sendgrid / MailChimp

  • Currently mails can only be send via SMTP. If you are using sendgrid or Mailchimp they have a transactional mail REST api. You want to use that api.
  • You set the AUTH_WEBHOOK_BEFORE_SEND_EMAIL to
    {
      "url": "https://your-lambda/auth-webhooks/beforeSendEmail",
      "timeout": 5000
    }
    
  • Here are more changes needed. So imagine there is a custom mail client with a send function in nhost.
  • The send function calls the webhook with the template and mail headers (to, subject, cc, bcc, etc.)
  • The webhook sends the mail via sendgrids / mailchimps REST api
  • The webhook returns { "continue": false }
  • The send function does not send the mail via SMTP

Customize mail templates conditionally (users from domain X get another mail than users from domain Y)

  • You have a SaaS that has tenants. For every tenant new users can register. The users will be matched to the tenant by mail. Every tenant should have a different email template for signup / password reset.
  • You set the AUTH_WEBHOOK_BEFORE_EMAIL_TEMPLATE_CREATION to
    {
      "url": "https://your-lambda/auth-webhooks/beforeEmailTemplateCreation",
      "timeout": 5000
    }
    
  • The lambda gets all the the data it needs via post and returns the following individual template:
    {
      "renderedTemplate": "<html [...]"
    }
    
  • The email lib will use that template instead of the local

Check custom password block list (e.g. contains company name)

  • Often bad passwords in companies are based on the company name. For example: nhostWinter2022 or something. That password is not in the hibp list.
  • Your client wants to disallow all passwords that contain the company name.
  • I think you can imagine now how this would work :) Instead of sending the password to hibp it sends it to your custom lambda.
  • Well, now that I'm thinking about it this could be a security problem if SSL wasn't checked properly or something. So care should be taken with this feature ^^
  • The lambda would return something like { "passwordIsPwned": true }

Disable sign up / login conditionally

  • You have this fancy new startup idea and want to allow signup only on Friday afternoons to make it super rare.
  • Before each signup a webhook lambda is asked if the signup is active
    • the lambda gets the user details so it could decide that VIP users with mail [email protected] are always able to login for all the other mails it must be Friday.
    • the lambda returns something like { "registeringIsActive": false }

I hope this makes my idea clear and shows how powerful such a feature could be. People could build so many extensions and the nhost auth core doesn't have to be polluted. For example the hibp check could easily be a webhook.

sean-nicholas avatar Jun 02 '22 20:06 sean-nicholas

It's basically a plugin system but programming language agnostic and without the hassle of installing and managing plugins

sean-nicholas avatar Jun 03 '22 15:06 sean-nicholas

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar May 11 '23 15:05 stale[bot]