API gateway keys are long-lived shared secrets that rarely expire, are often issued to a partner years ago and forgotten, and on some platforms open every API in a plan once one is issued. This guide is a step-by-step audit of the keys and usage plans on two common gateways: Amazon API Gateway REST APIs (API keys and usage plans) and Azure API Management (subscriptions and their keys). It shows how to list every key, map it to the APIs it opens, find which methods rely on a key alone, measure real use, assign owners, and then disable, rotate or replace keys with a rollback ready. It is for API platform teams, cloud security engineers and anyone asked to prove who holds access to a public API. The design principles behind gateway credentials are covered in the API Gateway Security Guide.
Key takeaways
- A key's reach is set by its plan or scope: AWS warns that a valid key for one API in a usage plan can access all APIs in that plan, and an Azure API Management subscription can be scoped to a product, a single API or all APIs. Audit the scope, not just the key.
- Find methods protected by a key alone: on Amazon API Gateway, a method with
apiKeyRequiredtrue andauthorizationTypeNONEis protected only by a shared string, which AWS says should not be used for authentication or authorisation. - Nothing expires by itself: Microsoft states API Management has no built-in expiry or automatic rotation for subscription keys, and AWS keys stay enabled until someone disables them. Age and last use are your controls.
- The built-in all-access subscription is a master key: every API Management instance has one that opens every API; Microsoft says never to embed it in client apps. Check who has used it.
- Quotas are not a security boundary: AWS describes usage plan throttles and quotas as best effort and says not to rely on them to control costs or block access. Use them for fairness, and use WAF, budgets and real authentication for protection.
When you need this
- Partner or customer offboarding: a contract ends but its key still works. The audit finds keys with no live owner.
- Key leak response: a key turns up in a public repository or a mobile app. You need to know in minutes what that key opens. See the Developer Secret Scanning Triage guide for the intake side.
- Periodic access review: keys are non-human credentials and belong in the same review cycle as service accounts. See How to Run an Access Review for Service Accounts.
- Before moving to token-based access: the inventory tells you which callers must migrate. See the API Keys vs OAuth Tokens Guide.
Before you start
- Read-only access: on AWS, an IAM role that can call the API Gateway
GEToperations in every Region and account in scope; on Azure, a role that can read API Management instances. Listing key values is more sensitive than listing metadata, so keep--include-valuesandlistSecretsout of the routine audit. - Scope: every AWS account and Region with REST APIs, and every API Management instance (including workspaces). Gateways created by product teams outside the platform account are the usual blind spot.
- Logging in place: API Gateway access logs with the API key ID, and API Management resource logs sent to Log Analytics (
ApiManagementGatewayLogs). Without request logs you can only see quota counters, not who called what. - A register: key or subscription ID, name, owner, scope, plan or product, created date, last used, enabled state, decision. The API Key Management Standard Template sets the rules you will measure against.
Step-by-step
1. Know the objects you are auditing
| Concept | Amazon API Gateway (REST) | Azure API Management |
|---|---|---|
| The credential | API key: an alphanumeric string of 20 to 128 characters, generated by API Gateway or imported | Subscription with a primary and a secondary key |
| What it opens | Usage plan, linked to one or more API stages | Scope: a product, a single API, all APIs, or the built-in all-access subscription |
| How the caller sends it | X-API-Key header (apiKeySource = HEADER), or returned by a Lambda authoriser (AUTHORIZER) | Ocp-Apim-Subscription-Key header, or the subscription-key query parameter if the header is absent (names can be changed per API) |
| Enforcement switch | apiKeyRequired on each method | Requires subscription on a product, Subscription required on an API |
| Limits | Throttle (rateLimit, burstLimit) and quota (limit, period DAY, WEEK or MONTH) per key, aggregated across the plan's stages | Rate limit and quota policies at product or API scope |
| Lifecycle | enabled flag; no expiry | State: active, suspended, submitted, rejected, cancelled or expired; no built-in key expiry or rotation |
2. Inventory keys and plans on Amazon API Gateway (read-only)
- List keys without values:
aws apigateway get-api-keysreturnsid,name,enabled,createdDate,lastUpdatedDate,stageKeys,customerIdandtags. Do not add--include-valuesfor the audit; the value is only needed if you must match a leaked string, and then only for that one key. - List usage plans:
aws apigateway get-usage-plansreturns each plan'sapiStages(API ID and stage),throttleandquota. To find the plans one key belongs to, add--key-id <id>. - List keys per plan:
aws apigateway get-usage-plan-keys --usage-plan-id <id>gives the keys attached to each plan. AWS allows one key in several plans, but only one plan per stage for a given key. - Find what each stage exposes: for each API in a plan,
aws apigateway get-resources --rest-api-id <id> --embed methodsreturns each method withapiKeyRequired,authorizationType(NONE,AWS_IAM,CUSTOMorCOGNITO_USER_POOLS) andauthorizerId. - Record the key source: read
apiKeySourceon each REST API. WithAUTHORIZER, the Lambda authoriser supplies the key, so the audit must include where that function gets keys from. - Repeat in every Region and account. Paginate with the
positionvalue returned by each call.
3. Inventory subscriptions on Azure API Management (read-only)
- List subscriptions: call the Subscription List REST operation,
GET .../providers/Microsoft.ApiManagement/service/{serviceName}/subscriptions?api-version=2024-05-01. Each result givesscope(for example/products/{productId},/apisor/apis/{apiId}),state,ownerId,displayName,createdDate,expirationDateandallowTracing. - Do not pull keys: Microsoft documents that
primaryKeyandsecondaryKeyare not filled on GET; they need a POST tolistSecrets. Leave that out of the audit and alert on it instead (step 6). - Filter for the risky scopes:
$filtersupportsscope,state,ownerIdandproductId. Pull/apis(all APIs) and the built-in all-access subscription first. - Check which APIs and products need no subscription: in each product's settings, check Requires subscription, and in each API's settings, Subscription required. Microsoft notes that when the requirement is off, a key in the request is ignored and the API is open unless another mechanism protects it.
- Note scope effects: Microsoft states that product-scope policies are not applied to requests from API-scoped, all-APIs or all-access subscriptions. A rate limit set on a product does not limit those keys.
4. Map each key to what it can reach
Join the outputs: key to plan (or subscription to scope), plan to stages, stage to methods. For each key, record the APIs and methods it opens and how each method authenticates. Then classify:
| Finding | Where you see it | Risk | Action |
|---|---|---|---|
| Key is the only control on a method | apiKeyRequired true with authorizationType NONE; or an APIM API with subscription only and no token policy | Anyone with the string calls the API (OWASP API Security Top 10 2023, API2 Broken Authentication) | Add IAM, a Lambda or Cognito authoriser, or a JWT validation policy |
| Plan spans unrelated APIs | One usage plan with several apiStages from different products | A key issued for one API opens all of them | Split plans per API product |
| All-APIs or all-access subscription in use | Scope /apis or the built-in subscription with gateway traffic | Master key | Replace with product or API scope; restrict all-access to testing |
| Method or API open with no key and no authoriser | apiKeyRequired false and NONE; Subscription required off | Anonymous access | Confirm it is meant to be public |
| Keys passed through to the backend | APIM inbound policy without set-header removal | Microsoft notes keys are passed to the backend by default and may appear in backend logs | Strip the header or query parameter at the end of inbound |
| Tracing allowed on a subscription | allowTracing true | Request traces may expose details to the caller | Turn off outside debugging |
5. Measure real use
- AWS quota counters:
aws apigateway get-usage --usage-plan-id <id> --start-date <YYYY-MM-DD> --end-date <YYYY-MM-DD>returns, per key, a daily pair of used and remaining quota. A key with zero use over 90 days is a candidate for disabling. This only works for plans with a quota. - AWS access logs: include
$context.identity.apiKeyId,$context.identity.sourceIp,$context.statusand$context.requestTimein the access log format. Log the key ID, not$context.identity.apiKey, which is the key itself and would turn your log store into a key store. - APIM gateway logs: in Log Analytics, group
ApiManagementGatewayLogsbyApimSubscriptionId,ApiId,CallerIpAddressandResponseCodeover 90 days to find last use, unexpected source networks and failed calls. - Look for misuse patterns: one key from many unrelated IP ranges, a sudden jump in calls, a partner key used outside its expected APIs, or repeated 403 responses that suggest someone trying keys.
6. Watch the control plane
AWS CloudTrail records API Gateway management calls as events (except TestInvokeAuthorizer and TestInvokeMethod), so key creation, import, update, deletion and usage plan changes are all visible. Review GetApiKey and GetApiKeys calls by unexpected principals, since these can return key values, and alert on ImportApiKeys, and on changes that set apiKeyRequired to false. In Azure, the activity log records listSecrets and key regeneration on subscriptions; alert on both outside approved automation. The AWS CloudTrail Guide covers trail coverage across accounts.
7. Assign owners and decide
| Evidence | Decision |
|---|---|
| Active use, known owner, narrow scope, real authentication behind it | Keep; record owner and next review date |
| Active use, but key is the only control | Keep for now with a dated plan to add an authoriser or token validation |
| No use for 90 days, owner known | Owner confirms, then disable or suspend |
| No use, no owner | Disable or suspend after notice; delete after a review cycle |
| Key found exposed | Rotate now (step 8), then investigate use from the logs |
| Over-broad scope or plan | Issue a narrower key, migrate the caller, retire the old one |
Small teams with a handful of partner keys can do this by email in a week. Platforms with thousands of developer-portal keys should automate: tag every key with an owner and a customer ID at issue, and let unused self-service keys expire through a scheduled job, because neither gateway does it for you.
8. Remediate with a rollback ready (destructive, change-controlled)
- Disable before delete: on AWS, set the key's
enabledflag to false; on Azure, set the subscription state to suspended. Both are reversible. Wait one billing or usage cycle before deleting. - Rotate Azure keys with the pair: Microsoft designs keys in pairs so a caller can switch from the primary to the secondary while you regenerate the primary, then the reverse. Confirm the caller has switched in the gateway logs before regenerating the second key.
- Rotate AWS keys by replacement: create a new key, add it to the same usage plan, give it to the caller, watch the logs for the new key ID, then disable the old key. AWS notes that adding a key to a plan can take a few minutes to take effect.
- Narrow scope: split broad usage plans or all-APIs subscriptions into per-product ones, issue new keys, migrate callers, then retire the old plan.
- Add real authentication: attach an IAM, Lambda or Cognito authoriser in AWS, or a
validate-jwtstyle policy in APIM, so the key returns to its proper role of identifying and metering a client.
Verify it worked
The targets below are NHI Mgmt Group recommendations, not vendor or regulatory requirements.
| Metric | Source | Target |
|---|---|---|
| Keys and subscriptions with a named owner | Register and tags | 100% |
| Enabled keys unused for 90 days | get-usage, access logs, ApiManagementGatewayLogs | Zero |
| Methods or APIs where the key is the only control | get-resources --embed methods; APIM policy review | Zero for non-public data, with dated exceptions |
| All-APIs and all-access subscriptions with production traffic | Gateway logs by subscription | Zero |
Key value reads (listSecrets, value-including key reads) outside automation | Activity log, CloudTrail | Each one explained |
| Median key age | Created dates | Within your rotation standard |
Rollback and common errors
- Rollback: re-enable the AWS key or reactivate the APIM subscription. Because you disabled rather than deleted, the caller's existing key works again without reissue. A deleted key has to be recreated and redistributed, so keep deletion for after the review cycle.
- Auditing keys but not plans: a well-owned key in an over-broad plan still opens APIs it was never meant for.
- Relying on quotas for abuse control: AWS states clients can exceed quotas in some cases. Use AWS WAF, budgets and authentication for that job, and the OWASP API Top 10 API4 Unrestricted Resource Consumption Guide for the wider controls.
- Logging the key instead of its ID: AWS says keys travel in headers that can be logged; logging
$context.identity.apiKeyor full request headers copies every key into the log platform. - Keys in the query string: the APIM
subscription-keyquery parameter puts keys in URLs, proxy logs and browser history. Disable it per API by requiring the header. - Forgetting the developer portal: AWS notes that customers can subscribe to all APIs in a usage plan through a developer portal even if you have not made them visible.
Where identity fits
Each key is a non-human identity: a credential held by another organisation's software or by your own front end, with no person attached at the time of use. Treat keys with the same lifecycle as other machine credentials: an owner at issue, a scope, a review date and a retirement path. The API Key Management Guide covers issuance and storage, and the Azure API Management Security guide covers the management plane identities that can read every key.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST CSF 2.0 | PR.AA-01, PR.AA-05, PR.PS-04, DE.CM-03 | Service credentials managed; least privilege; logs generated; usage monitored |
| NIST SP 800-53 Rev 5 | AC-2, AC-2(3), AC-6, IA-5, AU-6, SI-4 | Account management and disabling of inactive accounts, least privilege, authenticator management, log review, monitoring |
| OWASP API Security Top 10 2023 | API2 Broken Authentication; API4 Unrestricted Resource Consumption | Keys used as authentication; quotas and limits |
| CIS Controls v8.1 | Controls 5, 6 and 8 | Account management, access control, audit log management |
| MITRE ATT&CK v20 | T1552.001 Credentials In Files; T1078.004 Cloud Accounts; T1499.003 Application Exhaustion Flood | Keys found in code and config; abuse of valid cloud credentials; resource exhaustion through API calls |
Practitioner checklist
- List every API key and usage plan in every AWS account and Region, without key values.
- List every APIM subscription with scope, state, owner and
allowTracing, without callinglistSecrets. - Map each key to the stages, APIs and methods it opens, and flag methods where the key is the only control.
- Check products and APIs with the subscription requirement turned off.
- Measure last use from
get-usage, access logs andApiManagementGatewayLogs, logging key IDs only. - Alert on key value reads, imports, regeneration and changes to
apiKeyRequired. - Assign owners, then disable or suspend unused keys before deleting them.
- Rotate exposed keys by replacement or the primary and secondary swap, and add real authentication behind keys.
Standards and references
- AWS: Usage plans and API keys for REST APIs in API Gateway
- AWS: Choose an API key source in API Gateway
- AWS CLI Command Reference: get-api-keys
- AWS: Variables for access logging in API Gateway
- AWS: Logging API Gateway API calls using AWS CloudTrail
- Microsoft Learn: Subscriptions in Azure API Management
- Microsoft Learn: API Management REST, Subscription List
- Microsoft Learn: ApiManagementGatewayLogs table reference
Related NHI Mgmt Group resources: API Security Guide, Apigee Security, Kong Gateway Security Guide, OWASP API Top 10 API2 Broken Authentication Guide.