Summary#
A policy names a reusable authorization predicate — a condition over the current user (user) that says
who is allowed. A page requires a policy with [Authorize(Name)]; a logged-in user who does not satisfy the
predicate is refused the page (the server returns it to no one who fails the check).
policy Admins => UserRole.Any(r => r.User == user && r.Role == Role.Admin);
[Page("/admin")]
[Authorize(Admins)]
component AdminPanel() { render { Text("secret"); } }The reference is a checked symbol, not a string: [Authorize(Admins)] names the declared policy Admins, so a
typo ([Authorize(Admin)]) is a compile error. A policy is declared once and reused across as many pages as need
it.
Signature#
policy Name => <predicate over `user`>; // a reusable named authorization predicate
[Authorize(Name)] component Page() { … } // require it — the principal must satisfy NameThe predicate is ordinary Osy#: it reads user (the current principal) and queries your data. A role check is the
common shape — RoleEntity.Any(r => r.User == user && r.Role == Role.X) — but any boolean predicate over the user
works.
Description#
Pages are protected by default (see routes and pages): a routed component requires an authenticated principal
unless it is [AllowAnonymous]. [Authorize(Name)] narrows that further — the authenticated principal must also
satisfy the named policy. If they don't, the page is refused.
policy Name => <predicate>;— declares the predicate once, by name. It readsuserand may query entities (typically a role-grant table). The same policy can gate many pages.[Authorize(Name)]— attaches the policy to a page. The reference is compile-checked against the declared policies; an unknown name fails the build.- Fail closed — a policy that cannot be resolved or evaluated refuses the page. If the named policy is missing or its predicate errors, the page is refused, never served — authorization never falls open.
Authorization is enforced on the server, when the page's definition is requested — so it holds regardless of what the client does.
Examples#
A role-gated admin page — a reusable Admins policy plus a page that requires it:
[Principal] entity User { string Email; }
[Role] enum Role { Admin, Viewer }
entity UserRole { [Required] User User; [Required] Role Role; }
policy Admins => UserRole.Any(r => r.User == user && r.Role == Role.Admin);
[Page("/admin")]
[Render(CSR)]
[Authorize(Admins)]
component AdminPanel() {
render { Text("Admin only"); }
}See also#
- routes and pages — protected-by-default routing and
[AllowAnonymous] - component — the page a policy gates
- creating & saving data — a create obeys the entity's write permissions, a related access check