# Session.CurrentUser

> `Session.CurrentUser` is the person the app is being shown to, as your own `[Principal]` entity. Read it in a member, in a render expression, or straight inside an action — the compiler puts the read where it belongs, so `Owner = Session.CurrentUser` in a Save button means what it looks like it means. A single scalar of it (`Session.CurrentUser.Email`, `.Id`) costs no round trip at all. It is null for a visitor who has not signed in.

<!-- id: ui-current-user · area: ui · stability: stable · html: https://osysharp.com/reference/ui/current-user/ -->

## Signature      {#signature}
```osy syntax
Session.CurrentUser          // your [Principal] entity — the signed-in person. Null when nobody is.
Session.CurrentUser.Email    // any SCALAR of theirs — resolved in place, no round trip
Session.SignOut()            // the other end of the session — drops the ticket, back to the login page
```

Available in every component, with no `using`. Requires the app to declare a `[Principal]` entity.

## Summary        {#summary}
`Session.CurrentUser` is the signed-in principal — a row of whatever entity your app marked `[Principal]`, with the
fields you declared on it. It is **null when nobody is signed in**, which is the honest answer and the reason a page
that needs a user should say so with routing rather than by checking here.

You can read it in any of the three places a component holds a value, and you do not have to know which:

- as a **member** — `var me = Session.CurrentUser;` — the whole row, fetched when the page loads;
- in a **render expression** — `Text(Session.CurrentUser.Email)`;
- inside an **action** — `new Order { Reference = reference, Owner = Session.CurrentUser };`

The third one is the one that used to need a workaround. It does not any more: the compiler hoists the read onto the
component and the action closes over it, which is precisely what you would have written by hand.

## Description    {#description}

### Its type: your one kind of account        {#type}
On the kits, the `[Principal]` is the Identity kit's base `Principal`, and your app signs people in as a type that
derives from it — `User` from the UserAccounts kit, or your own `entity Member : Principal`. When the app has exactly
**one** concrete type derived from its `[Principal]`, `Session.CurrentUser` IS that type, so its own fields are there
with no cast:

```osy syntax
var me = Session.CurrentUser;      // a User, when User is the app's one kind of account
Text(me?.SecondFactorOnAt is null ? "Turn on two-step sign-in" : "Two-step sign-in is on");
```

With two or more (`User` and `Employee`), it is the base `Principal`, and `Session.CurrentUser is Employee` tells them
apart. `user` in a security rule is always the base: a rule describes every kind of account, including one a later
version adds.

### Reading a single field costs nothing        {#scalars}
A scalar of the principal — `Session.CurrentUser.Email`, `.Id`, or any column you declared — resolves **in place, on
whichever side is asking**, with no round trip. The browser reads it from the bag the server sent at boot, built
server-side, so a field your security rules mask reads as it does on the server — null, or a value type's default
([Security.IsMasked — was this value withheld from me?](https://osysharp.com/reference/security/is-masked/)) — in the browser too. Use it
freely in a render expression, a filter, or a field default:

```osy syntax
Text($"Signed in as {Session.CurrentUser.Email}");
live var mine = Order.Where(o => o.Owner.Id == Session.CurrentUser.Id);
```

Reaching **through** a reference (`Session.CurrentUser.Manager.Name`) is a different question — the browser holds the
manager as an id, not as a row — so that stays a server read and belongs on a member.

### The whole row, in an action        {#in-an-action}
An action runs in the browser, and the browser cannot run a database read in the middle of one. So when an action
mentions `Session.CurrentUser`, the compiler lifts the read onto the component as an ordinary fetched member and the
action reads that. Several actions on one page share one fetch.

```osy test app=ui-current-user
[Principal] entity User {
  [Required, MaxLength(200)] string Email;
  security { allow read when IsAuthenticated; }
}

entity Order {
  [Required, MaxLength(50)] string Reference;
  User Owner;
  security { allow read, create when IsAuthenticated; }
}

[Route("/orders/new")]
[Render(CSR)]
component NewOrder() {
  string reference = "";

  action Save() {
    new Order { Reference = reference, Owner = Session.CurrentUser };
    UnitOfWork.Commit();
  }

  render {
    Stack {
      Input(value: reference, placeholder: "Reference");
      Pressable(onClick: Save) { Text("Save"); }
    }
  }
}
```

⚠ **Other reads behave differently inside an action, and it is worth knowing which.** An ordinary read —
`Order.Where(…)` — is **not yet available inside an action**: bind it to a member and read the member instead. The
browser has no database, so a read in the middle of an action means a round trip at that moment; the compiler does not
yet arrange one. `Session.CurrentUser` needs no such arrangement — its value is fixed for as long as the page is open
(signing in or out reloads the app), so it is fetched with the page and simply read.

### It is who is being SHOWN the page, not who wrote the row        {#versus-audit}
A `[CreatedBy]` field on an entity ([[CreatedAt] [CreatedBy] [ModifiedAt] [ModifiedBy]](https://osysharp.com/reference/entity/row-stamps/)) is stamped **by the server** from the request's principal.
Your own field (`Owner` above) is the app's view; the stamp is the platform's, and no app code can write it. When you
want proof of who did something, declare the stamp and read it. When you want a relationship you control —
who a task is assigned to, whose basket this is — declare your own reference and set it.

### Nobody is signed in        {#anonymous}
`Session.CurrentUser` is null for an anonymous visitor, and asking whether it is null costs nothing — the comparison
is answered by the principal's id, which every side already holds:

```osy title="is anybody signed in — in a render, with no round trip" test app=ui-current-user-presence
[Principal] entity User {
  [Required, MaxLength(200)] string Email;
  security { allow read when IsAuthenticated; }
}

[Route("/")]
[AllowAnonymous]
[Render(CSR)]
component Home() {
  render {
    Stack {
      Text(Session.CurrentUser == null ? "Join us" : "Welcome back");
      if (Session.CurrentUser != null) { Text($"Signed in as {Session.CurrentUser.Email}"); }
    }
  }
}
```

That is the right tool for choosing what to SHOW. Do not use that null as a gate: a page that requires a user
should require one at the route (routed components are protected unless they say `[AllowAnonymous]`), so the page is
never rendered for someone who is not there. If you want a name for work done *before* sign-in, that is
[Visitor](https://osysharp.com/reference/ui/visitor/).

## See also       {#see-also}
- [Visitor](https://osysharp.com/reference/ui/visitor/) — the anonymous twin, for work that begins before there is a user
- [component](https://osysharp.com/reference/ui/component/) — members, actions, and where each kind of value lives
- [[security-auth-bootstrap#sign-out]] — `Session.SignOut()`, the verb that ENDS the session this page reads
- [principal predicates (IsAuthenticated / IsAnonymous / IsTheApp) and open reads](https://osysharp.com/reference/security/principal-predicates/) — the predicates that read the same principal in a `security { }` block
