Description
When using oidc_rule with ApiOptions(security=[...]) and MethodOptions(security=[...]),
the generated OpenAPI spec contains a name mismatch between the security scheme defined in
components/securitySchemes and the name referenced in route security definitions.
This causes API Gateway to silently ignore the JWT authorizer on all routes — the authorizer
is created in API Gateway but never attached to any route.
Environment
- Nitric CLI: v1.61.1
- Nitric Python SDK: v1.2.3
- Provider: AWS (Pulumi)
- Region: eu-west-1
Steps to Reproduce
from nitric.resources import api, ApiOptions, oidc_rule
from nitric.resources.apis import MethodOptions
cognito_auth = oidc_rule(
"cognito-auth-rule",
issuer="https://cognito-idp.eu-west-1.amazonaws.com/POOL_ID/.well-known/openid-configuration",
audiences=["CLIENT_ID"]
)
auth_api = api("auth", ApiOptions(security=[cognito_auth([])]))
@auth_api.post("/logout")
async def logout_handler(ctx):
...
Root Cause
In nitric/resources/apis.py, _attach_oidc constructs the resource name as
f"{options.name}-{api_name}":
# nitric/resources/apis.py
def _attach_oidc(api_name: str, options: OidcOptions) -> OidcSecurityDefinition:
return Nitric._create_resource(
OidcSecurityDefinition, f"{options.name}-{api_name}", api_name, options
# ^^^^^^^^^^^^^^^^^^^^^^^^^^
# becomes self.name → sent as req.Id.Name via gRPC
)
This name (cognito-auth-rule-auth) becomes the req.Id.Name sent via gRPC to the CLI,
which in pkg/collector/service.go uses it as the key for the security scheme:
// pkg/collector/service.go:152
s.apiSecurityDefinition[req.GetApiSecurityDefinition().GetApiName()][req.Id.GetName()] = req.GetApiSecurityDefinition()
And in pkg/collector/spec.go it becomes the key in SecuritySchemes:
// pkg/collector/spec.go:563-588
for schemeName, securityScheme := range serviceRequirements.apiSecurityDefinition[apiName] {
// schemeName = "cognito-auth-rule-auth"
api.Components.SecuritySchemes[schemeName] = ...
}
Meanwhile, route security references use the original name (cognito-auth-rule),
producing this mismatch in the final OpenAPI spec:
"securitySchemes": {
"cognito-auth-rule-auth": { ... } ← scheme key
},
"paths": {
"/logout": {
"post": {
"security": [{"cognito-auth-rule": []}] ← references original name
}
}
}
API Gateway receives an OpenAPI spec with an unresolvable security reference and silently
ignores the authorizer.
Expected Behavior
The security scheme name in securitySchemes should match the name referenced in route
security definitions. The authorizer should be attached to all routes that declare it.
Actual Behavior
The JWT authorizer is created in API Gateway (visible in the Authorizers tab) but is
not attached to any route. Routes show "Authorization: NONE" in the API Gateway console.
Workaround
Two changes are needed in nitric/resources/apis.py:
1. Change _attach_oidc to use options.name as the resource name instead of
f"{options.name}-{api_name}":
def _attach_oidc(api_name: str, options: OidcOptions) -> OidcSecurityDefinition:
return Nitric._create_resource(
OidcSecurityDefinition, options.name, api_name, options # use options.name directly
)
2. Add rule_name field to OidcSecurityDefinition and use it in _oidc_to_resource:
class OidcSecurityDefinition(BaseResource):
api_name: str
issuer: str
rule_name: str # ← add this
audiences: List[str]
def __init__(self, name: str, api_name: str, options: OidcOptions):
super().__init__(name)
self.api_name = api_name
self.issuer = options.issuer
self.audiences = options.audiences
self.rule_name = options.name # ← add this
def _oidc_to_resource(b: OidcSecurityDefinition) -> ResourceIdentifier:
return ResourceIdentifier(name=b.rule_name, type=ResourceType.ApiSecurityDefinition)
# ^^^^^^^^^ was b.name
Since _create_resource deduplicates by name, using options.name directly means that
the same OIDC rule applied to multiple APIs would conflict. A safer fix might be to keep
the composite key internally but ensure the ResourceIdentifier.name always uses
options.name — which is what the _oidc_to_resource fix achieves.
Description
When using
oidc_rulewithApiOptions(security=[...])andMethodOptions(security=[...]),the generated OpenAPI spec contains a name mismatch between the security scheme defined in
components/securitySchemesand the name referenced in routesecuritydefinitions.This causes API Gateway to silently ignore the JWT authorizer on all routes — the authorizer
is created in API Gateway but never attached to any route.
Environment
Steps to Reproduce
Root Cause
In
nitric/resources/apis.py,_attach_oidcconstructs the resource name asf"{options.name}-{api_name}":This name (
cognito-auth-rule-auth) becomes thereq.Id.Namesent via gRPC to the CLI,which in
pkg/collector/service.gouses it as the key for the security scheme:And in
pkg/collector/spec.goit becomes the key inSecuritySchemes:Meanwhile, route
securityreferences use the original name (cognito-auth-rule),producing this mismatch in the final OpenAPI spec:
API Gateway receives an OpenAPI spec with an unresolvable security reference and silently
ignores the authorizer.
Expected Behavior
The security scheme name in
securitySchemesshould match the name referenced in routesecuritydefinitions. The authorizer should be attached to all routes that declare it.Actual Behavior
The JWT authorizer is created in API Gateway (visible in the Authorizers tab) but is
not attached to any route. Routes show "Authorization: NONE" in the API Gateway console.
Workaround
Two changes are needed in
nitric/resources/apis.py:1. Change
_attach_oidcto useoptions.nameas the resource name instead off"{options.name}-{api_name}":2. Add
rule_namefield toOidcSecurityDefinitionand use it in_oidc_to_resource:Since
_create_resourcededuplicates by name, usingoptions.namedirectly means thatthe same OIDC rule applied to multiple APIs would conflict. A safer fix might be to keep
the composite key internally but ensure the
ResourceIdentifier.namealways usesoptions.name— which is what the_oidc_to_resourcefix achieves.