Middle · Go service security

A valid JWT reaches another user’s object

Signature verification succeeds, but a request asks for another tenant’s order. What checks are still required?

Try explaining this aloud before opening the answer. State your assumptions and trace a boundary case.

EXAMPLE · FRAGMENT UNLESS A COMPLETE PROGRAM IS SHOWN

go
package main

import "fmt"

type Principal struct{ Subject, Tenant, Role string }
type Document struct{ Tenant, Owner string }

func canRead(p Principal, d Document) bool {
	return p.Subject != "" && p.Tenant == d.Tenant && (p.Subject == d.Owner || p.Role == "auditor")
}
func main() {
	// These are already-verified test principals, not values read from headers.
	d := Document{Tenant: "a", Owner: "user-1"}
	fmt.Println(canRead(Principal{"user-1", "a", "reader"}, d)) // true
	fmt.Println(canRead(Principal{"user-1", "b", "reader"}, d)) // false
}
Reveal a strong answer
  1. A signed token can be genuine and still belong to the wrong audience, issuer or operation. Even a fully valid token does not prove that its subject may read a particular order. Treat authentication as construction of a verified principal and authorization as an explicit resource-scoped decision. Fail closed when either contract is missing rather than accepting whatever identity-shaped value a request provides.

  2. With JWT, use a maintained verifier, constrain acceptable algorithms and validate key selection, issuer, audience, expiry and other required claims. Parsing or base64-decoding is not verification. Design key rotation and revocation/session policies. For browser clients, choose cookie/CSRF/CORS rules deliberately; CORS is not an authorization mechanism for non-browser callers. The same subject string in a different tenant is denied. This pure function models authorization after authentication; it deliberately does not parse or verify a JWT. Construct the principal only after the authentication layer validates the chosen credential, and test resource rules independently of token parsing.

  3. Do not trust roles or tenant IDs copied from unverified headers or an unverified token payload. Avoid returning a different secret-laden error body for every verification failure. Test wrong issuer/audience, expired and not-yet-valid credentials, unknown keys, missing required claims and a valid credential attempting another tenant’s resource. These are native service lessons, not registration or accounts added to GopherForge.

Common trap

Authentication and object-level authorization are separate decisions even when a token contains familiar role names.

Try it

List issuer, audience, time and key-selection checks, then write an independent resource authorization test with two tenants.

Worked solution

Verify the full credential contract, not only its signature, and construct a principal only after those checks pass. Then authorize the specific action on the tenant-scoped resource. Client-provided roles or tenant headers are not authority, and CORS does not protect a server from non-browser requests. Include revocation/rotation policy and consistent failure responses without leaking secrets or object details.

Change the constraint

How should a cached authorized response react to permission revocation?

How did you do?

Self-assessment, not a compiler pass or interview score. Explain the reasoning unaided before marking understood.

Not marked. Progress stays on this browser, separate from course completion.

Primary references

Checked 2026-10-28. Use documentation for your pinned runtime, driver and tool version.