OAuth2 scope model

OAuth2 scope model

Why scopes matter

When an external system authenticates with the Protime API, it receives a token that grants access to API resources. Without scopes, that token would be an all-or-nothing key: either full access to every collection and operation, or no access at all. This creates unnecessary risk – a payroll export service that only needs to read clockings should not hold a token capable of deleting activity definitions.

The OAuth2 scope model solves this by allowing integrators to request only the permissions they need. Each scope grants access to a specific collection and operation type, enabling fine-grained authorization that follows the principle of least privilege.

Scope naming convention

Every scope in the Protime API follows a predictable naming pattern:

connector-protimeapi-<collection>.<permission>

Where:

  • <collection> is the kebab-cased name of the API collection (for example, clockings, activity-definitions, people-historical-data).
  • <permission> is either .read or .write.

Permission types

Permission Grants access to HTTP methods
.read Retrieving resources from the collection GET
.write Creating, updating, and deleting resources POST, PUT, DELETE

Not every collection exposes both permission types. Many collections are read-only and define only a .read scope. For example, the absences collection has connector-protimeapi-absences.read but no corresponding .write scope. The Authentication reference lists which scopes exist for each collection.

A scope is per-collection, not per-endpoint. Holding connector-protimeapi-clockings.read grants access to all GET endpoints under the clockings collection – single resource, list, filtered list, delta, and webhooks for that collection.

Examples

Scope Grants
connector-protimeapi-clockings.read Read clockings (including delta and webhook reads)
connector-protimeapi-clockings.write Create clockings
connector-protimeapi-activity-definitions.read Read activity definitions
connector-protimeapi-people-historical-data.read Read historical field data for people
connector-protimeapi-webhooks.write Create and delete webhook subscriptions

Default behavior

When no scope parameter is included in the token request, the authorization server grants all available scopes that the client credentials are entitled to. While this simplifies initial development, it is not recommended for production use because it violates least-privilege principles and increases the blast radius if credentials are compromised.

Design principles

The scope model reflects several security design principles:

  • Least privilege. Because each scope targets a single collection and operation type, an integration can obtain only the access it requires. A service that exports clockings holds connector-protimeapi-clockings.read and nothing else, reducing the blast radius if its credentials are compromised.
  • Read/write separation. Separating read and write permissions allows an integration to use distinct tokens for retrieval and mutation paths, limiting the damage any single token can cause.
  • Credential isolation. When multiple services integrate with the same tenant, each service can have its own client credentials with a tailored scope set. This prevents one service’s compromise from affecting another’s access.

Scope reference

For the complete list of all available scopes grouped by domain, see the Authentication reference.

How scopes are requested

Scopes are provided as a space-separated string in the scope field of a token request. The authorization server validates the requested scopes against the client’s entitlements and returns the granted set in the token response, making it explicit which permissions the token carries. For the mechanics of constructing a token request with specific scopes, see the Authenticate guide.

Further reading