MCPcopy Create free account
hub / github.com/Mnexa-AI/e2a / resolveAgentAccessToken

Method resolveAgentAccessToken

internal/agent/agent_identity.go:159–186  ·  view source on GitHub ↗

resolveAgentAccessToken verifies an e2a-minted access_token JWT and resolves it to an agent-scoped principal. Returns (nil, false, nil) when the bearer is not one of our JWTs (so the caller can fall through to API-key/OAuth paths); returns an error only when it IS our JWT but fails verification or l

(r *http.Request, bearer string)

Source from the content-addressed store, hash-verified

157// not one of our JWTs (so the caller can fall through to API-key/OAuth paths);
158// returns an error only when it IS our JWT but fails verification or lookup.
159func (a *API) resolveAgentAccessToken(r *http.Request, bearer string) (*identity.Principal, bool, error) {
160 if !a.agentAuthReady() || !looksLikeJWT(bearer) {
161 return nil, false, nil
162 }
163 claims, err := a.signer.VerifyToken(bearer, agentauth.TypAccessToken, a.agentAuthIssuer())
164 if err != nil {
165 // It parses as a JWT but isn't a valid e2a access token — reject
166 // rather than fall through (a tampered/expired token is a 401, not an
167 // API-key probe).
168 return nil, true, errors.New("invalid agent access token")
169 }
170 ag, err := a.store.GetAgentByID(r.Context(), claims.Subject)
171 if err != nil || ag == nil {
172 return nil, true, errors.New("agent not found for access token")
173 }
174 // Kill switch, re-checked per request (the agent row is already loaded, so
175 // this is free): a bumped assertion_version invalidates outstanding access
176 // tokens immediately rather than only starving new mints — revocation is
177 // instant, not bounded by the 15-min token TTL.
178 if ag.AssertionVersion != claims.AssertionVersion {
179 return nil, true, errors.New("access token revoked (stale assertion_version)")
180 }
181 user, err := a.store.GetUserByID(r.Context(), ag.UserID)
182 if err != nil || user == nil {
183 return nil, true, errors.New("owner not found for access token")
184 }
185 return &identity.Principal{User: user, Scope: identity.ScopeAgent, AgentID: ag.ID}, true, nil
186}
187
188// looksLikeJWT is a cheap pre-filter: a compact JWS is three base64url segments
189// separated by dots and (for our RS256 tokens) starts with the "eyJ" header.

Callers 1

authenticatePrincipalMethod · 0.95

Calls 6

agentAuthReadyMethod · 0.95
agentAuthIssuerMethod · 0.95
looksLikeJWTFunction · 0.85
VerifyTokenMethod · 0.80
GetAgentByIDMethod · 0.80
GetUserByIDMethod · 0.80

Tested by

no test coverage detected