The news on another origin than the app's: a marketing site, a help
centre, a page the app does not serve. The :embed feature.
{Tayori,
repo: MyApp.Repo,
pubsub: MyApp.PubSub,
secret_key_base: secret,
features: [:embed],
embed: [origins: ["https://www.atelier.app"]]}The JSON API (Tayori.API) answers the pages of those origins, and no
others: it gives them CORS headers, without credentials, so that a
browser never sends the app's cookies along. A reader there is not in
the app's session; the app's server says who they are with a token it
signs, token/1, which the page gives <tayori-news>:
<tayori-news
api="https://app.atelier.app/embed/news"
reader-token="<%= Tayori.Embed.token(@reader) %>"
></tayori-news>The element sends it in the authorization header
(Bearer <token>), and the API reads the reader from it: their id,
segments, language and the time they joined, as the app's resolver
gave them when the token was made. A token is valid for a day
(:max_age of the :embed option). Without one, or with one that is
not Tayori's, the API asks the app's resolver, and the reader is
otherwise a visitor; with one that has expired, it answers 401.
The token is a Phoenix.Token, signed with the app's :secret_key_base
and a salt of Tayori's own: no one can make one, or change the reader
in it, without the app's secret. Make one for the person the page is
for, on the server, and never from an id the browser sends.
The Any frontend guide has the whole setup.
Summary
Functions
A signed token of the reader, for <tayori-news reader-token="...">
on another origin. Raises for a visitor (a visitor needs no token) and
when the :embed feature is off.
The reader of a token of token/1: {:ok, reader}, or
{:error, :expired} for a token older than :max_age, and
{:error, :invalid} for anything else (a token Tayori did not sign, or
the :embed feature off).
Functions
@spec token(Tayori.Reader.t()) :: String.t()
A signed token of the reader, for <tayori-news reader-token="...">
on another origin. Raises for a visitor (a visitor needs no token) and
when the :embed feature is off.
@spec verify(String.t()) :: {:ok, Tayori.Reader.t()} | {:error, :expired | :invalid}
The reader of a token of token/1: {:ok, reader}, or
{:error, :expired} for a token older than :max_age, and
{:error, :invalid} for anything else (a token Tayori did not sign, or
the :embed feature off).