question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[CEP] Improve granularity of API key access controls

See original GitHub issue

Abstract

CommCare does not have any granularity in our user / role permission model to properly restrict API access. This CEP is to provide a mechanism to allow more fine-grained control over API access at the token level instead of relying on user-level controls only.

Motivation

Today CommCare has the notion of permissions at the user/project level. Users are provided access to projects (domains) and project administrators control the level of access granted to those users via the Roles and Permissions framework.

Additionally, users have API keys, which can be associated with a whitelisted set of IP addresses. API keys can also be deleted (revoked). API keys do not provide any granularity on top of the user’s permissions. All API keys grant access to whatever the user can access.

For a third-party integration ecosystem it’s important that we can properly scope API access to the most narrow set of rights as possible. External applications should be able to access the minimum set of data needed for those applications to function, and not all data available to the user.

Specification

This CEP seeks to add more fine-grained control over APIs.

The rest of this section documents permissions in the context of an API key, but the same should apply to an Oauth application, and any future externally integratable authentication mechanisms.

Types of access

It’s unclear which set of these controls we will need. At a minimum we likely need Domain-level access. The specifics of which types will be added will depend on emerging requirements and feasibility.

Identity Access

Identity access would simply let users confirm they are who they say they are, and potentially provide a few details, for example email address and name. It would not provide access to any underlying data.

Identity access would primarily be used for external authentication. For example, using something like OpenID Connect.

Domain-Level Access

API keys should be able to be scoped to particular projects. For example, a user should be able to say for a particular API key that it can access their data from one project, but not from others. This will allow users to safely scope the data permissions provided to the project spaces they seek to integrate with.

Permission-Level Access

In this model you could hook into the Roles and Permissions framework to associate the API key with a particular set of permissions. For example, you could create an API key that only provided access to application data but not report data or individual cases/forms. Or you could create roles that can read data but not modify it.

API-Level Access (likely ruled out for the first version)

This would be the most fine-grained option. In it, you could grant access to specific APIs, as well as choose the type of access (e.g. read/write). Any APIs not explicitly included would not be allowed.

Modeling

Since at a minimum we would like to share functionality between API keys and Oauth grants, these models should extend from some shared interface. We’ll call it a PermissionCollection.

In YAML, this model would look something like this (this uses the “permission-level access” paradigm mentioned above, just as an example):

name: role1
domain_permissions:
  domain1: 
    - view_apps
    - view_reports
    - edit_data
  domain2:
    - view_apps

In English, this would represent: the “role1” role has the “view_apps”, “view_reports”, and “edit_data” permissions on domain1, and the “view_apps” permission on “domain2”.

Then both API Keys (via HQApiKey) and Oauth Grants (likely via a new model) would extend this interface.

Permission Checks

Permission checks would apply everywhere that API-based authentication is supported (which is basically just APIs). We would start by building this functionality for tastypie endpoints only

Our current tastypie implementation conflates authentication and authorization, e.g. RequirePermissionAuthentication actually includes authorization checks built into the authentication workflow.

For this work it is recommended to decouple authentication from authorization. So the authentication class would simply verify the user account and the (new) authorization class would check permissions. In order to maintain authorization at the API Key level, some state will have to be maintained about how the user authenticated. The details of this need to be ironed out, but it should be possible to save the data e.g. on the request object.

Impact on users End users who make use of APIs will be able to have finer-grained control over how their API keys grant access than they currently do.

Impact on hosting No anticipated impact.

Backwards compatibility To ensure backwards compatibility all existing API keys must be granted “all” access either as a default behavior or via a data migration.

Release Timeline No concrete timeline as of yet.

Open questions and issues

  • What’s the right type of access to provide?
  • How do we handle API permission migrations if we make permissions more restrictive?

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:16 (16 by maintainers)

github_iconTop GitHub Comments

1reaction
czuecommented, Sep 1, 2020

I’m working on the UI for this. Basically adding (optional) “domain” and “role” selection boxes to the API key UI. Does anyone want to make the case that those options shouldn’t be generally available? Thinking I won’t bother with a feature flag.

cc @dimagi/product

1reaction
orangejennycommented, Aug 20, 2020

Backwards compatibility does seem tough. This approach seems right:

Guessing we would just need to announce the change and be willing to break integrations if people don’t update their roles?

I also agree with @esoergel that we’d benefit from using the existing roles and permissions framework. I’d imagine API permissions would eventually get more granular than our existing permissions, possibly to the point of granting access to specific endpoints, but I think ideally that granularity would be an additional layer that uses most of the same code but isn’t visible in the UI, rather than a totally separate framework. That’d hopefully let us share code, and it also seems better for users to only have one permissions model to comprehend.

Read more comments on GitHub >

github_iconTop Results From Across the Web

API Design — Granularity Concerns -PART 1 - Medium
The optimal granularity of the API is one of the main challenges in the design and implementation of distributed systems as it impacts...
Read more >
25 API Security Tips You're Probably Not Considering
“Treat APIs like they have a direct interface into your underlying systems and can bypass security controls – because that is pretty much ......
Read more >
Controlling and managing access to a REST API in API Gateway
Learn how to control and manage access to a REST API in Amazon API Gateway.
Read more >
API Security Best Practices MegaGuide
Users should have the ability to revoke the current authorization of an API key. Revocation is needed in situations where the key may...
Read more >
How to Improve the Security of API Keys | HackerNoon
One way to improve security is to keep the API key out of the channel. Instead of adding the plaintext API key to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found