Summary
Goa 3.25.3 does not appear to support expressing an HTTP APIKeySecurity scheme that is transported via request cookies in a way that is both runtime-correct and OpenAPI-correct.
We need a native Goa way to model authenticated browser routes that use a session cookie (for example __Host-ak_session) as the auth credential, instead of falling back to post-generation OpenAPI rewriting.
What we expected
Given a design like this:
var AuthSessionToken = JWTSecurity("auto_k_session_bearer", func() {
Description("App bearer")
})
var BrowserSessionCookie = APIKeySecurity("browser_session_cookie", func() {
Description("Browser session cookie")
})
var BrowserAuthenticatedRequest = Type("BrowserAuthenticatedRequest", func() {
APIKey("browser_session_cookie", "browser_session", String, func() {
Description("Opaque browser session cookie")
})
Token("auth", String, func() {
Description("Bearer token")
})
})
Method("profile", func() {
Security(AuthSessionToken)
Security(BrowserSessionCookie)
Payload(BrowserAuthenticatedRequest)
Result(User)
HTTP(func() {
GET("/auth/profile")
Header("auth:Authorization")
Cookie("browser_session:__Host-ak_session")
Response(200)
})
})
We expected Goa to:
- Generate an OpenAPI security scheme for
browser_session_cookie with type: apiKey, in: cookie, name: __Host-ak_session.
- Generate the operation
security array with cookie auth as an alternative requirement.
- Not duplicate the auth cookie as a normal request parameter when it is already modeled as a security scheme.
- Keep generated server/client code valid.
What actually happens
In 3.25.3, Goa appears to resolve APIKeySecurity locations via expr.findKey, and findKey only checks query params, headers, and body. It does not check request cookies.
Relevant source:
func findKey(exp eval.Expression, keyAtt string) (string, string) {
switch e := exp.(type) {
case *HTTPEndpointExpr:
if n, exists := e.Params.FindKey(keyAtt); exists {
return n, "query"
} else if n, exists := e.Headers.FindKey(keyAtt); exists {
return n, "header"
} else if e.Body == nil {
return "", "header"
}
...
return "", "header"
}
return "", ""
}
Because cookies are ignored here, the generated OpenAPI/API key scheme ends up header-bound instead of cookie-bound.
Practical consequences
In our case this caused two problems:
- The generated OpenAPI modeled the browser session scheme as
header: Authorization instead of cookie: __Host-ak_session.
- When the same payload attribute was also mapped as a request cookie, generated server code ended up with duplicate locals/parameters for the same field and failed to compile.
Example shape from generated code:
func NewBeginGithubLinkBrowserAuthenticatedOAuthLinkStartRequest(body *BeginGithubLinkRequestBody, auth *string, browserSession *string, browserSession *string) *restauth.BrowserAuthenticatedOAuthLinkStartRequest
and similarly duplicate local declarations in generated HTTP decode code.
Current workaround
We had to keep the DSL/browser payloads using normal cookie request fields and then post-process the generated OpenAPI artifacts to:
- add a cookie-based security scheme,
- add cookie auth as an alternative security requirement on browser-authenticated operations,
- remove the duplicate cookie request parameter,
- normalize the 401 description away from bearer-specific wording.
That gets us a truthful served OpenAPI contract, but it is obviously not ideal.
Request
Could Goa support a native way to express cookie-backed APIKeySecurity for HTTP endpoints?
Concretely, it would help if:
APIKeySecurity location inference considered HTTP cookies.
- Cookie-backed security fields could be mapped without generating a duplicate cookie parameter.
- Generated OpenAPI and generated transport code remained aligned for this case.
Even a documented/explicit DSL pattern for “API key security in cookie transport” would help a lot if there is already a supported way that we missed.
If useful, I can provide a smaller standalone reproducer, but the root cause looks pretty directly tied to expr.findKey ignoring e.Cookies.
Summary
Goa 3.25.3 does not appear to support expressing an HTTP
APIKeySecurityscheme that is transported via request cookies in a way that is both runtime-correct and OpenAPI-correct.We need a native Goa way to model authenticated browser routes that use a session cookie (for example
__Host-ak_session) as the auth credential, instead of falling back to post-generation OpenAPI rewriting.What we expected
Given a design like this:
We expected Goa to:
browser_session_cookiewithtype: apiKey,in: cookie,name: __Host-ak_session.securityarray with cookie auth as an alternative requirement.What actually happens
In 3.25.3, Goa appears to resolve
APIKeySecuritylocations viaexpr.findKey, andfindKeyonly checks query params, headers, and body. It does not check request cookies.Relevant source:
expr/helpers.go:Because cookies are ignored here, the generated OpenAPI/API key scheme ends up header-bound instead of cookie-bound.
Practical consequences
In our case this caused two problems:
header: Authorizationinstead ofcookie: __Host-ak_session.Example shape from generated code:
and similarly duplicate local declarations in generated HTTP decode code.
Current workaround
We had to keep the DSL/browser payloads using normal cookie request fields and then post-process the generated OpenAPI artifacts to:
That gets us a truthful served OpenAPI contract, but it is obviously not ideal.
Request
Could Goa support a native way to express cookie-backed
APIKeySecurityfor HTTP endpoints?Concretely, it would help if:
APIKeySecuritylocation inference considered HTTP cookies.Even a documented/explicit DSL pattern for “API key security in cookie transport” would help a lot if there is already a supported way that we missed.
If useful, I can provide a smaller standalone reproducer, but the root cause looks pretty directly tied to
expr.findKeyignoringe.Cookies.