How To Continue An Auth0 Login Action

in my auth0 app, i have a paywall that is redirected to if the user has not paid yet or if they are on their first login to make sure they have to pay

it redirects them to a checkout page that when a button is clicked, it redirects to a new stripe checkout page that the user pays on and is redirected back to the /continue endpoint with the same session token sent to the checkout page, but i am not getting sent back to the home page and logged in and sent to blank page of my site with /continue route and the session token in the URL and my footer on the top of an empty page

btw, the continue code just needs to change the isPaid metadata to true and then just log the user in normally in the default manner

and payment is a success or else it wouldn’t redirect to the success url

why?

here’s my code

AUTH0 ACTION

/**
* Handler that will be called during the execution of a PostLogin flow.
*
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
  try {
    const isPaid = event.user.app_metadata.isPaid;

    if (event.stats.logins_count !== 1 && isPaid) {
      return;
    } else {
      if (event.user.app_metadata.stripe_customer_id) {
          const sessionToken = api.redirect.encodeToken({
            secret: event.secrets.NEW_STATE,
            payload: {
              customerId: event.user.app_metadata.stripe_customer_id,
            },
          });
          console.log(sessionToken)

          // Redirect the user to the Stripe checkout page with session_token query parameter
          api.redirect.sendUserTo('https://www.************.com/checkout', { 
            query: 
            { 
              session_token: sessionToken, 
              redirect_uri: `https://www.**************.com/continue`,

            },

          });
      }
      
    }
  } catch (error) {
    console.error(error.message);

    api.access.deny(
      "We could not create your account, problem with stripe redirection.\n" +
        "Please contact support for assistance."
    );
  }
};

exports.onContinuePostLogin = async (event, api) => {

  try {

    let decodedToken;

    decodedToken = api.redirect.validateToken({
      secret: event.secrets.NEW_STATE,
      tokenParameterName: 'session_token',
    });
    console.log(decodedToken)
    if(decodedToken) {
      api.user.setAppMetadata("isPaid", true);
    } 

  } catch (error) {


    return api.access.deny('Error occurred during redirect.');

  }
  

};

CHECKOUT.TSX

import React from 'react';
import { useAuth0 } from '@auth0/auth0-react';
import Stripe from 'stripe';
import queryString from 'query-string';
import jwt, { JwtPayload } from 'jsonwebtoken'; // Import the JWT library

const stripe = new Stripe('*************************************************', {
  apiVersion: '2022-11-15',
});

const Checkout = () => {
  const sessionToken = '*********************************'
  const { user } = useAuth0();
  //const [customerId, setCustomerId] = useState(null);


  //const customerId = user?.app_metadata?.stripe_customer_id;
  //console.log(customerId)
  const priceId = '****************************'
  const successUrl = 'https://www.***********.com/continue'
  const cancelUrl = 'https://www.*********.com/about'


  async function createCheckoutSession() {
    // Parse the URL to get state and redirect_uri
    const parsedUrl = queryString.parse(window.location.search);
    const sessionToken = parsedUrl.session_token;
    const customerId = parsedUrl.customerId;
    const redirectUri = parsedUrl.redirect_uri;
    // Check if the state and redirectUri exist
    if (sessionToken && redirectUri) {
      // Create the checkout session with state in the success_url
      //const validCustomerId = typeof customerId === 'string';
      //if(validCustomerId){
        const session = await stripe.checkout.sessions.create({
          customer: user?.app_metadata?.stripe_customer_id,
          payment_method_types: ['card'],
          line_items: [{ price: priceId, quantity: 1 }],
          mode: 'subscription',
          success_url: `${redirectUri}?session_token=${sessionToken}`,
          cancel_url: cancelUrl,
        });
        
      if (session.url) {
        window.location.href = session.url; // Redirect to Stripe checkout page
      }
      //}

    };
  }

  return (
    <div>
      <br></br><br></br><br></br>
      {/* Render your component's content */}
      <button onClick={createCheckoutSession}>Click Here To Checkout For Our ECOmium Plan!</button>
    </div>
  );
};

export default Checkout;

Hi Harish!
When you get redirected to the checkout page from the action, auth0 sends you a state parameter in the url. You would need to keep the state parameter value and later when you would want to continue login provide the state value. Your continue url should look something like this:
https://{Auth0-Domain}/continue?state={state-value}
I hope this helps. :slight_smile:

i am saving that value under the session_token - is there a difference between saving that under a session_token or a state in how it is validated

i tested that and it doesn’t make a difference

is there any other reason the redirect might not continue and reactivate the login flow

Saving the state value in a session token should not be an issue. I would just compare the initial and final values to ensure that some sort of encoding didn’t cause a problem. Also, are you using any custom domain? Does your continue endpoint look like https://{Auth0-Domain}/continue?state={state-value} ?