Merge pull request #146 from pedroigor/master
Improvements and documenting new entitlement request metadata
This commit is contained in:
commit
b945767fc1
9 changed files with 171 additions and 76 deletions
|
@ -88,8 +88,10 @@
|
||||||
... link:authorization_services/topics/service/entitlement/entitlement-api.adoc[Entitlement API]
|
... link:authorization_services/topics/service/entitlement/entitlement-api.adoc[Entitlement API]
|
||||||
|
|
||||||
.... link:authorization_services/topics/service/entitlement/entitlement-api-aapi.adoc[Requesting Entitlements]
|
.... link:authorization_services/topics/service/entitlement/entitlement-api-aapi.adoc[Requesting Entitlements]
|
||||||
|
.... link:authorization_services/topics/service/entitlement/entitlement-request-metadata.adoc[Entitlement Request Metadata]
|
||||||
|
|
||||||
... link:authorization_services/topics/service/protection/token-introspection.adoc[Introspecting a Requesting Party Token]
|
... link:authorization_services/topics/service/rpt/overview.adoc[Requesting Party Token (RPT)]
|
||||||
|
.... link:authorization_services/topics/service/rpt/token-introspection.adoc[Introspecting a Requesting Party Token]
|
||||||
|
|
||||||
... link:authorization_services/topics/service/client-api.adoc[Authorization Client Java API]
|
... link:authorization_services/topics/service/client-api.adoc[Authorization Client Java API]
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
Before going further, it is important to understand these terms and concepts introduced by {{book.project.name}} {{book.project.module}}.
|
Before going further, it is important to understand these terms and concepts introduced by {{book.project.name}} {{book.project.module}}.
|
||||||
|
|
||||||
|
[[_overview_terminology_resource_server]]
|
||||||
==== Resource Server
|
==== Resource Server
|
||||||
|
|
||||||
Per OAuth2 terminology, a resource server is the server hosting the protected resources and capable of accepting and responding to protected resource requests.
|
Per OAuth2 terminology, a resource server is the server hosting the protected resources and capable of accepting and responding to protected resource requests.
|
||||||
|
|
|
@ -45,7 +45,8 @@ if (contextAttributes.containsValue('kc.client.network.ip_address', '127.0.0.1')
|
||||||
You can also use role-based access control (RBAC):
|
You can also use role-based access control (RBAC):
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var identity = $evaluation.getIdentity();
|
var context = $evaluation.getContext();
|
||||||
|
var identity = context.getIdentity();
|
||||||
|
|
||||||
if (identity.hasRole('keycloak_user')) {
|
if (identity.hasRole('keycloak_user')) {
|
||||||
$evaluation.grant();
|
$evaluation.grant();
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
[[_service_authorization_api_aapi]]
|
[[_service_authorization_api_aapi]]
|
||||||
==== Requesting Authorization Data and Token
|
==== Requesting Authorization Data and Token
|
||||||
|
|
||||||
Client applications using the UMA protocol can use a specific endpoint to obtain a special security token called a requesting party token (RPT).
|
Client applications using the UMA protocol can use a specific endpoint to obtain a special security token called a <<fake/../../rpt/overview.adoc#_service_rpt_overview, Requesting Party Token (RPT)>>.
|
||||||
This token consists of all the permissions granted to a user as a result of the evaluation of the permissions and authorization policies associated with the resources being requested.
|
This token consists of all the permissions granted to a user as a result of the evaluation of the permissions and authorization policies associated with the resources being requested.
|
||||||
With an RPT, client applications can gain access to protected resources at the resource server.
|
With an RPT, client applications can gain access to protected resources at the resource server.
|
||||||
|
|
||||||
|
.UMA compliant Authorization API Endpoint
|
||||||
```bash
|
```bash
|
||||||
http://${host}:${port}/auth/realms/${realm_name}/authz/authorize
|
http://${host}:${port}/auth/realms/${realm_name}/authz/authorize
|
||||||
```
|
```
|
||||||
|
|
||||||
When requesting an RPT, you need to provide two things:
|
When requesting an RPT, you need to provide two things:
|
||||||
|
|
||||||
* A <<fake/../../protection/permission-api-papi.adoc#_service_protection_permission_api_papi, permission ticket>> with the resources you want to access
|
* A <<fake/../../protection/permission-api-papi.adoc#_service_protection_permission_api_papi, permission ticket>> representing the resources you want to access
|
||||||
* The <<fake/../whatis-obtain-aat.adoc#_service_authorization_aat, authorization API token (AAT)>> (as a bearer token) representing a user's identity and his consent to access authorization data on his behalf.
|
* The <<fake/../whatis-obtain-aat.adoc#_service_authorization_aat, Authorization API token (AAT)>> (as a bearer token) representing a user's identity and his consent to access authorization data on his behalf.
|
||||||
|
|
||||||
|
The permission ticket is added to a HTTP request as a parameter whether the AAT is included in a ```Authorization``` header in order to authenticate de request
|
||||||
|
using the AAT as a bearer token.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -X POST
|
curl -X POST
|
||||||
|
@ -26,33 +30,3 @@ As a result, the server response is:
|
||||||
```json
|
```json
|
||||||
{"rpt":"${RPT}"}
|
{"rpt":"${RPT}"}
|
||||||
```
|
```
|
||||||
|
|
||||||
===== Requesting Party Token
|
|
||||||
|
|
||||||
A Requesting Party Token (RPT) is a https://tools.ietf.org/html/rfc7519[JSON web token (JWT)] digitally signed using https://www.rfc-editor.org/rfc/rfc7515.txt[JSON Web Signature (JWS)].
|
|
||||||
The token is built based on the AAT sent by the client during the authorization process.
|
|
||||||
|
|
||||||
When you decode an RPT you will see something like:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"authorization": {
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"resource_set_id": "d2fe9843-6462-4bfc-baba-b5787bb6e0e7",
|
|
||||||
"resource_set_name": "Hello World Resource"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"jti": "d6109a09-78fd-4998-bf89-95730dfd0892-1464906679405",
|
|
||||||
"exp": 1464906971,
|
|
||||||
"nbf": 0,
|
|
||||||
"iat": 1464906671,
|
|
||||||
"sub": "f1888f4d-5172-4359-be0c-af338505d86c",
|
|
||||||
"typ": "kc_ett",
|
|
||||||
"azp": "hello-world-authz-service"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
From this token you can obtain all permissions granted by the server from the *permissions* claim.
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,37 @@
|
||||||
[[_service_entitlement_api_aapi]]
|
[[_service_entitlement_api_aapi]]
|
||||||
==== Requesting Entitlements
|
==== Requesting Entitlements
|
||||||
|
|
||||||
Client applications can use a specific endpoint to obtain a special security token called a requesting party token (RPT).
|
Client applications can use a specific endpoint to obtain a special security token called a <<fake/../../rpt/overview.adoc#_service_rpt_overview, Requesting Party Token (RPT)>>.
|
||||||
This token consists of all the entitlements (or permissions) for a user as a result of the evaluation of the permissions and authorization policies associated with the resources being requested.
|
This token consists of all the entitlements (or permissions) for a user as a result of the evaluation of the permissions and authorization policies associated with the resources being requested.
|
||||||
With an RPT, client applications can gain access to protected resources at the resource server.
|
With an RPT, client applications can gain access to protected resources at the resource server.
|
||||||
|
|
||||||
|
.Entitlement API Endpoint
|
||||||
```bash
|
```bash
|
||||||
http://${host}:${port}/auth/realms/${realm_name}/authz/entitlement
|
http://${host}:${port}/auth/realms/${realm_name}/authz/entitlement/{client_id}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The **client_id** parameter above must be provided in order to identify the client application acting as a <<fake/../../../overview/terminology.adoc#_overview_terminology_resource_server, resource server>>
|
||||||
|
in {{book.project.name}}. You must provide the client identifier in order to restrict the scope of the evaluation to the resources, scopes and permissions
|
||||||
|
managed by a specific resource server.
|
||||||
|
|
||||||
|
The Entitlement API comes in two flavors:
|
||||||
|
|
||||||
|
* Using HTTP **GET** in order to obtain all entitlements based on the resources owned by a specific user or/and general resources
|
||||||
|
owned and managed by the resource server itself.
|
||||||
|
|
||||||
|
* Using HTTP **POST** in order to obtain entitlements based on a a set of one or more resources and scopes sent along with an entitlement request.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
Using one or another depends on your use case and how much resources you have registered in {{book.project.name}}. Although the **GET** variant
|
||||||
|
provides an easy way to obtain entitlements from the server, it might not be appropriate in case you have too much resources associated
|
||||||
|
with an user. In this case, the **POST** method is recommended.
|
||||||
|
|
||||||
|
Regardless of the HTTP method you decide to use, the Entitlement API endpoint expects an access token in the request representing a user's identity
|
||||||
|
and his consent to access authorization data on his behalf. The access token must be sent as a bearer token using a HTTP ```Authorization``` header.
|
||||||
|
|
||||||
|
After successfully invoking the Entitlement API endpoint, you will get a <<fake/../../rpt/overview.adoc#_service_rpt_overview, RPT>> with all permissions
|
||||||
|
granted by the server.
|
||||||
|
|
||||||
===== Obtaining Entitlements
|
===== Obtaining Entitlements
|
||||||
|
|
||||||
The easiest way to obtain entitlements for a specific user is using an HTTP GET request. For example, using curl:
|
The easiest way to obtain entitlements for a specific user is using an HTTP GET request. For example, using curl:
|
||||||
|
@ -16,14 +39,9 @@ The easiest way to obtain entitlements for a specific user is using an HTTP GET
|
||||||
```bash
|
```bash
|
||||||
curl -X GET \
|
curl -X GET \
|
||||||
-H "Authorization: Bearer ${access_token}" \
|
-H "Authorization: Bearer ${access_token}" \
|
||||||
"http://localhost:8080/auth/realms/hello-world-authz/authz/entitlement/${resource_server_id}"
|
"http://${host}:${port}/auth/realms/${realm_name}/authz/entitlement/{client_id}"
|
||||||
```
|
```
|
||||||
|
|
||||||
[NOTE]
|
|
||||||
When requesting entitlements using this endpoint, you must provide the access_token (as a bearer token) representing a user's identity and his consent to access authorization data on his behalf.
|
|
||||||
|
|
||||||
In the curl example, *${resource_server_id}* is the *client_id* registered with the client application acting as a resource server.
|
|
||||||
|
|
||||||
As a result, the server response is:
|
As a result, the server response is:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
@ -33,7 +51,17 @@ As a result, the server response is:
|
||||||
```
|
```
|
||||||
|
|
||||||
Using this method to obtain entitlements, the server responds to the requesting client with *all* entitlements for a user, based on the evaluation of the permissions and
|
Using this method to obtain entitlements, the server responds to the requesting client with *all* entitlements for a user, based on the evaluation of the permissions and
|
||||||
authorization policies associated with the resources managed by the resource server.
|
authorization policies associated with the resources owned by the user or the resource server itself. For instance, suppose you have permissions defined in {{book.project.name}} for the following resources:
|
||||||
|
|
||||||
|
* Main Page
|
||||||
|
* Alice Bank Account
|
||||||
|
* Bob Bank Account
|
||||||
|
|
||||||
|
*Main Page* is a common resource in your application and owned by the resource server itself, it represents a landing or main page in your application. On the
|
||||||
|
other hand, *Alice Bank Account* is a resource where user *alice* is the owner. The same goes for *Bob Bank Account* which is owned by a different user, *bob*.
|
||||||
|
|
||||||
|
When obtaining entitlements for user *alice*, the server is going to evaluate all permissions associated with resources *Main Page* and *Alice Bank Account*. Giving you
|
||||||
|
back a RPT (if permissions were actually granted) with a set of permissions representing these resources.
|
||||||
|
|
||||||
===== Obtaining Entitlements for a Specific Set of Resources
|
===== Obtaining Entitlements for a Specific Set of Resources
|
||||||
|
|
||||||
|
@ -43,10 +71,10 @@ You can also use the entitlements endpoint to obtain a user's entitlements for a
|
||||||
curl -X POST -H "Authorization: Bearer ${access_token}" -d '{
|
curl -X POST -H "Authorization: Bearer ${access_token}" -d '{
|
||||||
"permissions" : [
|
"permissions" : [
|
||||||
{
|
{
|
||||||
"resource_set_name" : "Hello World Resource"
|
"resource_set_name" : "Alice Bank Account"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}' "http://localhost:8080/auth/realms/hello-world-authz/authz/entitlement/hello-world-authz-service"
|
}' "http://${host}:${port}/auth/realms/${realm_name}/authz/entitlement/{client_id}"
|
||||||
```
|
```
|
||||||
|
|
||||||
As a result, the server response is:
|
As a result, the server response is:
|
||||||
|
@ -60,45 +88,21 @@ As a result, the server response is:
|
||||||
Unlike the GET version, the server responds with an RPT holding the permissions granted during the evaluation of the permissions and authorization policies
|
Unlike the GET version, the server responds with an RPT holding the permissions granted during the evaluation of the permissions and authorization policies
|
||||||
associated with the resources being requested.
|
associated with the resources being requested.
|
||||||
|
|
||||||
When requesting entitlements, you can also specify the scopes you want to access. For example, using curl:
|
You can also specify the scopes you want to access. For example, using curl:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -X POST -H "Authorization: Bearer ${access_token}" -d '{
|
curl -X POST -H "Authorization: Bearer ${access_token}" -d '{
|
||||||
"permissions" : [
|
"permissions" : [
|
||||||
{
|
{
|
||||||
"resource_set_name" : "Hello World Resource",
|
"resource_set_name" : "Alice Bank Account",
|
||||||
"scopes" : [
|
"scopes" : [
|
||||||
"urn:my-app.com:scopes:view"
|
"withdraw"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}' "http://localhost:8080/auth/realms/hello-world-authz/authz/entitlement/hello-world-authz-service"
|
}' "http://${host}:${port}/auth/realms/${realm_name}/authz/entitlement/{client_id}"
|
||||||
```
|
```
|
||||||
|
|
||||||
===== Requesting Party Token
|
|
||||||
|
|
||||||
A requesting party token (RPT) is a https://tools.ietf.org/html/rfc7519[JSON web token (JWT)] digitally signed using https://www.rfc-editor.org/rfc/rfc7515.txt[JSON web signature (JWS)]. The token is built based on the access_token sent by the client during the authorization process.
|
|
||||||
|
|
||||||
When you decode an RPT, you see a payload similar to the following:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"authorization": {
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"resource_set_id": "d2fe9843-6462-4bfc-baba-b5787bb6e0e7",
|
|
||||||
"resource_set_name": "Hello World Resource"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"jti": "d6109a09-78fd-4998-bf89-95730dfd0892-1464906679405",
|
|
||||||
"exp": 1464906971,
|
|
||||||
"nbf": 0,
|
|
||||||
"iat": 1464906671,
|
|
||||||
"sub": "f1888f4d-5172-4359-be0c-af338505d86c",
|
|
||||||
"typ": "kc_ett",
|
|
||||||
"azp": "hello-world-authz-service"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
From this token you can obtain all permissions granted by the server from the *permissions* claim.
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
[[_service_entitlement_request_metadata]]
|
||||||
|
==== Entitlement Request Metadata
|
||||||
|
|
||||||
|
When requesting entitlements client applications are allowed to associate metadata information to the request and define how
|
||||||
|
they expect to obtain the permissions.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST -H "Authorization: Bearer ${access_token}" -d '{
|
||||||
|
"metadata" : {
|
||||||
|
"include_resource_name" : false
|
||||||
|
},
|
||||||
|
"permissions" : [
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}' "http://${host}:${port}/auth/realms/${realm_name}/authz/entitlement/{client_id}"
|
||||||
|
```
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
The Entitlement API endpoint only allows passing metadata along an entitlement request when using HTTP POST.
|
||||||
|
|
||||||
|
The following sections will explain how and when you can use the different information you can include in an entitlement request as a metadata.
|
||||||
|
|
||||||
|
==== Decide whether or not resource's name should be included the response
|
||||||
|
|
||||||
|
.include_resource_name
|
||||||
|
```bash
|
||||||
|
curl -X POST -H "Authorization: Bearer ${access_token}" -d '{
|
||||||
|
"metadata" : {
|
||||||
|
"include_resource_name" : false
|
||||||
|
},
|
||||||
|
"permissions" : [
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}' "http://${host}:${port}/auth/realms/${realm_name}/authz/entitlement/{client_id}"
|
||||||
|
```
|
||||||
|
Clients can use ```include_resource_name``` to decide whether or not resource`s name should be included on each permission granted by the server. This option
|
||||||
|
can be used to reduce the size of RPTs and optimize client-server communication.
|
||||||
|
|
||||||
|
By default, permissions in a RPT contain both the id and name of the resource that was granted by every single permission. This option is specially useful
|
||||||
|
when the resource server is capable of map their resources only based on the resource`s id.
|
||||||
|
|
||||||
|
==== Limiting the number of permissions within a RPT
|
||||||
|
|
||||||
|
.limit
|
||||||
|
```bash
|
||||||
|
curl -X POST -H "Authorization: Bearer ${access_token}" -d '{
|
||||||
|
"metadata" : {
|
||||||
|
"limit" : 10
|
||||||
|
},
|
||||||
|
"permissions" : [
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}' "http://${host}:${port}/auth/realms/${realm_name}/authz/entitlement/{client_id}"
|
||||||
|
```
|
||||||
|
Clients can use ```limit``` to specify how many permissions they expected within a RPT returned by the server. The limit option works as follows:
|
||||||
|
|
||||||
|
* If a request is sent *without* a previously issued RPT, only ```limit``` permissions will be returned based on the resources/scopes from the ```permissions``` claim.
|
||||||
|
* If a request is sent *with* a previously issued RPT, the permissions associated with the resources/scopes from the ```permissions``` claim take precedence where the permissions
|
||||||
|
from the previously issued RPT are only included if ```limit``` is not reached. In case there is enough room for permissions from a previously issued RPT, the server
|
||||||
|
will include the first permissions defined there.
|
||||||
|
|
||||||
|
This option allows clients to control the size of RPTs and keep only last permissions granted by the server. It usually makes sense only in cases your client
|
||||||
|
is capable of sending previously issued RPTs while asking for new permissions (a.k.a.: incremental authorization).
|
||||||
|
|
||||||
|
|
|
@ -17,3 +17,19 @@ In the full UMA protocol, resource servers can register permission requests in t
|
||||||
|
|
||||||
In most cases, you won't need to deal with this endpoint directly. {{book.project.name}} provides a <<fake/../../../enforcer/overview.adoc#_enforcer_overview, policy enforcer>> that enables UMA for your
|
In most cases, you won't need to deal with this endpoint directly. {{book.project.name}} provides a <<fake/../../../enforcer/overview.adoc#_enforcer_overview, policy enforcer>> that enables UMA for your
|
||||||
resource server so it can obtain a permission ticket from the authorization server, return this ticket to client application, and enforce authorization decisions based on a final requesting party token (RPT).
|
resource server so it can obtain a permission ticket from the authorization server, return this ticket to client application, and enforce authorization decisions based on a final requesting party token (RPT).
|
||||||
|
|
||||||
|
The process of obtaining permission tickets from {{book.project.name}} is performed by resource servers and not regular client applications,
|
||||||
|
where permission tickets are obtained when a client tries to access a protected resource without the necessary grants to access the resource. The issuance of
|
||||||
|
permission tickets is an important aspects when using UMA as it allows resource servers to:
|
||||||
|
|
||||||
|
* Abstract from clients the data associated with the resources protected by the resource server
|
||||||
|
* Register in the {{book.project.name}} authorization requests which in turn can be used later in workflows to grant access based on the resource's owner consent
|
||||||
|
* Decouple resource servers from authorization servers and allow them to protect and manage their resources using different authorization servers
|
||||||
|
|
||||||
|
Client wise, a permission ticket has also important aspects that its worthy to highlight:
|
||||||
|
|
||||||
|
* Clients don't need to know about how authorization data is associated with protected resources. A permission ticket is completely opaque to clients.
|
||||||
|
* Clients can have access to resources on different resource servers and protected by different authorization servers
|
||||||
|
|
||||||
|
These are just some of the benefits brought by UMA where other aspects of UMA are strongly based on permission tickets, specially regarding
|
||||||
|
privacy and user controlled access to their resources.
|
32
authorization_services/topics/service/rpt/overview.adoc
Normal file
32
authorization_services/topics/service/rpt/overview.adoc
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
[[_service_rpt_overview]]
|
||||||
|
==== Requesting Party Token
|
||||||
|
|
||||||
|
A requesting party token (RPT) is a https://tools.ietf.org/html/rfc7519[JSON web token (JWT)] digitally signed using https://www.rfc-editor.org/rfc/rfc7515.txt[JSON web signature (JWS)]. The token is built based on the OAuth2 access token previously issued by {{book.project.name}} to a specific client acting on behalf of an user
|
||||||
|
or on its own behalf.
|
||||||
|
|
||||||
|
When you decode an RPT, you see a payload similar to the following:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"authorization": {
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"resource_set_id": "d2fe9843-6462-4bfc-baba-b5787bb6e0e7",
|
||||||
|
"resource_set_name": "Hello World Resource"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"jti": "d6109a09-78fd-4998-bf89-95730dfd0892-1464906679405",
|
||||||
|
"exp": 1464906971,
|
||||||
|
"nbf": 0,
|
||||||
|
"iat": 1464906671,
|
||||||
|
"sub": "f1888f4d-5172-4359-be0c-af338505d86c",
|
||||||
|
"typ": "kc_ett",
|
||||||
|
"azp": "hello-world-authz-service"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
From this token you can obtain all permissions granted by the server from the *permissions* claim.
|
||||||
|
|
||||||
|
Also note that permissions are directly related with the resources/scopes you are protecting and complete decoupled from
|
||||||
|
the access control methods that were used to actually grant and issue these same permissions.
|
Loading…
Reference in a new issue