Protecting Resource APIs with API Scopes

Enabling Zero-Trust, Fit-For-Purpose Scope-Based API Authorization

TRGoodwill
API Central
9 min readOct 31, 2022

--

This discussion is an excursion from the parent article Securing APIs with an Integrated Security Framework

API Scopes

API scopes extend/overload the OAuth scope mechanism and are utilized by OAS 3 and many API management platforms to control access to API operations.

API scopes represent an authorization from the owner of a business resource for a client application to call a particular business resource API. They are used by API gateways to determine the authorised scope of client access to the API. They are sometimes extended to provide additional first-pass role-based end-user access control — providing client applications with visibility of API operations available to users.

API scopes represent a low-granularity, defense-in-depth access decision that answers the question “is this a registered client/user with a valid API use-case?”. Fine-grained access control is always the responsibility of the business service. Access and OIDC identity token claims provide the business service with the means to ask the high-granularity access question “Does this particular user have a right to see the requested data?”.

On API Management platforms, read and write access scopes may be applied to enable self-service to API GET operations (read scope), while back-ending POST, PATCH and DELETE operations (write scope) with a blocking subscription approval workflow.

Documenting API Scope of Access

API scopes are documented by security schemes in the API specification.

Both OpenID (end-user identity) and OAuth2 client credentials (server-to-server) OAuth2 schemes will need to be supported in most cases…

securitySchemes:
OpenID:
type: openIdConnect
openIdConnectUrl: https://example.com/.well-known/openid-configuration
OAuth2: # <------
type: oauth2
flows:
clientCredentials:
tokenUrl: https://example.com/oauth/token
scopes:
read: Grants read access

The OpenID Connect Discovery (OIDC) endpoint provided in the API specification OpenID security definition will return the authorization and token URLs, as well as valid scopes, response types and authentication methods.

API scopes defined in a security scheme are applied at an operation granularity. The following security definition allows either client applications (client credentials) or authenitcated users (OpenID) with read permissions to access the API ‘GET /users’ operation.

paths:
/users:
get:
summary: Get a list of users
security:
- OAuth2: [read] # <------
- OpenID: [read] # <------
...

Applied on its own, an OpenID authentication type will lock down an operation to an OIDC (user identity) flow…

    post:
summary: Create a new user
security:
- OpenID: [write] # <------
...

An API gateway will validate the access token scope values against the security definition and enforce the scope of access authorized by the OAuth2/OIDC authorization server.

Requesting API Scopes

Several scopes for multiple APIs required to fulfill the current service context may be requested in an OAuth2/OIDC authentication request.

GET /authorize?
response_type=id_token%20token
&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&scope=scope1%20scope2
&state=af0ifjsldkj
Host: server.example.com

The generated access token will include the subset of requested scopes to which the user and/or client is authorized, along with the resource audience(s) to which the scopes apply. It will also include the user and client ids, the expiry time and other claims.

Identifying the Token Audience

According to RFC7519 (JWT) and by reference, RFC7662 (OAuth 2.0 Token Introspection), “each principal intended to process the [token] MUST identify itself with a value in the audience claim”.

The “aud” value may be “an array of case-sensitive strings, each containing a StringOrURI value”. When a managed resource API is invoked, the token “aud” value should include one or more resource servers and the API Gateway.

In the indicative example below, audience client Ids are illustrated as URIs for the sake of clarity, however obfuscated identifiers such as a UUID are commonly employed.

{
"aud": [
"https://example.com/resource-server",
"https://example.com/api-gateway"
],
"iss": "https://authorization-server.com/",
"sub": "12B34C",
"exp": 1637359973,
"iat": 1637356372,
"azp": "https://example.com/client-app",
"scope": "openid scope1 scope2"
}

Resource services not explicitly named in the audience claim will not be able to access userinfo and introspection services. Consult your IAM team as to whether it is thier expectation that gateway services performing jwks validation of the token are named in the “aud” claim.

Core OAuth2 and OIDC framework specifications lack a mechanism to identify target resource server(s) for inclusion in the “aud” claim when requesting a token, however RFC 8693: OAuth 2.0 Token Exchange and RFC 8707: Resource Indicators for OAuth 2.0 OAuth2 framework enhancements specifically provide this mechanism.

API Scope Taxonomy

Agreement on an OAuth schema for client system, API scope and potentially other claims will be required. JWT schemas and semantics may be addressed with internal standards, or potentially by the adoption of national or industry digital identity frameworks.

Generic, unambiguous API scopes such as ‘read’ and ‘write’ against an API resource are possible when either or both of rfc 8693 and rfc 8707 are supported. The client may request generic ‘read’ and ‘write’ scopes for multiple resources (a scheme more amenable to OIDC in a large org), and if the user/client is not authorized for that scope against ALL of the requested resources, the scope is not returned. Where authorizations differ across resources (‘write’ access for example), the client must make multiple token requests. Generic scopes must be enterprise defined and broadly applicable to OAuth2/OIDC secured APIs.

Resource-specific, name-spaced API scopes allow tokens to encompass multiple resource services in any case, and provides opportunities for granular, domain-specific access policies – at the cost of additional complexity. In the absence of support for both Token Exchange and Resource Indicators, it will provide a means to identify resource service(s) for inclusion in the access token “aud” claim. API scopes will require a name-spaced taxonomy (e.g. api:[domain]:[resource]:[R|W]) to control clashes, complexity and sprawl.

Some APIM and STS platforms are opinionated about API scope implementation, and may offer deep, proprietary APIM-STS integration to mitigate some of the complexities. Default platform mechanisms and behaviours should be examined and considered.

Authorization Flows

Token service support for RFC 8693: OAuth 2.0 Token Exchange and RFC 8707: Resource Indicators for OAuth 2.0 enhancements to the OAuth 2.0 Authorization Framework is highly desirable in order to enable coherent, standardized flows in support of scope-based API authorization.

The “resource” parameter provided by these specifications allows the client to specify target resources by URI. A mapping between a resource URI and an audience identifier (if different) must be maintained by the authorization server. This detail must be captured during registration of API resources.

Support may be out-of-the-box, or if still ‘on the roadmap’ for your platform, configuration and/or customization can potentially bridge the gap. Some vendors provide configuration assets via public repositories such as github.

Token Exchange Flow

Security platform support for RFC 8693 OAuth 2.0 Token Exchange provides an opportunity to bind API scopes to a resource (mapped to “aud”) — it is a transparent, standardized method of propagating identity and managing access to upstream business resources. The pattern supports generic, unambiguous scopes such as ‘read’, and ‘write’.

In the Token Exchange scenario, the user presents a valid token for the client application. For each new service/API context, the client application will exchange the user access token (with client-side audience and OIDC scope claims) for a new access token (with the required resource service audience and API scope claims).

POST /as/token HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange
&scope=read
&resource=https%3A%2F%2Fbackend.example.com%2Fap

&subject_token=eyJhbGciOiJFUzI1NiIsImtpZCI6IjE2In0.eyJhdWQiOiJodHRw
...

The generated token retains the binding to the user’s identity token.

Indicative OAuth 2.0 Token Exchange flow

Resource services are also able to exchange the token in order to propagate the original end-user identity to resource services further upstream.

Server-to-Server Client Credentials Grant Type Token Request

RFC 8707: Resource Indicators for OAuth 2.0 introduces a resource parameter to the OAuth 2.0 Authorization Framework. The specification allows client servers to define the token audience in a token request or authorization redirect — providing support for scenarios such as client credentials grant type token requests for server-to-server API calls.

POST /as/token HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&scope=scope1%20scope2
&resource=https%3A%2F%2Fbackend.example.com%2Fap
&client_id ...

The scopes returned in the generated token determine the client’s access to API resources.

Indicative client credentials token request specifying the token audience.

Scope-based authorization can be combined with API subscription and subscription approval workflows to control client access.

OIDC Authorization Code Flow

Resource indicators also support OIDC authorization flows in a thin ‘gateway’ client context— the user authorization redirect will include both scope and resource parameters. The user-agent will then make a token request that identifies both the required scopes and the API resource service(s) for the audience claim. As the user is not the resource owner in this context, the user is not asked for access scope consent.

GET /as/authorize?response_type=code
&client_id=s6BhdRkqt3
&state=tNwzQ87pC6llebpmac_IDeeq-mCR2wLDYljHUZUAWuI
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&scope=openid%20read
&resource=https%3A%2F%2Fcal.example.com%2F
&resource=https%3A%2F%2Fcontacts.example.com%2F HTTP/1.1

Host: authorization-server.example.com
Indicative RFC 8707 OIDC Authorization Code flow. Detail varies with context

Tactical Pattern — When Token Exchange and Resource Indicators are Not Yet Supported

When a neither Token Exchange nor Resource Indicators specifications can be supported, the identity of the resource service audience must be derived by the STS via a custom or proprietary mechanism.

The most prominent mechanism is the identification of resources via name-spaced resource-centric scope requests. In this case, each requested API scope maps 1:1 to an API resource and is name-spaced accordingly. In any new service/API context, the client application provides an authorization endpoint redirect to the user-agent, including required API scopes (e.g. api:[domain]:[resource]:[R|W]). For each requested scope, the token service must derive and validate the back-end resource, authorize the scope, and insert the resource service identifier into the “aud” claim.

GET /as/authorize?response_type=code
&client_id=s6BhdRkqt3
&state=tNwzQ87pC6llebpmac_IDeeq-mCR2wLDYljHUZUAWuI
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&scope=openid%20api:membership:applications:read
Host: authorization-server.example.com
Indicative high-level OIDC Authorization Code flow for name-spaced scopes and “aud” derivation.

Registration of API Scopes

A standard authorization/STS platform mechanism for scope management requires client systems to pre-register scopes that may be dynamically requested in an authorization/token request. Where this is the case, client scope registration should be synchronized with API subscription approval via the API client portal. This can be achieved by utilizing the Dynamic Client Registration (RFC 7591) protocol, along with additional scope-of-access subscription fields and/or workflow steps.

Where forms/workflows are not configurable, an alternative tactic is to introduce templated READ and WRITE API subscription plans for each published resource API to align with read and write scopes. Subscription to either a READ or WRITE plan is then approved via standard subscription approval workflows, and corresponding read or write client access scopes registered to the STS/Authz service via dynamic registration (rfc7591).

More on platform integration and dynamic registration here: Securing APIs with an Integrated Security Framework

Controlling Validation Latency in the Gateway

Platform performance profiling is essential, as aggregated gateway introspection latency in can be substantial.

Latency can be controlled with the use of JWTs (rather than opaque tokens) and the implementation of gateway JWKS token validation (rather than introspection). The consideration here is the loss of timely revocation — tactics to control risk might include limiting token lifespan and a token age threshold that would trigger introspection.

Wrap-up

API scopes provide a standard mechanism for API authorization and threat protection based on client, user or invocation context, however a mechanism to identify the target resource for scope authorization and inclusion in the token audience is needed. Support for RFC 8693: OAuth 2.0 Token Exchange and/or RFC 8707: Resource Indicators for OAuth 2.0 can provide such a mechanism. If these specifications cannot be supported, a proprietary or custom method of identifying resource servers such as name-spaced scopes must be employed.

--

--

TRGoodwill
API Central

Tim has several years experience in the delivery and evolution of interoperability frameworks and platforms, and currently works out of Berlin for Accenture ASG