Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access control via sub claim #86

Open
uniqueg opened this issue Apr 26, 2021 · 3 comments
Open

Access control via sub claim #86

uniqueg opened this issue Apr 26, 2021 · 3 comments
Assignees
Labels
priority: high High priority type: auth Related to authorization or authentication type: feature New feature or request type: security Related to security workload: weeks Likely takes weeks to resolve

Comments

@uniqueg
Copy link
Member

uniqueg commented Apr 26, 2021

Currently, anyone with a valid access token can access all the resources in the service. While this may sometimes be desirable, there are many situations where only specific people should be able to a given resource.

For now, the easiest way of granting access control to specific endpoints is by recording a user's identity when registering a resource and then, when access to that resource is requested, check that the person requesting the resource is the same person that registered it. This can be done via the JWT's sub claim. If a user then supplies a valid token and the correct sub claim, they will get access. If the sub claim does not match, a 403 response should be returned.

The solution to be implemented should allow some level of controlling this behavior to cover as many use cases as possible. For example, a user might want to register a tool and then only that user should be able to modify or delete that resource. However, the user may want everyone to be able to access the tool, perhaps even without providing an access token at all.

The solution should also consider later extension by checking for other specific claims in a token, e.g., those that confer some form of group membership.

Code repetition should be avoided, and usage as simple as possible. The information on who registered which resources should always be recorded in the database. The logic to check if the sub claim matches the one recorded could, for example, be implemented as a decorator that wraps the endpoints that should be protected against access by unauthorized users. If implemented in a sufficiently abstract manner, the code could also be put into FOCA (preferable) and corresponding config options could be implemented (e.g., a dictionary of controller functions/classes and access control configurations) there.

Before starting to implement this, please draw up a detailed plan on how you plan to implement the feature so that we can discuss if/how to improve the design with respect to usability, general applicability, extensibility and the possibility to migrate the solution to FOCA so that other services can make use of it, too.

@uniqueg uniqueg added priority: high High priority type: auth Related to authorization or authentication type: feature New feature or request type: security Related to security workload: weeks Likely takes weeks to resolve labels Apr 26, 2021
@anuragxxd anuragxxd self-assigned this May 6, 2021
@anuragxxd
Copy link
Member

As mentioned above this structure is based on the use of the foca to easily implement it across different services:-

As MongoDB is used as our default database across different services. It attaches the uniques _id field to any new records being saved in any schema. We can make use _id field to uniquely identify each user. Service schema can store the extra field as the array of the users which have the permissions for the that service. Permissions can be based on the levels. Eg:-

Owner:- Have access to permit new users/groups to the service. Can do read, update & delete operations on the service.
Manager:- Can do read & update operations on the service.
Reader:- Can read and register the service.

When user requests for the the service we can send the _id of the user along with the request in JWT and check in service schema for the details of the user using JWT sub claim as told above. For the any operation user does on the service he/she has to first authorize for that operation according to the user levels. This approach will also helps us to connect the service schema with the user schema using the foreign keys as we are using _id here. This will help allowing user to list out all the serivces he he authorized to use and to what extend (i.e. level) or Owner of the service to list out all the user which are authorized to use the service.

Service model can be:-

Service: {
    ...all other properties, 
    users: [
         user: {
               id : {
                    type: ObjectId(), 
                    ref: 'UserSchema'
               },
               level : {
                    type: String, 
               },
         }
    ]
}

Any addition will be great. @uniqueg

@uniqueg
Copy link
Member Author

uniqueg commented May 17, 2021

Thanks @git-anurag-hub! I don't understand your suggested solution fully. Some questions/comments:

  • It reads as if you suggest that the _id field that MongoDB creates for each resource is somehow user-specific. It is not. It uniquely identifies a resource.
  • I am not a 100% sure that a JWT token's sub claim uniquely identifies a user (you would need to validate that first). Also, this may not go both ways, i.e., a sub claim value may be unique to a user, but a user may not have a unique sub claim, even within the context of a single identity provider (I think I have seen this before). If the sub claim is not stable - it is not a good candidate to store in the database as a mapping for the roles, because I may register a service today, but tomorrow (with a new sub claim), I can't access it anymore. This needs some more research.
  • Otherwise the approach of storing an object outlining the permitted users with their roles together with a resource is fine of course, but it would be good to think of a way how this can be leveraged at the level of FOCA. I haven't really seen that in your proposed solution (or I didn't understand it). It's not an absolute requirement, but would be super helpful to reuse the approach in other services.
  • I suppose a reader should have only the ability to read a service, not modify it. In this regard, note that there should also be a mechanism by which a resource can be made public, i.e., everyone should be able to read a resource.

Can you please clarify these issues?

@anuragxxd
Copy link
Member

anuragxxd commented May 26, 2021

Answers as follows:-

  • As we know now that sub claim values are globally stable & unique for all the users we can use that as the unique identifier for the user. (We don't need to use _id now).
  • Sub claim can now go both ways i.e. It is unique so it can act as an identifier & It is stable so it doesn't recycle over time. So it won't cause any problems.
  • As of now, we are having the service schema's specific to the services and not included in the foca. By the above approach, it will be important to change the service schema. Another approach can be to make the user schema in the foca and then to store the user-specific serviceId's (or any unique service identifier) in that schema. It will make foca as the centralized source for the users to get the services. (If this looks good we can proceed with this too)
  • Yeah reader can't modify the service he/she can only read the service. For public we can add the field in the service schema named public type Boolean which when true represents that service in public & vice-versa. (Moreover, here also we can face the issue of changing the service schema for every registry service).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: high High priority type: auth Related to authorization or authentication type: feature New feature or request type: security Related to security workload: weeks Likely takes weeks to resolve
Projects
None yet
Development

No branches or pull requests

3 participants