Permissions Matrix
OSO MS Teams CLI uses delegated Microsoft Graph permissions for normal user actions. Delegated permissions allow the CLI to act on behalf of the signed-in user after Microsoft sign-in and consent.
Current OSO app scopes
The default OSO public client app currently requests these delegated scopes:
| Scope | Used for | Consent and security note |
|---|---|---|
User.Read | Sign in and read the signed-in user's basic profile. | Baseline delegated sign-in scope. |
offline_access | Keep the profile signed in without prompting every command. | Creates refresh-token material in the local credential store. |
Team.ReadBasic.All | List teams and resolve team IDs. | Review tenant policy for team discovery. |
Channel.ReadBasic.All | List channels and resolve channel IDs. | Required for channel workflows. |
ChannelMessage.Send | Send channel messages. | Messages are sent as the signed-in user. |
Chat.ReadWrite | Work with chat objects and chat workflows. | High-impact delegated chat access. |
ChatMessage.Read | Read chat messages. | Meeting or restricted chats can still deny reads. |
ChatMessage.Send | Send chat messages. | Messages are sent as the signed-in user. |
User.ReadBasic.All | Resolve users for member and mention workflows. | Exposes basic directory profile data through Graph. |
Presence.Read.All | Read user presence. | Tenant policy can restrict presence access. |
Presence.ReadWrite | Set, clear, and set a status message on your own presence. | Writes only the signed-in user's own presence. Microsoft does not mark it admin-consent required, unlike Presence.ReadWrite.All. |
Presence.ReadWrite joined the default set after the presence write commands were fixed. A session created before that keeps the scopes it was granted, so run teams auth login again to consent to it — teams auth refresh cannot add a scope that was never consented to. A login that names its own scopes (--scopes, TEAMS_CLI_SCOPES, or a profile scopes value) replaces the default set rather than extending it, so restate the whole list with Presence.ReadWrite in it.
The default does not request ChannelMessage.Read.All, because Microsoft marks that delegated Graph scope as admin-consent required. Add it explicitly with --scopes or use a customer-owned app when a workflow needs channel message reads.
Profiles can pin broader scope sets for a workflow:
[profiles.attachments]
scopes = "User.Read People.Read Chat.ReadWrite ChatMessage.Read ChatMessage.Send ChannelMessage.Send ChannelMessage.Read.All Files.Read.All Files.ReadWrite Files.ReadWrite.All offline_access"
After an admin grants consent, run teams auth refresh --profile attachments to redeem the stored refresh token for the resolved profile scopes.
Feature mapping
| Feature | Normal permission model | Notes |
|---|---|---|
| Sign in and profile | Delegated User.Read | Default login path. |
| Team and channel discovery | Delegated Team.ReadBasic.All, Channel.ReadBasic.All | Required before channel operations. |
| Channel message send | Delegated ChannelMessage.Send | App-only normal sends are blocked. |
| Channel message read | Delegated ChannelMessage.Read.All | Broad channel-read permission; admin review recommended. |
| Chat message send | Delegated ChatMessage.Send | App-only normal sends are blocked. |
| Chat read | Delegated ChatMessage.Read or Chat.ReadWrite | Meeting chats may still deny access. |
| Chat quote-reply | Delegated ChatMessage.Send | message send --quote uses Graph's replyWithQuote; delegated only. |
| Chat message delete and restore | Delegated Chat.ReadWrite | message delete / message undelete use softDelete / undoSoftDelete on your own messages; delegated only. |
| Channel message delete and restore | Delegated ChannelMessage.ReadWrite | Admin-consent required, so not in the default set: grant it with teams auth consent-url --scopes ..., then sign in with it. |
| Presence read | Delegated Presence.Read.All | Tenant policy can restrict. |
| Presence write | Delegated Presence.ReadWrite | presence set, presence set-preferred, presence status, presence clear, and presence clear-preferred. Delegated only — the commands reject an app-only token locally, because they act on /me. |
| User lookup | Delegated User.ReadBasic.All; People.Read improves user resolve. | user resolve verifies People API hits through /users/{userPrincipalName} before returning an object ID. |
| Inline image read/download | Same message-read scope as the message. | Pasted images are Graph hosted contents. No file scope is needed. |
| Message file attachment download | Delegated Files.Read.All. | File references point at SharePoint/OneDrive and are downloaded through Graph shares. |
| Message file attachment send | Delegated Files.ReadWrite for chats; Files.ReadWrite.All for channels. | --attach uploads to OneDrive or the team's SharePoint library before sending the message. For a chat, the same scope lets the CLI grant the chat's members read access to the uploaded file; that step also reads the roster, which Chat.ReadWrite in the default set covers. |
| Channel files | Delegated file scopes such as Files.ReadWrite.All depending on operation. | Use BYO app if you need tight scope control. |
| App-only admin reads | Application permissions where supported. | Validate per Graph endpoint. Not the normal CLI message model. |
Use auth doctor to inspect token audience, scopes, and roles.
For the admin-facing trust model, read Security and Consent.