Skip to content

fix: propagate OTEL alias span attributes in AuthORWrapper#7758

Open
buger wants to merge 1 commit intomasterfrom
fix/otel-alias-multiauth-span-propagation
Open

fix: propagate OTEL alias span attributes in AuthORWrapper#7758
buger wants to merge 1 commit intomasterfrom
fix/otel-alias-multiauth-span-propagation

Conversation

@buger
Copy link
Member

@buger buger commented Feb 10, 2026

Summary

  • Propagate OTEL span attributes (e.g., tyk.api.apikey.alias) from inner auth middlewares to the AuthORWrapper name in compliant mode multi-auth APIs
  • When AuthORWrapper orchestrates authentication (JWT OR API Key), inner middlewares store span attributes under their own name (e.g., JWTMiddleware), but TraceMiddleware looks for attributes under AuthORWrapper — causing them to be missing from OTEL spans
  • After successful auth in the compliant mode path, the fix iterates over the security requirement's schemes and collects any span attributes from the successful inner middleware(s), then stores them under the AuthORWrapper name

Test plan

  • Added TestCompliantMode_OtelAliasAttribute unit test verifying span attribute propagation for both JWT and API key auth through AuthORWrapper
  • Verified go build ./gateway/ and go vet ./gateway/ pass
  • Test compilation verified (go test -c ./gateway/)
  • Existing TestCompliantMode_JWTOrAPIKeyOrHMAC and other compliant mode tests unaffected

🤖 Generated with Claude Code

…auth APIs

When an API uses multiple security requirements in compliant mode (e.g.,
JWT OR API Key), the AuthORWrapper middleware orchestrates authentication.
Inner auth middlewares store span attributes under their own name (e.g.,
"JWTMiddleware"), but TraceMiddleware looks for attributes under
"AuthORWrapper" — causing the tyk.api.apikey.alias attribute to be
missing from OTEL spans.

This fix propagates span attributes from the successful inner middleware
to the AuthORWrapper name after authentication succeeds, so
TraceMiddleware can apply them to the OTEL span.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@github-actions
Copy link
Contributor

🚨 Jira Linter Failed

Commit: 3016ef6
Failed at: 2026-02-10 14:36:58 UTC

The Jira linter failed to validate your PR. Please check the error details below:

🔍 Click to view error details
failed to validate branch and PR title rules: branch name 'fix/otel-alias-multiauth-span-propagation' must contain a valid Jira ticket ID (e.g., ABC-123)

Next Steps

  • Ensure your branch name contains a valid Jira ticket ID (e.g., ABC-123)
  • Verify your PR title matches the branch's Jira ticket ID
  • Check that the Jira ticket exists and is accessible

This comment will be automatically deleted once the linter passes.

@github-actions
Copy link
Contributor

API Changes

no api changes detected

@probelabs
Copy link

probelabs bot commented Feb 10, 2026

This PR fixes a bug where OpenTelemetry (OTEL) span attributes, such as tyk.api.apikey.alias, were not correctly propagated when using multi-factor authentication (e.g., JWT or API Key) in compliant mode. The inner authentication middlewares were setting span attributes under their own names, but the TraceMiddleware expected them under the AuthORWrapper's name, causing them to be omitted from OTEL spans.

The fix introduces logic within the AuthORWrapper to collect any span attributes set by a successful inner authentication middleware and re-associate them with the AuthORWrapper's context key. This ensures that the downstream TraceMiddleware can correctly find and apply these attributes to the request's OTEL span, improving observability for multi-auth APIs.

Files Changed Analysis

  • gateway/mw_auth_or_wrapper.go: Contains the core fix, adding 15 lines of code to propagate the OTEL attributes after a successful authentication.
  • gateway/mw_auth_or_wrapper_test.go: Adds a comprehensive new unit test (TestCompliantMode_OtelAliasAttribute) with 206 lines to validate the fix for both JWT and API key authentication paths, ensuring the attributes are correctly passed up.

Architecture & Impact Assessment

What this PR accomplishes:
This PR rectifies a bug that resulted in the loss of crucial observability data (OTEL span attributes) for APIs configured with compliant mode multi-authentication. This ensures that request traces contain the correct metadata, such as the API key alias, for accurate monitoring and debugging.

Key technical changes introduced:

  • After a successful authentication within the AuthORWrapper, the code now iterates through the configured security schemes.
  • It retrieves span attributes set by the successful inner middleware from the request's context.
  • It then sets these collected attributes back into the context under the AuthORWrapper's name, making them accessible to the TraceMiddleware.

Affected system components:

  • Gateway Authentication: Specifically the AuthORWrapper middleware.
  • Observability: The OpenTelemetry tracing functionality, which will now receive the correct attributes.

Flow Diagram:

sequenceDiagram
    participant Client
    participant AuthORWrapper
    participant "InnerAuth (e.g., APIKey Middleware)" as InnerAuth
    participant TraceMiddleware

    Client->>AuthORWrapper: Request with API Key
    AuthORWrapper->>InnerAuth: ProcessRequest()
    InnerAuth-->>AuthORWrapper: Success, sets span attributes under its own context key
    Note over AuthORWrapper: **New Logic:** Copies attributes from InnerAuth's key to its own key
    AuthORWrapper->>TraceMiddleware: Continue request processing
    TraceMiddleware->>TraceMiddleware: Creates OTEL span, reads attributes from AuthORWrapper's key
    Note over TraceMiddleware: Span now correctly includes `tyk.api.apikey.alias`
Loading

Scope Discovery & Context Expansion

The change is well-contained within the AuthORWrapper middleware and primarily affects how context is passed between authentication middlewares and the TraceMiddleware. The core mechanism relies on the helper functions ctxGetSpanAttributes and ctxSetSpanAttributes located in gateway/api.go, which manage data within the http.Request context.

The impact is limited to APIs using the compliant security processing mode with multiple authentication schemes (OR logic). Other authentication configurations are unaffected. The addition of a targeted integration test confirms the fix without causing regressions in existing compliant mode tests.

Metadata
  • Review Effort: 2 / 5
  • Primary Label: bug

Powered by Visor from Probelabs

Last updated: 2026-02-10T14:44:06.079Z | Triggered by: pr_opened | Commit: 3016ef6

💡 TIP: You can chat with Visor using /visor ask <your question>

@probelabs
Copy link

probelabs bot commented Feb 10, 2026

✅ Security Check Passed

No security issues found – changes LGTM.

✅ Architecture Check Passed

No architecture issues found – changes LGTM.

Performance Issues (1)

Severity Location Issue
🟡 Warning gateway/mw_auth_or_wrapper.go:121-123
The use of `append` within a loop to build the `spanAttrs` slice can lead to multiple memory reallocations. For each successful middleware that has span attributes, `append` might need to reallocate the underlying array for `spanAttrs` and copy existing elements, which introduces overhead on a performance-sensitive request path.
💡 SuggestionTo optimize and reduce allocations, calculate the total number of attributes required across all successful middlewares first. Then, pre-allocate the `spanAttrs` slice with the exact capacity needed. This avoids incremental resizing of the slice within the loop.
// Collect attributes and calculate total size in one pass
var allAttrs [][]otel.SpanAttribute
totalAttrs := 0
for _, schemeName := range requirement {
	if mw := a.getMiddlewareForScheme(schemeName); mw != nil {
		if attrs := ctxGetSpanAttributes(r, mw.Name()); len(attrs) &gt; 0 {
			allAttrs = append(allAttrs, attrs)
			totalAttrs += len(attrs)
		}
	}
}

if totalAttrs &gt; 0 {
	spanAttrs := make([]otel.SpanAttribute, 0, totalAttrs)
	for _, attrs := range allAttrs {
		spanAttrs = append(spanAttrs, attrs...)
	}
	ctxSetSpanAttributes(r, a.Name(), spanAttrs...)
}

Quality Issues (2)

Severity Location Issue
🟠 Error gateway/mw_auth_or_wrapper.go:116-122
The loop `for _, schemeName := range requirement` iterates over the values of the `requirement` map, which are of type `[]string` (a list of scopes). However, the loop variable is named `schemeName` and is passed to `a.getMiddlewareForScheme()`, which expects a `string` (the scheme name). This is a type mismatch that should cause a compilation error. The loop should iterate over the map keys to get the scheme names.
💡 SuggestionChange the loop to `for schemeName := range requirement {` to correctly iterate over the keys of the map, which represent the scheme names.
🟢 Info gateway/mw_auth_or_wrapper_test.go:5507-5512
The assertion for the JWT authentication case only checks for the presence of an attribute with the alias key (`tyk.api.apikey.alias`), but it doesn't verify the attribute's value. This makes the test less precise. A stronger assertion would check for the exact expected attribute, including its value (which is likely an empty string in this case).
💡 SuggestionRefactor the assertion to check for the complete `otel.SpanAttribute` struct, similar to how it's done in the API key authentication test case. This ensures both key and value are correct. For example: `if attr == otel.APIKeyAliasAttribute("") { ... }`.

Powered by Visor from Probelabs

Last updated: 2026-02-10T14:44:13.075Z | Triggered by: pr_opened | Commit: 3016ef6

💡 TIP: You can chat with Visor using /visor ask <your question>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant