[Learning Notes][Golang] Authorization Challenges in the AI Agent Era: What is ID-JAG and Why I Re-implemented It in Go A developer re-implemented the ID-JAG (Identity Assertion JWT Authorization Grant) mechanism in Go as an MCP server, addressing authorization challenges for AI agents accessing internal systems. ID-JAG allows agents to act on behalf of users with narrow, short-lived permissions, reducing risks from prompt injection or hallucinations. The implementation is based on the IETF Internet-Draft and is already cited by the Model Context Protocol specification. In the past six months or so, connecting AI Agents directly to internal systems to help get things done is no longer news. However, if you think one step further: in "whose identity" should the Agent call those APIs? If the permissions it receives are as broad as a human's, once it is tricked into performing an operation it shouldn't, the consequences could be more severe than a human's accidental slip. This is exactly the problem that ID-JAG Identity Assertion JWT Authorization Grant aims to solve. I recently organized the principles of this mechanism and re-implemented the MCP Server from the tutorial repo athenz-community/id-jag-the-hard-way https://github.com/athenz-community/id-jag-the-hard-way using Go: kkdai/id-jag-mcp This article will introduce the following in order: ID-JAG is an authorization mechanism that allows AI Agents to access protected resources on behalf of users, with the keyword being "on behalf of." Currently, it is still an IETF Internet-Draft and has not yet become an official RFC, but organizations like LY Corporation on the Athenz authorization system and Okta have already begun implementation, and the MCP Model Context Protocol specification has already cited this draft. Traditional service-to-service authorization usually falls into two extremes: either the entire service shares a universal master key API Key, Service Account , or the user's session or long-lived token is directly lent to the program. The former has too much power, while the latter lacks an audit trail; if leaked, an attacker can almost completely impersonate the user, and it is very difficult to detect. When AI Agents start deciding which tools to call and which internal APIs to connect to on their own, the risks of both approaches are amplified: an Agent might perform operations the user never intended due to prompt injection or hallucinations. If the Agent holds a master key, the consequence is that all company data is at its mercy. In real-world scenarios, there is often a multi-layered architecture where an "Orchestrator Agent calls a Sub-Agent," and the risk is passed all the way down. What ID-JAG wants to achieve is: for every action an Agent takes, it must be able to prove that "this is a specific user, at a specific moment, authorizing me to do this specific thing," and this authorization scope should be as narrow as possible, with a validity period as short as possible. It is built on top of OAuth2 token exchange RFC 8693 https://datatracker.ietf.org/doc/html/rfc8693 , adding a layer of proof that "this token is derived from a human's identity assertion." This is also why it is listed on OAuth.net's Cross-App Access XAA page https://oauth.net/cross-app-access/ —this is precisely a new problem emerging in the Agent era. Incidentally, ID-JAG also solves a very practical user experience problem: if an Agent had to pop up a browser window for the user to manually click "Agree" every time it needed to access a new service, the experience would quickly become exhausting, leading users to just agree to everything. ID-JAG consolidates the authorization action to the moment the user logs in via SSO. After that, when the Agent needs new access permissions, it uses the already issued identity assertion to exchange for a token with the authorization server, without requiring the user to pop up and click again. I previously wrote about How to develop OAuth2 PKCE via Golang https://www.evanlin.com/go-oauth-pkce/ , which covered the implementation experience of LINE Login adopting PKCE. The problem solved in that article and the one ID-JAG solves are actually on two different levels. Comparing them makes it clearer what is new about ID-JAG. PKCE solves the problem of "whether the client identity is trustworthy": for public clients like mobile apps that cannot safely store a client secret, the authorization code might be intercepted by a malicious app on the same phone during transmission. PKCE uses a code verifier / code challenge one-time pair to ensure that even if the code is stolen, it cannot be exchanged for a token without the correct verifier. The entire problem occurs in a "single hop" between the user and the app in their hand. ID-JAG solves the problem of "whether this non-human service identity is qualified to act on behalf of this person for this task," and it often spans several hops: User logs into IdP → AI Client Gateway → MCP Server → Final Resource Server. The caller at each hop is not the user themselves, yet each must prove they are "acting under authority." The original design of OAuth 2.0 was for "human user ↔ application" scenarios and does not directly support this multi-layer Agent chain delegation scenario. PKCE protects the integrity of a single authorization exchange; ID-JAG protects the minimum necessary permissions for every link in an entire authorization chain. The two do not conflict; they are mechanisms solving problems at different stages under the same broad architecture. ID-JAG did not invent a new protocol out of thin air; instead, it combines two existing IETF standards. Understanding these two cornerstones is necessary to understand what the subsequent complete exchange flow is doing. The first is RFC 8693 — OAuth 2.0 Token Exchange, which defines a general protocol for "exchanging one type of token for another." Conceptually, it's like going to a currency exchange to swap Yen for Taiwan Dollars, except here you are swapping security tokens. A token exchange request looks roughly like this: POST /token grant type=urn:ietf:params:oauth:grant-type:token-exchange subject token=