diff --git a/authorization_services/SUMMARY.adoc b/authorization_services/SUMMARY.adoc index 7ec0c69d77..5bccd18e8d 100755 --- a/authorization_services/SUMMARY.adoc +++ b/authorization_services/SUMMARY.adoc @@ -88,8 +88,10 @@ ... 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-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] diff --git a/authorization_services/topics/overview/terminology.adoc b/authorization_services/topics/overview/terminology.adoc index 3c4193b0e7..749dee456e 100755 --- a/authorization_services/topics/overview/terminology.adoc +++ b/authorization_services/topics/overview/terminology.adoc @@ -3,6 +3,7 @@ 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 Per OAuth2 terminology, a resource server is the server hosting the protected resources and capable of accepting and responding to protected resource requests. diff --git a/authorization_services/topics/policy/js-policy.adoc b/authorization_services/topics/policy/js-policy.adoc index e34481a333..0814819821 100644 --- a/authorization_services/topics/policy/js-policy.adoc +++ b/authorization_services/topics/policy/js-policy.adoc @@ -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): ```javascript -var identity = $evaluation.getIdentity(); +var context = $evaluation.getContext(); +var identity = context.getIdentity(); if (identity.hasRole('keycloak_user')) { $evaluation.grant(); diff --git a/authorization_services/topics/service/authorization/authorization-api-aapi.adoc b/authorization_services/topics/service/authorization/authorization-api-aapi.adoc index 65f2ca4006..0a75cb5fb1 100755 --- a/authorization_services/topics/service/authorization/authorization-api-aapi.adoc +++ b/authorization_services/topics/service/authorization/authorization-api-aapi.adoc @@ -1,18 +1,22 @@ [[_service_authorization_api_aapi]] ==== 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 <>. 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. +.UMA compliant Authorization API Endpoint ```bash http://${host}:${port}/auth/realms/${realm_name}/authz/authorize ``` When requesting an RPT, you need to provide two things: -* A <> with the resources you want to access -* The <> (as a bearer token) representing a user's identity and his consent to access authorization data on his behalf. +* A <> representing the resources you want to access +* The <> (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 curl -X POST @@ -25,34 +29,4 @@ As a result, the server response is: ```json {"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. - +``` \ No newline at end of file diff --git a/authorization_services/topics/service/entitlement/entitlement-api-aapi.adoc b/authorization_services/topics/service/entitlement/entitlement-api-aapi.adoc index 6a7cdbf495..34ce11fa4b 100755 --- a/authorization_services/topics/service/entitlement/entitlement-api-aapi.adoc +++ b/authorization_services/topics/service/entitlement/entitlement-api-aapi.adoc @@ -1,14 +1,37 @@ [[_service_entitlement_api_aapi]] ==== 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 <>. 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. +.Entitlement API Endpoint ```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 <> +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 <> with all permissions +granted by the server. + ===== Obtaining Entitlements 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 curl -X GET \ -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: ```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 -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 @@ -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 '{ "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: @@ -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 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 curl -X POST -H "Authorization: Bearer ${access_token}" -d '{ "permissions" : [ { - "resource_set_name" : "Hello World Resource", + "resource_set_name" : "Alice Bank Account", "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. \ No newline at end of file diff --git a/authorization_services/topics/service/entitlement/entitlement-request-metadata.adoc b/authorization_services/topics/service/entitlement/entitlement-request-metadata.adoc new file mode 100755 index 0000000000..ec9512d312 --- /dev/null +++ b/authorization_services/topics/service/entitlement/entitlement-request-metadata.adoc @@ -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). + + diff --git a/authorization_services/topics/service/protection/permission-api-papi.adoc b/authorization_services/topics/service/protection/permission-api-papi.adoc index 9a50c48d77..8d25bb70d5 100755 --- a/authorization_services/topics/service/protection/permission-api-papi.adoc +++ b/authorization_services/topics/service/protection/permission-api-papi.adoc @@ -16,4 +16,20 @@ _Permission ticket support is limited_. In the full UMA protocol, resource servers can register permission requests in the server to support authorization flows where a resource owner (the user that owns a resource being requested) can approve access to his resources by third parties, among other ways. This represents one of the main features of the UMA specification: resource owners can control their own resources and the policies that govern them. Currently {{book.project.name}} UMA implementation support is very limited in this regard. For example, the system does not store permission tickets on the server and we are essentially using UMA to provide API security and base our authorization offerings. In the future, full support of UMA and other use cases is planned. In most cases, you won't need to deal with this endpoint directly. {{book.project.name}} provides a <> 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). \ No newline at end of file +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. \ No newline at end of file diff --git a/authorization_services/topics/service/rpt/overview.adoc b/authorization_services/topics/service/rpt/overview.adoc new file mode 100644 index 0000000000..c69ad472b4 --- /dev/null +++ b/authorization_services/topics/service/rpt/overview.adoc @@ -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. \ No newline at end of file diff --git a/authorization_services/topics/service/protection/token-introspection.adoc b/authorization_services/topics/service/rpt/token-introspection.adoc similarity index 100% rename from authorization_services/topics/service/protection/token-introspection.adoc rename to authorization_services/topics/service/rpt/token-introspection.adoc