I have a Rails API backend and a ReactJS frontend. My backend sends custom emails that often have confirmation-like links (like email confirmation)
Should the confirmation links point to my backend directly, or should they rather load the frontend first and then make an API call to the backend?
The two alternatives I'm thinking of are:
1 - The email confirmation link hits directly
backend.example.com/email_confirmations/:confirmation_token
, which then redirects to a specific success (error) page frontend.example.com/email_confirmation/success
(/failure
) on my frontend.
On the backend I would only need a Metal
controller with minimum modules to perform redirection to the frontend app, the controller is always responding with redirects). If further actions need to be taken from the frontend, they'll hit a different API Endpoint
2 - The email confirmation links opens up my frontend at
frontend.example.com/email_confirmations/:confirmation_token
that triggers an API request to backend.example.com/email_confirmations/:confirmation_token
.
Then my (Json:api) backend makes a jsonapi-compliant response with a Rails APIController
.
What are you doing in practice?
I decided to opt in for the first scenario but maybe systematically calling/loading the frontend first makes more sense?
How do you wire backend/frontend in those scenarios?
I have currently implemented a very simple (Metal
) Controller that would just process the incoming parameters perform redirections only to the frontend. I was hoping to define "url helpers" that would point to my frontend like so:
namespace :email_redirection do
# Controller that gets hit by email confirmation links in scenario #1
resources :confirmations
end
namespace :frontend do
frontend_root = Rails.configuration.frontend_host_with_http_and_port
scope frontend_root do
# Generation of URL Helpers for the frontend app
resources :confirmations, only: [] do
get 'successful'
get 'unsuccessful'
end
end
end
And my confirmation controller would be like
class EmailRedirection::ConfirmationsController
def index
svc = MyConfirmationService.new(token: params[:confirmation_token])
if svc.confirm
redirect_to(
frontend_successful_confirmation_url,
email: svc.confirmable.email
)
else
redirect_to(frontend_unsuccessful_confirmation_url)
end
end
end
I'm getting several error and I believe maybe the url helpers are not useable with different host/port... (or I have to pass them explicitely to each call)
How can I handle that ? And if 1. is a good choice, what would be the redirection codes you'd send on success/failure (since they can only be 3xx) ?
Both solutions involve quite some wiring between the backend/frontend and I'm not sure how to best wire things up.
Note : my models use devise but because devise isn't so great with APIs/etc. I'm using my own ConfirmationService that also handles some side-effects. I don't consider Devise to be relevant here