AI 资讯
OAuth Failure Recovery: Why I Choose Safe Retries for Authorization and Callback Steps
Short answer: Retry the transport operation, never the OAuth meaning: keep one durable authorization attempt, accept its callback once, and make every downstream effect replayable from recorded state. For a B2B SaaS account-deletion flow, I would block new sessions before attempting remote cleanup, because deleting data while a surviving session can still act is the more dangerous ordering. That is the architecture decision. It treats a timeout as missing knowledge, not proof of failure. A callback may have committed even when the browser received no response; a token exchange may have reached the other side even when the connection closed; an account deletion may be retried by a worker after its first lease expires. The recovery design must therefore answer a narrow question at each boundary: do we know the operation did not happen, do we know it happened, or is the result still unknown? What must remain true during OAuth failure recovery? The first invariant is that an authorization attempt has one identity independent of any HTTP request. Store an opaque flow identifier, the expected callback state, the account or tenant context, a creation time, an expiry, and a small state machine such as pending , exchanging , succeeded , or failed . Don't let a browser refresh create a second logical attempt merely because it creates a second request. The second invariant is single consumption. An authorization code and its state belong to one attempt; the callback handler must atomically claim that attempt before triggering side effects. A duplicate callback should read the previously recorded outcome and return the same application-level destination. It must not provision the user again, issue another internal session, or append a second audit event that claims a second login. Exactly once is the goal, but HTTP cannot promise it by itself, so I use an exactly-once mindset at the business boundary: an atomic database transition establishes who owns the work, unique constrain
AI 资讯
Don't Hand Your Inbox to an Agent
A Reddit thread on connecting Claude Code to a Yahoo Mail account turned into a solid field guide for scoping down what an AI agent is allowed to touch. Here's the distilled version. Don't give Claude Code your Yahoo password or unrestricted mailbox access. The risk isn't only the password leaking, it's that an agent with full access can read private messages, attachments, recovery details, and information about other people, all in the course of doing something mundane. Why "just connect it" is the wrong instinct The thread's most-quoted line frames the problem well: people are casually handing agents the keys to everything at once. People are talking about just giving ai agents access to their entire devices LOL. Emails, passwords, bank accounts like what. The concern isn't that the agent will maliciously steal your data, it's that broad access creates exposure you didn't intend, every time the agent reads something to complete an unrelated task. The issue isnt really theft its exposure. And exposure scales with trust you've already granted, not with anything going wrong: It's all based on trust. Safer ways to connect it 1. OAuth over password Use a connection method where Yahoo shows you exactly what's being requested and lets you revoke it later. Never type your Yahoo login directly into the agent. 2. Least access, read-only Point it at a separate, low-value mailbox if you can. Avoid granting send, delete, forward, or account-settings permissions; the agent shouldn't be able to act as you. 3. Keep credentials out of the agent The safer pattern is a credential vault the agent calls out to, so it can request an authenticated action without ever seeing the raw secret. Before you connect anything ✅ Strip sensitive mail first. One commenter's habit: swap real details for placeholders and dummy data, then substitute the real values back in once the model's output comes back. ✅ Use a throwaway or secondary account. Never connect the address tied to banking, password re
AI 资讯
How I built the Appwrite MCP server (and decided to hide most of its capabilities)
When Anthropic introduced the Model Context Protocol on November 25, 2024, it got everyone's eyes on it, including Christy, who was Appwrite's Engineering Lead back then. I had just started my role as an "Engineering Intern" and had no idea what a whole new protocol meant, or why it was such a big deal. Looking at the surface, I wasn't entirely wrong. MCP is JSON-RPC with a schema and a handshake stapled on. What took us sixteen months was everything stapled around it. Streamable HTTP did not exist when MCP launched. It replaced HTTP+SSE in the 2025-03-26 revision. The stdio years Christy had a working stdio server in the repo by February 26, 2025. We already had API keys, so the wiring was simple: claude mcp add appwrite \ --env APPWRITE_PROJECT_ID = <YOUR_PROJECT_ID> \ --env APPWRITE_API_KEY = <YOUR_API_KEY> \ --env APPWRITE_ENDPOINT = https://cloud.appwrite.io/v1 \ -- uvx mcp-server-appwrite An API key is scoped to exactly one project by design, so the ceiling was baked into the credential. Switching projects meant editing your editor config. Creating a project was impossible. So was anything at the organization level. The credential is the whole difference between the two transports, and everything hard about the hosted version follows from swapping it for a token that belongs to the user instead of the project. Authorization ate the schedule By the spec, authorization is genuinely optional: Authorization is OPTIONAL for MCP implementations. [...] Implementations using an HTTP-based transport SHOULD conform to this specification. For a service where one tool call can drop a database, we weren't comfortable treating it as optional. If you use Auth0 or WorkOS, this is a config screen. Appwrite keeps everything in-house, so Matej built the authorization server itself, and I built the resource server plus whatever Cloud was still missing before real clients would work. Steps 2 through 6 are the part that makes "just paste this URL" work. Nothing is pre-provisioned.
AI 资讯
I thought giving my group chat AI assistant Google Calendar would take 5 minutes, and then OAuth humbled me
I went looking for a simple answer to a simple question: How do you give an agent access to Google Calendar? Not a demo. Not a screenshot. A real agent, running unattended, with enough access to be useful and enough guardrails that it won’t turn into a security incident. While researching OpenClaw setups, I found a thread on r/openclaw where someone asked what looked like a tiny question: what do I need to add Google Calendar to OpenClaw? One reply said: "Look into gog cli." That answer is way more revealing than it looks. Because the hard part usually isn’t Google Calendar itself. The hard part is everything hidden behind the phrase "connect Google" . And if you’re building agents in n8n, Make, Zapier, OpenClaw, or a custom OpenAI-compatible loop, auth is only half the problem anyway. Once the workflow runs 24/7, you also need to think about retries, quota limits, caching, and how many LLM calls the thing is quietly making in the background. That’s where a lot of teams hit the same wall: the integration works, but the operational shape of it is bad. Security is fuzzy. Request volume is noisy. And AI costs get weird fast if every poll and retry triggers more model calls. The demo version is lying to you If you’ve used something like n8n Cloud, you’ve seen the polished version: Click Google Calendar Sign in Approve access Done That flow is real inside a managed product. But the minute you leave the managed garden — self-hosted n8n, OpenClaw, a custom MCP server, a Python worker on Ubuntu, or your own app using the OpenAI SDK against an OpenAI-compatible endpoint — you inherit the boring parts. Now "connect Google" actually means: create a Google Cloud project configure the OAuth consent screen choose the right OAuth client type enable the Google Calendar API pick the right scopes store credentials safely handle refresh tokens deal with quota errors later That’s not setup trivia. That’s infrastructure. One user in that same OpenClaw discussion realized it immediately:
AI 资讯
How to Test OAuth Recovery Emails Without Exposing Real Inboxes
OAuth recovery emails look harmless until you test them the lazy way. A team sends password reset links or recovery codes into one shared mailbox, confirms that something arrived, and marks the job done. From a security view, that test is too weak. It can hide token reuse, wrong-user delivery, or log retention that exposes sensitive account events. For non-production checks, I like using a disposable email address that belongs to one test run. Some teams build that inbox layer themselves, some use tempmailso, but the core principle is the same: isolate the recovery event, inspect it quickly, and delete the evidence you no longer need. That is helpful when Authentication and OAuth changes ship together. Why OAuth recovery emails deserve their own threat model Recovery email tests are not just "did the mail send?" checks. They sit on the edge of account takeover risk, so the message itself matters almost as much as the login flow. A decent threat model for these emails should ask: did the message reach only the intended inbox for this run? does the link or code expire when the product says it does? is the message revealing too much user data in subject lines or previews? can an older token still be used after a new recovery request? do logs or test fixtures keep the recovery secret longer than they should? This is where shared inboxes become dangerous in a subtle way. Even if nobody has bad intent, mixed test data makes it harder to prove which token belonged to which request. The same operational confusion shows up in email change confirmation checks , and it gets worse when the email can restore account access. OWASP recommends testing authentication recovery features with the same care as sign-in and session controls, because weak recovery paths are a common bypass route for stronger primary login defenses: https://cheatsheetseries.owasp.org/cheatsheets/Forgot_Password_Cheat_Sheet.html A safer test flow for recovery links and codes The cleanest pattern is one inbox
AI 资讯
OAUTH2.0 In Action — A Guide To Implementing OAUTH In Apps and Websites.
Table of contents What is OAUTH A trip to OAUTH1.0Ville What is OAUTH2.0 Examples of OAUTH Technology OIDC Hands-on Implementation with Microsoft Entra ID What is OAUTH OAUTH is a technological standard that allows you to authorize one app or service to sign in to another without divulging private information, such as passwords. OAUTH stands for Open-Authorization , not Authentication . Authentication is a process that verifies your identity, although OAUTH involves identity verification, its main purpose is to grant access to connect you with different apps and services without requiring you to create a new account. How Does OAUTH Work OAUTH uses access tokens, and this is what makes OAUTH secure to use. An access token is a piece of data that contains information about the user and the resource the token is intended for. A token will also include specific rules for data sharing . For example, you want to share your photos from Instagram with Kyrier — An intelligent email platform built for professionals who refuse to let their inbox run their day , but you only want Kyrier to access your profile image. Kyrier does not also need to access your direct messages or friends list. Instagram issues an access token to Kyrier to access the data you approve (your profile image in this case) on your behalf. So an access token will only allow Kyrier to access your profile image, not even other photos on your page. There may be rules governing when Kyrier can use the access token, it might be for a single use or for recurring uses, and it always has an expiration date. A trip to OAUTH1.0Ville Welcome to OAuth1.0Ville. Please keep your hands inside the vehicle. This is where OAuth started. It was built only for websites , back when "an app" meant a web page and nothing else. Although it worked, it had a lot of problems: Only three authorization flows (2.0 has six) No real plan for mobile or modern apps A scaling problem it never solved It also makes you cryptographically sign e
AI 资讯
GitHub ships a one-click self-revoke for users whose credentials just leaked
You forwarded the phishing email to the security channel about ninety seconds too late. The laptop is already cooperating with someone else. Your personal access token, the one you minted "just for that one script", is on its way to whatever Discord pays for stolen tokens this week. Now what? For users on GitHub Enterprise, what was previously a clickthrough checklist you complete while your hands shake is now one button. On June 24 the GitHub Changelog announced a self-service credential revocation flow under Settings, Credentials. From that view a user can see counts of every credential they have generated or authorized through SSO, then revoke or delete all of them in a single action. Personal access tokens, SSH keys, OAuth tokens, SSO authorizations: gone together. What actually shipped Containment used to be a manual scavenger hunt. PATs sat under Developer Settings. SSH keys lived one tab over. OAuth apps you forgot you authorized two years ago hid behind a different submenu. SSO was its own world. In practice that meant during an incident you forgot something, and the something you forgot was the credential the attacker actually wanted. The new view collapses that surface onto one screen. Counts on one side, a revoke-or-delete-everything action on the other. Whoever wrote it had clearly pictured the 3am screenshot: a user who has just been told to "rotate everything" and has no idea where "everything" lives. GitHub frames this as a complement to an earlier enterprise-owner capability that lets admins with the "Manage enterprise credentials" permission bulk-revoke across one user or many. So there are now two pairs of hands on the kill switch: the user, and the org. (Whichever one notices first.) Why a pipeline owner should care Because users are the trust boundary you keep pretending is somebody else's problem. A leaked PAT in a CI pipeline is rarely a CI bug. It is a human who pasted the token into a script, then a laptop, then a sync folder, then a backup,
AI 资讯
Connect a user's mailbox with Nylas hosted OAuth
Every Nylas request you make on a user's behalf needs one thing first: their permission. Before you can list a mailbox, send on someone's behalf, or read a calendar, the user has to authorize your application through their provider, and that authorization is what's called a grant. Doing the OAuth dance yourself means registering with Google and Microsoft separately, handling each provider's consent screen, token exchange, and refresh quirks. Hosted OAuth collapses that into one flow that works the same across every provider. This post walks through connecting an account from two angles: the HTTP API your web app uses in production, and the nylas CLI for connecting a test account from the terminal. I work on the CLI, so the terminal commands below are the ones I reach for when I need a grant to develop against. What a grant is A grant is an authenticated connection to a single user's account. When a user authorizes your application, Nylas stores the connection and hands you a grant_id , a stable identifier you pass on every subsequent request to act on that user's email, calendar, or contacts. The grant is the unit of access: one user who connected one mailbox is one grant, and everything you build addresses /v3/grants/{grant_id}/... . Keep two credentials distinct here. Your API key authenticates your application to Nylas and goes in the Authorization header on every request; the grant_id identifies which connected user that request acts on. The API key is yours and stays on your backend, while a grant_id is minted per user when they connect. The grant is also where provider differences disappear. A Gmail grant and a Microsoft grant have different OAuth scopes and token mechanics underneath, but once connected, both are just a grant_id you use the same way. That's the point of hosted OAuth: you run one flow, the user picks their provider, and you get back the same kind of identifier regardless of who hosts the mailbox. Hosted OAuth supports Google, Microsoft, Yahoo,
AI 资讯
AI Agent Identity and Permission Challenges: How Uber and Auth0 Are Rethinking Access Control
Uber recently described an internal architecture for propagating identity across multi-agent AI workflows. The design aims to perserve user context, agent provenance, and scoped access as agents delegate work and call internal tools. The case study aligns with Auth0’s view that AI agents need permissions based on delegated authority, scoped credentials, and explicit human approval boundaries. By Eran Stiller
AI 资讯
Two HNG Tasks That Taught Me More Than the Spec: OAuth for Three Clients, and Shipping AI on a Team Deadline
Two HNG Tasks That Taught Me More Than the Spec This is my Stage 9B write-up for the HNG internship . No new code just two tasks that stuck: one I owned solo across multiple repos, and one I shipped inside a team product under real deadline pressure. If you've ever had auth work almost done for three days straight, or watched an LLM politely ignore your JSON schema, you'll recognize these stories. Task 1 (Individual): Insighta Labs — One API, Three Clients, One Auth System Stage: 3 (Technical Requirements Document / TRD track) Why I picked it: Auth looked "done" on paper. It wasn't. Web portal, CLI, and graders all needed to log in differently, and every environment (localhost, Railway, preview URLs) found a new way to break. What it was Insighta Labs is a queryable profile-intelligence API I built during HNG. By Stage 3 the backend wasn't just CRUD anymore it needed GitHub OAuth with PKCE , JWT access + refresh with rotation , RBAC ( admin vs analyst ), rate limits, API versioning, and three first-class clients : Client Repo How it authenticates Backend API HNG_STAGE-1 Issues tokens, sets cookies Web portal Insighta-WebPortal HTTP-only cookies + CSRF CLI Insighta-Cli PKCE + local callback + Bearer tokens Every /api/* route required X-API-Version: 1 and a valid session. Access tokens expired in 3 minutes ; refresh tokens in 5 minutes with rotation. That sounds harsh, it was intentional, and it surfaced bugs fast. The problem it was solving Reviewers and real users had to prove identity without sharing one login mechanism. Browsers should never see raw tokens in JavaScript. The CLI can't use cookie redirects the same way a React app does. Automated graders needed a test path that didn't depend on GitHub's OAuth exchange. One auth design. Three runtimes. Zero "works on my machine only." How I approached it I split auth into explicit paths instead of one generic "login" handler: Web flow GET /auth/github — server stores PKCE verifier, redirects to GitHub GET /auth/gith
AI 资讯
From OpenSSL to One Click: Meet the Payneteasy Key Pair Factory
Connecting to a payment gateway rarely fails because of business logic. More often, it fails at the very first technical step: authentication. If you’ve ever worked with payment APIs, you know the drill. Before sending a single request, you need to generate a cryptographic key pair and sign every request correctly. Sounds straightforward—until you actually try to do it. The hidden hurdle in every integration To securely call the Payneteasy API, each request must be signed. That means: Generating an RSA key pair (usually via OpenSSL) Converting between PKCS#1 and PKCS#8 formats Building a correct signature base string Percent-encoding everything properly Signing with RSA-SHA256 or HMAC-SHA1 Assembling the Authorization header One small mistake—a missing character, wrong encoding, or incorrect format—and your request gets rejected. For teams without deep cryptography expertise, this step alone can turn a one-day integration into a week-long debugging session. If you’re curious, the full manual process is documented here: https://doc.payneteasy.com/integration/general_api_usage/request_authentication_methods/oauth.html#generating-key-pair The solution: Key Pair Factory We built the Payneteasy Key Pair Factory to remove this bottleneck entirely. Instead of dealing with OpenSSL commands and key formats, you can generate everything you need in just a few clicks. What it does: Generates a ready-to-use RSA key pair Ensures correct formatting for Payneteasy APIs Eliminates manual conversion and configuration errors Keeps the private key on your side Provides a public key for request verification No cryptography expertise required. The tool is open-source and available on GitHub: https://github.com/payneteasy/key-pair-factory Why this matters This is not just about convenience—it directly impacts integration speed and success. With the Key Pair Factory, you get: Faster onboarding Fewer integration errors Less back-and-forth with support teams A smoother developer experience I
AI 资讯
OAuth for Remote MCP Servers
OAuth for Remote MCP Servers How each AI assistant signs in to a remote MCP (Model Context Protocol) server, and why the flow differs by client and by where it runs. Overview The protocol throughout is standard OAuth 2.1 — an open, widely implemented authorization standard. The human sign-in runs through oauth2-proxy , one of the most widely deployed open-source auth proxies; the only deployment-specific piece is a thin, spec-conforming authorization server (the /oauth endpoints) that hands MCP clients their tokens. Every client ends up the same way — a person signs in against Google (restricted to your organization's domain), and the client holds a short-lived bearer token it presents on each /mcp call. Two things differ between assistants: where the client runs (a machine on the VPN — private — vs. the vendor's cloud — public ), which decides the host it reaches; and what kind of OAuth client it is — a public client proving itself with PKCE (Proof Key for Code Exchange, which lets a client with no secret prove the token request comes from the same client that started the flow), or a confidential client proving itself with a secret. The participants oauth2-proxy — the public-facing reverse proxy. It authenticates the human against Google (the sign-in restricted to your organization's domain) and forwards the verified identity to the app behind it. Only oauth2-proxy faces the internet. It is a mature, heavily-deployed open-source project — the standard way to put Google/OIDC (OpenID Connect) single sign-on in front of a service, widely used in Kubernetes deployments — so the most security-sensitive leg of the flow (the OAuth exchange with the identity provider) runs on battle-tested code. The MCP server — the app on a loopback port behind the proxy. It plays two roles: the OAuth authorization server ( /oauth/authorize , /oauth/token , /oauth/register , .well-known discovery) and the /mcp tool endpoint. It mints codes and tokens, and validates a token on every /mcp c
AI 资讯
How we made our niche-industry SaaS MCP-ready (and watched ChatGPT call our dispatch tools)
Note: This is an English digest of the original Zenn post (Japanese) . Read there for the full timeline and commit-level trace. TL;DR We ship tasteck , a B2B SaaS for the Japanese night-leisure industry (dispatch + cast shift management). 8 years of operational data, ~100 venues live. Two days after the MCP design post , ChatGPT Plus can call our tools live: "Who's available tonight?" → MCP list_available_drivers → JSON → natural-language reply. Estimated B2 OAuth sprint = 2 weeks (6/16–7/1). Actual = 1 day , by reading the spec carefully before touching code. We hit 12 distinct traps between "OAuth issuance works" and "ChatGPT actually invokes the tool." The QA logs caught every one. What we shipped 3 read tools (B1): list_available_drivers — drivers free tonight list_cast_shifts — today's cast shift roster list_assignable_casts — joined resolution: roster ∧ stage-name set ∧ shop match Natural-language date helper: resolveBusinessDate(naturalText, company) — handles "today / tomorrow / day-after-tomorrow" and the per-tenant business-day boundary (e.g. day flips at 04:00 or 05:00, configured per Company.changeDateTime ). MCP SDK Server + SSE transport: @modelcontextprotocol/sdk wired into a NestJS controller. One SSE connection = one McpServer instance, company-scoped, with a session_id Map routing POST /messages . OAuth flow (B2, finished in one day across 7 steps) Step What Commit 1 Protected Resource Metadata endpoint (RFC 9728) d6f05ff6 2 /authorize + consent screen + PKCE start 107edbcb 3 /token + PKCE verify + JWT issue + resource (RFC 8707) ffd0468c 4 OAuthAccessTokenGuard (RS256 + HS256 fallback, extracts companyId / staffId ) f2c9bed4 5 Streamable HTTP transport (SSE → POST /sse/:companyId for JSON-RPC) 3a28d92f 6 resolveBusinessDate undefined fallback (`(naturalText 7 QA redeploy + ChatGPT live demo — The 12 traps (compressed) The full timeline is in the Japanese post; the abridged list: Discovery path mismatch. ChatGPT expected {% raw %} .well-known/oauth