rabbitmq-server
                                
                                
                                
                                    rabbitmq-server copied to clipboard
                            
                            
                            
                        Support Rich Authorization Request OAuth2 specification
Proposed Changes
Rich Authorization Request specification is an extension to the OAuth2 specification. It is still a draft but it has been stable for a good while. This specification moves away from the concept of scopes and instead proposes a new JWT token field called authorization_details which consists of a list of permissions where each permission is meant for one type of resource server and it defines a list of locations and a list of actions allowed on those locations. Here is an example of a JWT token using this specification:
{
    ... ,
  "authorization_details": [
     {
      "type":"rabbitmq-endpoint", 
      "locations": [
          "cluster:rabbitmq/vhost:finance"
      ],
      "actions": [ "read", "write", "configure", "tag:administrator" ]
    }
  ]
}
A RabbitMQ server/cluster is configured with a resource_server_id which uniquely identifies it. And in this new PR we are introducing a new setting called resource_server_type which is used as a permissions' discriminator. In other words, RabbitMq will only look into those permissions which are tagged with a type which matches the value configured in resource_server_type . In the example above, resource_server_id would be rabbitmq and resource_server_type would be rabbitmq-endpoint.
The specification does not make any recommendations on the exact format of the values in the locations field. The format will be defined by the resource server the location is targeting. More on that, this PR suggests the following location's structure :
cluster:<resource_server_id_pattern>[/vhost:<vhostpattern>][/queue:<queue_name_pattern>|/exchange:<exchange_name_pattern][/routing-key:<routing_key_pattern>].
Any string separated by / which does not conform to <key>:<value> is ignored. For instance, if your locations start with a prefix, e.g. vrn/cluster:rabbitmq, the vrn pattern part is ignored.
Although it is not strictly speaking part of the Rich Authorization Request specification, we are including into this PR the ability to disable the validation of the aud field. Thru a new setting called verify_aud we can disable it. By default, it is enabled.
Types of Changes
What types of changes does your code introduce to this project?
- [ ] Bug fix (non-breaking change which fixes issue #NNNN)
 - [x ] New feature (non-breaking change which adds functionality)
 - [x] Breaking change (fix or feature that would cause an observable behavior change in existing systems)
 - [ ] Documentation improvements (corrections, new content, etc)
 - [ ] Cosmetic change (whitespace, formatting, etc)
 - [ ] Build system and/or CI
 
Checklist
Put an x in the boxes that apply.
You can also fill these out after creating the PR.
If you're unsure about any of them, don't hesitate to ask on the mailing list.
We're here to help!
This is simply a reminder of what we are going to look for before merging your code.
- [ ] I have read the 
CONTRIBUTING.mddocument - [ ] I have signed the CA (see https://cla.pivotal.io/sign/rabbitmq)
 - [x] I have added tests that prove my fix is effective or that my feature works
 - [x] All tests pass locally with my changes
 - [ ] If relevant, I have added necessary documentation to https://github.com/rabbitmq/rabbitmq-website
 - [ ] If relevant, I have added this change to the first version(s) in release-notes that I expect to introduce it
 
Further Comments
This PR will be validated by stakeholders who requested it before being reviewed and merged/released.
@MarcialRosales Why do we need tag in actions (example: tag:administrator)? there is a possibility that identity providers can reserve ":" for some specific use cases. Why can't we consider administrator as admin without "tag"?
{
"authorization_details": [
{ "type" : "rabbitmq",
"locations": ["cluster:finance/vhost:primary-*"],
"actions": [ "read", "write", "configure"  ]
},
{ "type" : "rabbitmq",
"locations": ["cluster:finance", "cluster:inventory" ],
"actions": ["tag:administrator" ]
}
]
}
Because that's how management plug-in roles have been since 2010.
We cannot avoid potential tag name conflicts, the idea is that RabbitMQ tokens/scopes are not reused by arbitrary apps.
It appears this issue with the colon on the user-tag's actions is a blocker because the identity provider does not tolerate colons on the action's values. To overcome this issue there are a few alternatives.
- very simple - Drop the prefix 
tag:from the action mane, e,g.administratorormanagement. There should not be any clash with other resource servers because every authorization entry withinauthorization_detailsis for just one resource type. - rather complex - Configure rabbitmq with 
action_aliasessimilar toscope_aliases. This rather complex alternative not only allows us to map a user-defined action name to a rabbitmq action name, e.g.admin->tag:administratorbut also map one user-defined action to many rabbitmq¡'s actions: 
{action_aliases, #{
               <<"FullAccess">>      => [<<"tag:administrator">>, <<"configure">>, <<"write">>, <<"read">> ],
Although this latter alternative is more flexible I would rather stick to the simpler one.
@MarcialRosales both seem OK to me but we can try dropping the prefix since the set of tags used by the management plugin is known ahead of time.
We can also support a different character for separator, e.g. tag=management