Open jluterek opened 4 years ago
Thanks for the issue. This sounds reasonable. It will have to be prioritised and planned. While we reach out to product could you state what fields on the JWT you would recommend that information to be passed on if you have preferred ones already?
My initial thoughts were organization, team, project, and user. Giving this more thought, I don't believe the organization is needed. Since users are often in multiple teams I'm not sure how difficult it will be to identify their current team for accessing the project.
In order of usefulness:
Okay thanks. Furthermore, do you already have an idea how (of which claim) of the JWT you would see those fields to be defined?
I feel like we are focusing too much on the implementation details here.
I would like first to understand how the external service is supposed to work, meaning for example:
Based on those information, we can have a better understanding of what is actually needed from the external service, and how we can make that happen.
Thanks
I can't discuss client specifics in this open forum, so I would be happy to discuss in a call, slack, or confluence. I will try to answer the questions in a generic way here.
does it need to call the CTP API?
Yes - For one implementation the external service is calling CTP. The service has it's own key/secret. This is to get around a lack of permissions in the Merchant Center regarding shopping lists. The requirements are that any user from their organization in the team Administrators or Technology can have access.
No - Another project will be concerned with calling external services allowing a business user to make very basic configuration changes. Going through a custom application allows for a single place for a business user to login and manage content. In this case, there is a dev and prod project within CT and a dev/prod configuration in the external services. Users with access to the dev project in CT will have access to the dev external API. Users with access to the prod project in CT will have access to the prod external API.
does it need "higher" level information like, projects and orgs of the user? If so, why?
Many companies have multiple projects, often a development and production project. Passing the project key allows the external service to verify this information before making production level changes.
The project key can also be used to determine if the user has access to call this service. For example, the external API may allow anyone who has access to the production project to read from the service. It also prevents a user from creating their own MC account and calling that external service as it will be called from a different project. While this can be done at the user level that creates an additional burden as users are added and removed in the Merchant Center the External API would need to be maintained.
The current organization is not needed, but an indication of that user's permissions within the organization. Since the Merchant Center groups users into Teams in order to allocate permission levels this is often how companies manage access. Providing Team information would allow for proper access restrictions on the external API.
does it not call any of the CTP APIs?
See above.
does it use any sort of authorization? Is it based on "custom permissions" or does it rely on the CTP permissions?
Yes. The currently documented approach allows for locking down an external API to ANY Merchant Center user. The goal is to allow for a more granular approach to add additional security to the external API.
The most granular is user-specific. It is also important to pass userid for any logging needed.
The MC allows users to be grouped for permission purposes, it would be useful to leverage this same grouping when evaluating permissions. An example would be that Administrators and Shop Owners could access the API, but Customer Service can not. This would mean passing the current team (the one allowing them to access the MC Custom Application), not the full list of teams for the user.
While having the Team would be great (it fits how companies consider MC permissions), it may be more difficult on the technical side. A simpler approach may be to pass the CT scopes for that user in the current project. Then some type of mapping can be done (Admins and Shop Owners have edit order permissions so look for that scope). This is not how companies have defined their requirements to me, but I could see it as a workaround if others deem it a better approach.
It's important that the data passed would be specific to that call not for the user. For example if a user belongs to multiple organizations and teams:
UserID: 12345
Organizations: [abc, def, ghi]
Teams: [a1, d2, g3]
Projects: [abc1, abc2, def1, def2, ghi1]
This user calls an external API from a custom application registered in project abc1, the only data that external API would have access to is around that call:
UserID: 12345
Team: a1
Project: abc1
Providing the full list of teams would expose too much information.
Thanks a lot for the extended feedback. This is already a good start!
We will discuss this internally and get back to you if we have more questions.
A couple of follow up questions first:
The service has it's own key/secret.
I suppose what you might need from the MC is to give you the list of scopes that you would need to get an access token from CTP. The MC could perform some initial checks (about the user + project) and extract the necessary scopes from the user's permissions.
Alternatively, you can simply ask the MC to give you a valid access token for this user + project.
Those are just a couple of ideas first, just to understand if that would be enough for you. For an external service to access orgs and teams information might not be what you really need we are also not sure we want to expose this information.
suppose what you might need from the MC is to give you the list of scopes
I understood that differently. The permissions might be enough. The service could then use those. If the scopes would then be needed the service could talk to another GraphQL query returning a set of scopes given a set of permissions.
I suppose what you might need from the MC is to give you the list of scopes that you would need to get an access token from CTP. The MC could perform some initial checks (about the user + project) and extract the necessary scopes from the user's permissions.
Alternatively, you can simply ask the MC to give you a valid access token for this user + project.
Those are just a couple of ideas first, just to understand if that would be enough for you. For an external service to access orgs and teams information might not be what you really need we are also not sure we want to expose this information.
Having the MC give a valid access token would not help at all. Unless it can be used to query additional information about the user, but then why not pass the info first instead of needing a follow-up call.
For the first scenario where this external API accesses CTP resources. We can not use an access token for the user+project. That access token is scoped only for resources managed in the Merchant Center. So there is no way to scope that token for endpoints like Shopping Lists or Reviews. I'm hoping that eventually, this scenario will go away as MC permissions evolve, but currently, an external API with its own key/secret is a workaround.
For the second scenario of accessing another service, there is no need for a CTP token. Here we need to build rules around WHO can access that service. That is where a UserID, or TeamID can be leveraged, in order to build rules. Permission rules I've received follow the format:
Extracting the user scopes and passing that along with the userid could work depending on Team structure.
The UserID would be used for logging changes.
Is your feature request related to a problem? Please describe.
I am building an external service that will be leveraged by a Custom Application. The service will be called following the procedure outlined in https://docs.commercetools.com/custom-applications/main-concepts/proxy-to-external-api
There is no way to secure the external API and limit access to the correct users. The only option is to validate that the user has a Merchant Center login. Since you can sign-up for a free trial at any time (providing a Merchant Center login), the API is open to the public.
There should be a process to lock an API down to a set of specific users. This could be through project, organization, permissions, or group.
Describe the solution you'd like
I'd like to see the organization, team, project, and user-name passed through the JWT claims. The service could then check this data when validating the bearer token.
Describe alternatives you've considered
I have considered passing this data in each call, but saw multiple problems:
I also wondered if the bearer token could be used to call another MC API that would retrieve this data, but there is already a lot of traffic validating the token and another call would add complexity and latency.
Additional context