How to authenticate members with other services
(Draft)

Ghost is awesome, but maybe it doesn't do everything you need, and you need to have a separate function that lives somewhere else provide some service to your Ghost users. This is doable, but it'll take some cloud function "glue" (or some api endpoints on your own server – the flow doesn't change much).
I like either Netlify or Cloudflare for hosting logic of this sort, where I don’t really need a full server.
The way you verify if a user is subscribed is:
- Client side (browser-based) javascript runs and gets the user’s session (a jwt) from
/members/api/session
. - The client side script makes a request to your cloud function, including the session data.
- Your cloud function uses the jwks available at
/members/.well-known/jwks.json
to validate the jwt. (Don't look this up every time – store it!) - Your cloud function makes an admin api request to
/ghost/api/admin/members/?filter=${encodeURIComponent(filter)}
(where filter isemail:'${email}'
)to get the information you need about the member (subscription status, tier, any labels, etc) - Your cloud function retrieves the post content requested from the browser way back in step 2.
- Your cloud function returns the post content to the user’s browser.
It sounds like a lot, but it’s pretty fast. You can speed it up by having your cloud function set up its own cookie containing a jwt , so that you can simplify the subsequent requests to:
- User’s browser makes a request, including the cookie containing the cloud function-created jwt.
- Cloud function verifies the jwt
- Cloud function retrieves the content from the admin API
- Cloud function returns the content to the browser
Another option would be to work with your reverse proxy to make the cloud function endpoints appear to be on your Ghost domain. (They might be on your same server if you're self-hosting, or not.) That allows you to have your cloud function receive the user’s cookie and then make a request to /members/api/member
using the member’s cookie. That response may have enough information that you can skip several of the steps above and go right to retrieving the requested content. It doesn't sound a lot shorter, but it sets you up to let the user navigate the site normally (no extra javascript), with your cloud function constructing the response on the fly, rather than serving the user a page without content, then filling in the content with javascript. It hides more of the flow from the user and (assuming you've got your proxy set up correctly) may simplify matters quite a bit.