API keys¶
Your backend authenticates to the perms.io API with an API key. Each key belongs to one project.
Creating a key¶
In the dashboard, pick the project in the project switcher, open API Keys and click Create New Key. Give the key a name, ideally after the service or environment that will use it, and click Create key.
Shown once
The full key is only shown once, when it is created. Copy it into your secrets manager straight away. perms.io only stores a hash of the key, so it can't show it to you again. If you lose a key, create a new one and invalidate the old one.
Format¶
Keys are opaque, 44-character strings:
perms_ + 32 random base62 characters + 6-character checksum
- The
perms_prefix makes leaked keys easy for secret scanners to spot. - The last 6 characters are a CRC32 checksum of the random part. Clients can use them to reject a mistyped or truncated key before sending it. The TypeScript SDK does this in its constructor.
- The checksum only catches typos. Whether a key exists and is still valid is decided by the API.
Older keys were issued as JWTs. These are still accepted.
Sending a key¶
Send the key as a bearer token on every request:
Authorization: Bearer perms_...
authorization: Bearer perms_...
A request with a missing, unknown or invalidated key is rejected with Unauthenticated (HTTP 401).
Access levels¶
A key is a principal in its own right. When it is created, the key is granted a role on its project, and that role decides which calls the key may make.
| Access | Role | Allows |
|---|---|---|
| Check (default) | apikey.checker |
Check, BatchCheck, ListAccess and ListPrincipalsWithAccess. Reading permissions, roles, principals, assignments, groups and group members (permission.check, permission.get, permission.list, role.get, role.list, principal.list, principal.assignment.get, principal.assignment.list, group.get, group.list, group.member.list). |
| Full access | apikey.manager |
Everything above, plus creating, updating and deleting permissions, roles and groups, granting and revoking, and adding and removing group members (permission.create/update/delete, role.create/update/delete, principal.assignment.create/delete, group.create/update/delete, group.member.add/remove). |
Each RPC's level is listed in the API reference.
Choosing the level¶
The level is set when the key is created, with the access field of
CreateAPIKey:
access |
Level |
|---|---|
API_KEY_ACCESS_CHECK |
Check. |
API_KEY_ACCESS_FULL |
Full access. |
API_KEY_ACCESS_UNSPECIFIED (or left out) |
Check. |
The key's access field reports its level when you list keys. A key's level can't be changed later: create a new
key with the level you need and invalidate the old one.
To create a key with a given level, you must hold every permission that level grants on the project, so nobody can
create a key with more access than they have. Otherwise the call fails with PERMISSION_DENIED. Choosing the level
when creating a key in the dashboard is being added. Until it is available there, keys created in the dashboard get
check access.
Give a key the least access it needs. A service that only checks permissions, filters lists or shows who has access needs only check access. Use full access for services that manage permissions, roles, grants or groups.
A call the key isn't allowed to make is rejected with PermissionDenied (HTTP 403). This is about the key's rights,
not the principal you are checking. For Check, the key needs permission.check on the checked resources and on
the principal, which the check role gives it across its whole project.
Neither role includes organisation-level permissions. Most Organisation service calls are meant for the dashboard and will be denied for an API key.
Invalidating a key¶
On the API Keys page, click Invalidate next to the key and confirm. The key stops working immediately and this can't be undone. Its grants on the project are removed too. Invalidated keys stay listed, marked Invalidated.
Keys created in the dashboard don't expire, so invalidate any key you no longer need.
Good practice¶
- Use one key per service and environment, so you can invalidate one without affecting the others.
- Keep keys on the server. Never ship a key in browser or mobile code: anyone who loads the page can read it.
- Store keys in a secrets manager or environment variables, not in source control.