Repository navigation
feat(outlook): Each user signs in, so a chat agent works on each user's own mailbox (1.0.0) - #4163
Open
ForeignKeyCN wants to merge 3 commits into
Open
ForeignKeyCN wants to merge 3 commits into
ForeignKeyCN wants to merge 3 commits into
Conversation
…'s own mailbox (1.0.0) - New "Each user signs in" mode on the API Key credential: the first time a chat user needs Outlook, the tool returns a Microsoft sign-in link (authorization code + PKCE); the plugin's new sign-in endpoint receives the browser's return, and the tools then act on that user's /me with their own token. - Per-user tokens are kept in plugin storage, keyed by a hash of the Dify user ID and Fernet-encrypted with a key derived from the client secret; never in tool output. - Refresh in the background; keep the refresh token when Microsoft omits a new one; ask to sign in again only when the refresh token is rejected. - Sign Out tool; the first answer after signing in names the account used. - Callback page warns about forwarded links and offers to cancel the sign-in. - Credential validation rejects a localhost Sign-in Callback URL. - README rewritten (en, zh_Hans, ja_JP) with a step-by-step guide and screenshots.
The new Agent exposes tools by their bare name and rejects duplicates, so an agent with Outlook and Teams (both had sign_out) failed with "Duplicate Dify Tool name".
…g links The events list only carried subject and times, so an agent asked "do I have any Teams meetings?" opened every event with Get Event. List Events now also selects location, bodyPreview, isOnlineMeeting and onlineMeeting; both tools show the location and the join link (Graph's, or a Teams/Zoom/Meet/Webex link pasted into the invitation) in the summary and as is_online_meeting / online_meeting_url.
This was referenced Nov 1, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Today every Outlook authorization is shared: with OAuth, everyone who uses the tool acts on the mailbox of the one person who signed in from the console; with a Service Principal, on a fixed mailbox. That doesn't fit the most common agent use case: an assistant that many people chat with, where "What's on my calendar today?" should mean the calendar of whoever is asking.
Dify's tool credentials are workspace-level, so this PR does it inside the plugin, without changing the existing modes:
Each user signs in (new Mode on the API Key credential)
GET /outlook/callback) receives the browser's return. It only stores the one-time code under the state the tool issued; it never sees the client secret or the PKCE verifier, so it cannot redeem the code itself. Unknown or expired states are rejected.client_id | Dify user IDand Fernet-encrypted with a key derived (HKDF) from the client secret. Tokens never appear in tool output or logs, so prompt injection cannot leak them. The user ID comes from Dify's runtime, never from the LLM.outlook_sign_out(forgets the calling user's sign-in, e.g. to switch accounts; in the other modes it explains that the credential is shared). It is not calledsign_out: the new Agent exposes tools by their bare name and rejects duplicates, so an agent with Outlook and Teams (which gets the same mode) would fail with "Duplicate Dify Tool name". The first answer after signing in names the account used.localhostcallback URL (Dify shows one whenENDPOINT_URL_TEMPLATEis left at its default), and for a specific tenant proves the client ID and secret with a client-credentials token that is then discarded./me.List Events / Search Events show online meetings
location,bodyPreview,isOnlineMeetingandonlineMeeting; both tools add the location and the join link to each line of the summary, and to the output variables asis_online_meeting/online_meeting_url.onlineMeeting.joinUrl), or else a Teams / Zoom / Google Meet / Webex link found in the invitation text: invites from other organizations and hand-pasted links are not flagged as online meetings by Graph.Docs
user, public web app per browser), security notes, and troubleshooting for every error we hit.readme/README_zh_Hans.md(which held English, Japanese and Chinese together) is now Chinese only;readme/README_ja_JP.mdadded. Old screenshots replaced.Existing OAuth and Service Principal authorizations keep working unchanged; the version goes to 1.0.0 because of the new mode and endpoint.
Release Notes
Change Type
Screenshots / Videos
Agent on a self-hosted Dify, using the Each user signs in authorization:
Testing
pytest), including the online-meeting link detection, the full sign-in, cached and refreshed tokens, per-user isolation and encryption at rest, secret rotation, revoked vs. temporarily failing refresh, a refresh response without a new refresh token, the callback rejecting unknown/expired/forged states, the cancel link, the account shown after sign-in, and the localhost check.Checklist
manifest.yaml(0.7.1 → 1.0.0)