Tokens and who a request runs as
The sign-in routes answer { token, expires, userId }. Every other request sends the token as
Authorization: Bearer <token>.
- A token runs out after
TokenLifetime, 12 hours by default. Renew it withauth/refresh. A token whose user node was deleted is refused. auth/sessiongives a token to a visitor the site has already signed in, so an interface on the same site needs no second sign-in. Send it as JSON.SessionTokens = falseturns it off.- The default
ICmsApiTokensseals tokens with ASP.NET Core data protection, so they cannot be forged or read. Replace its registration to use tokens of another kind. - Tokens outlive a restart only when the data protection keys do. Keep the keys, or every restart signs everyone out:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(Path.Combine(builder.Environment.ContentRootPath, "keys")));The payload's context says how the user reads:
context |
Means |
|---|---|
culture |
read and write in this culture, such as nb-NO |
cultureFallback |
read a node with no version in the culture in another culture |
edit |
edit view: unpublished nodes too, with edit-view access checked beside read access |
hidden |
include nodes of hidden types |
revisions |
{ nodeId: revisionId }: which revision of a node to read and write (Revisions and cultures) |
collection |
the site the user works in: new nodes go in it (Sites) |
links |
"stored": HTML and Markdown with their links as # tokens, not as URLs |
An editor that writes back what it reads should use links: "stored", so its links stay links by id
however the URLs change. content-links says what the tokens point at.
Reads run as the user. Every query applies the user's read access, and so do get and
exists: they go through a query, because a read by id ignores read access.
Writes are open to every signed-in user. Restrict them with CmsApiOptions.Authorize. It is
called before every command with the caller and the command type (an upload as file-upload), and
false answers 403:
.AddApi(o => {
// only administrators and the editors group may use the API
o.Authorize = (ctx, command) => ctx.IsAdmin || ctx.IsInGroup(EditorsGroupId);
});Authorize sees only the command type, and a transaction is one command whatever its actions are.
A rule against delete must cover transaction too.
AllowAnonymous = true serves requests without a token as the anonymous visitor, for commands that
only read.