diff --git a/SUMMARY.adoc b/SUMMARY.adoc index bec52f8634..50e174ff17 100755 --- a/SUMMARY.adoc +++ b/SUMMARY.adoc @@ -5,6 +5,7 @@ .. link:topics/overview/terminology.adoc[Terminology] . link:topics/getting-started/getting-started.adoc[Getting Started] .. link:topics/getting-started/hello-world.adoc[Hello Authorization World] + .. link:topics/getting-started/hello-world-servlet-authz.adoc[Securing a Servlet Application] . link:topics/resource-server/overview.adoc[Managing Resource Servers] .. link:topics/resource-server/view.adoc[Viewing Resource Servers] .. link:topics/resource-server/create.adoc[Creating Resource Servers] diff --git a/images/pep-pattern-diagram.png b/images/pep-pattern-diagram.png new file mode 100644 index 0000000000..3e019cce88 Binary files /dev/null and b/images/pep-pattern-diagram.png differ diff --git a/images/servlet-authz-app-structure.png b/images/servlet-authz-app-structure.png new file mode 100644 index 0000000000..c6b1418bb3 Binary files /dev/null and b/images/servlet-authz-app-structure.png differ diff --git a/topics/enforcer/jaxrs-enforcer.adoc b/topics/enforcer/jaxrs-enforcer.adoc deleted file mode 100755 index 503f2ba8f9..0000000000 --- a/topics/enforcer/jaxrs-enforcer.adoc +++ /dev/null @@ -1 +0,0 @@ -== JAX-RS Policy Enforcer \ No newline at end of file diff --git a/topics/enforcer/overview.adoc b/topics/enforcer/overview.adoc index 68f4036058..3320f6f29e 100755 --- a/topics/enforcer/overview.adoc +++ b/topics/enforcer/overview.adoc @@ -1 +1,7 @@ -== Policy Enforcers \ No newline at end of file +== Policy Enforcers + +PEP is a design pattern and as such you can implement it in different ways. {{book.project.name}} provides all the necessary means +to implement PEPs for different platforms, environments and using different programming languages. After all, {{book.project.name}} {{book.project.module}} is +fully RESTFUL-based, leveraging OAuth2 authorization capabilities to also support fine-grained authorization using a centralized authorization server. + +image:../../images/pep-pattern-diagram.png[alt="PEP Overview"] \ No newline at end of file diff --git a/topics/getting-started/getting-started.adoc b/topics/getting-started/getting-started.adoc index 412b84ede0..cb0166c098 100755 --- a/topics/getting-started/getting-started.adoc +++ b/topics/getting-started/getting-started.adoc @@ -6,7 +6,9 @@ you to understand the basic steps to enable fine-grained authorization to an app [NOTE] This guide assume that you are able to install and boot a {{book.project.name}} Server. For more information, please follow the intrusctions https://keycloak.gitbooks.io/getting-started-tutorials/content/[here]. -Make sure you have a {{book.project.name}} instance up and running on http://localhost:8080/auth[http://localhost:8080/auth]. If everything is OK, you would be able to login to the +All the guides are based on the *{{book.project.name}} Demo Distribution*. Please download it before going further with any guide. + +Make sure you have a {{book.project.name}} instance up and running on http://localhost:8080/auth[http://localhost:8080/auth]. If everything is OK, you should be able to login to the _Administration Console_ and get a page like that: image:../../images/gs-keycloak-console-page.png[alt="Keycloak Administration Console"] \ No newline at end of file diff --git a/topics/getting-started/hello-world-create-realm.adoc b/topics/getting-started/hello-world-create-realm.adoc deleted file mode 100755 index 0962c385a7..0000000000 --- a/topics/getting-started/hello-world-create-realm.adoc +++ /dev/null @@ -1,202 +0,0 @@ -=== Creating the Hello World AuthZ Realm - -For this guide, we are going to create a *hello-world-authz* realm. Just import the following JSON file to create the new realm: - -```json -{ - "realm" : "hello-world-authz", - "enabled" : true, - "privateKey" : "MIIEpQIBAAKCAQEAzMhNM9HXNQWhVf1m64zS67SIyQjj+tV5GR+MqlRTWDXdo8GAWHd+alY1urRhfRoqMy4F499+8wh2REKFykNt0ng6s6wWnEaKDboS3SAUV6lybcOAkwIOCtCZj1ItddKG3m64fzxDDQrcpkbiAvw3S8KJ4UJK+pyh9iX01duSDtM/HhPawsPdY8JSMfuo1IxQ2Vxw+8RKwbbdUeew6cyYGYAeFYwA66mlM3otB0RBHh4bjwg8297+2g53TdwM2rbCHRbrorMQD3031OTyFSp7lXCtoMLWRfAFnOP/2yZWZMXbiJheC0R3sLbU7Ef0/cUbYyk4Ckfq6pcYDR+VZBF7AwIDAQABAoIBAAwa4wVnKBOIS6srmYPfBTDNsTBBCEjxiYEErmn7JhoWxQ1DCPUxyxU6F177/q9Idqoj1FFOCtEO9P6/9+ym470HQmEQkR2Xxd1d3HOZy9oKuCro3ZbTDkVxY0JnlyxZz4MihGFxDH2e4MArfHy0sAgYbdIU+x2pWKGWSMzDd/TMSOExhc/sIQAg6ljbPCLLXCPQFAncoHRyGPrkRZs6UTZi5SJuCglVa2/3G+0drDdPuA83/mwsZfIBqQgbGbFgtq5T5C6CKMkPOQ42Rcclm7kEr6riTkJRo23EO1iOJVpxzI0tbxZsJAsW7zeqv0wWRyUgVfQAje6OdsNexp5aCtECgYEA6nMHCQ9xXvufCyzpIbYGxdAGqH6m1AR5gXerHqRiGNx+8UUt/E9cy/HTOhmZDK/eC4BT9tImeF01l1oSU/+wGKfux0SeAQchBhhq8GD6jmrtgczKAfZHp0Zrht7o9qu9KE7ZNWRmY1foJN9yNYmzY6qqHEy+zNo9amcqT7UZKO8CgYEA35sp9fMpMqkJE+NEJ9Ph/t2081BEkC0DYIuETZRSi+Ek5AliWTyEkg+oisTbWzi6fMQHS7W+M1SQP6djksLQNPP+353DKgup5gtKS+K/y2xNd7fSsNmkjW1bdJJpID7WzwwmwdahHxpcnFFuEXi5FkG3Vqmtd3cD0TYL33JlRy0CgYEA0+a3eybsDy9Zpp4m8IM3R98nxW8DlimdMLlafs2QpGvWiHdAgwWwF90wTxkHzgG+raKFQVbb0npcj7mnSyiUnxRZqt2H+eHZpUq4jR76F3LpzCGui2tvg+8QDMy4vwqmYyIxDCL8r9mqRnl3HpChBPoh2oY7BahTTjKEeZpzbR0CgYEAoNnVjX+mGzNNvGi4Fo5s/BIwoPcU20IGM+Uo/0W7O7Rx/Thi7x6BnzB0ZZ7GzRA51paNSQEsGXCzc5bOIjzR2cXLisDKK+zIAxwMDhrHLWZzM7OgdGeb38DTEUBhLzkE/VwYZUgoD1+/TxOkwhy9yCzt3gGhL1cF//GJCOwZvuECgYEAgsO4rdYScgCpsyePnHsFk+YtqtdORnmttF3JFcL3w2QneXuRwg2uW2Kfz8CVphrR9eOU0tiw38w6QTHIVeyRY8qqlHtiXj6dEYz7frh/k4hI29HwFx43rRpnAnN8kBEJYBYdbjaQ35Wsqkfu1tvHJ+6fxSwvQu/TVdGp0OfilAY=", - "publicKey" : "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzMhNM9HXNQWhVf1m64zS67SIyQjj+tV5GR+MqlRTWDXdo8GAWHd+alY1urRhfRoqMy4F499+8wh2REKFykNt0ng6s6wWnEaKDboS3SAUV6lybcOAkwIOCtCZj1ItddKG3m64fzxDDQrcpkbiAvw3S8KJ4UJK+pyh9iX01duSDtM/HhPawsPdY8JSMfuo1IxQ2Vxw+8RKwbbdUeew6cyYGYAeFYwA66mlM3otB0RBHh4bjwg8297+2g53TdwM2rbCHRbrorMQD3031OTyFSp7lXCtoMLWRfAFnOP/2yZWZMXbiJheC0R3sLbU7Ef0/cUbYyk4Ckfq6pcYDR+VZBF7AwIDAQAB", - "certificate" : "MIICsTCCAZkCBgFVETX4AzANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFIZWxsbyBXb3JsZCBBdXRoWjAeFw0xNjA2MDIxMzAxMzdaFw0yNjA2MDIxMzAzMTdaMBwxGjAYBgNVBAMMEUhlbGxvIFdvcmxkIEF1dGhaMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzMhNM9HXNQWhVf1m64zS67SIyQjj+tV5GR+MqlRTWDXdo8GAWHd+alY1urRhfRoqMy4F499+8wh2REKFykNt0ng6s6wWnEaKDboS3SAUV6lybcOAkwIOCtCZj1ItddKG3m64fzxDDQrcpkbiAvw3S8KJ4UJK+pyh9iX01duSDtM/HhPawsPdY8JSMfuo1IxQ2Vxw+8RKwbbdUeew6cyYGYAeFYwA66mlM3otB0RBHh4bjwg8297+2g53TdwM2rbCHRbrorMQD3031OTyFSp7lXCtoMLWRfAFnOP/2yZWZMXbiJheC0R3sLbU7Ef0/cUbYyk4Ckfq6pcYDR+VZBF7AwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQANm5gIT/c50lwjawM686gNXpppLA928WsCOn9NIIWjSKekP8Bf9S73kf7vWcsEppm5B8rRyRxolXmzwghv74L7uVDg8Injjgj+XbPVQP+cJqWpSaMZHF7UfWe0/4M945Xcbmsl5q+m9PmrPG0AaaZhqXHcp4ehB1H+awyRqiERpJUuwZNycw2+2kjDADpsFf8hZVUd1F6ReYyOkqUyUjbL+jYTC7ZBNa7Ok+w6HCXWgkgVATAgQXJRM3w14IOc5MH/vfMCrCl/eNQLbjGl9y7u8PKwh3MXHDO2OLqtg6hOTSrOGUPJZGmGtUAl+2/R7FzoWkML/BNe2hjsL6UJwg91", - "requiredCredentials" : [ "password" ], - "roles" : { - "realm" : [ - { - "name" : "uma_protection" - } - ] - }, - "users" : - [ - { - "username" : "alice", - "enabled" : true, - "credentials" : [ { - "type" : "password", - "value" : "password" - } ], - "clientRoles" : { - "hello-world-authz-service" : [ "uma_authorization" ] - } - }, - { - "username" : "jdoe", - "enabled" : true, - "credentials" : [ { - "type" : "password", - "value" : "password" - } ], - "clientRoles" : { - "hello-world-authz-service" : [ "uma_authorization" ] - } - }, - { - "username" : "service-account-hello-world-authz-service", - "enabled" : true, - "serviceAccountClientId" : "hello-world-authz-service", - "realmRoles" : [ "uma_protection"] - } - ], - "clients" : [ - { - "clientId" : "hello-world-authz-service", - "secret" : "password", - "serviceAccountsEnabled" : true, - "enabled" : true, - "redirectUris" : [ "http://localhost:8080/hello-world-authz-service" ], - "directAccessGrantsEnabled" : true, - "publicClient" : false - } - ] -} -``` -The realm *hello-world-authz* consists of: - -** Two users: _alice_ and _jdoe_ -** One client application: _hello-world-authz-service_ -** One global role: _uma_protection_ -** One client role: _uma_authorization_ - -The _hello-world-authz-service_ is the application with the resources we want to protect. In other words, it will act as a link:../overview/terminology.html[Resource Server]. - -In {{book.project.name}} a resource server is just a regular client application with some specific characteristics. It _must_ be a *confidential* client application as defined by: - -```json -"publicClient" : false -``` - -It must have a *client_id*, *client_secret* and *Service Account* enabled: - -```json -"clients" : [ - { - "clientId" : "hello-world-authz-service", - "secret" : "7801be7c-437a-44ae-be34-67da32f024eb", - "serviceAccountsEnabled" : true, - ... - } -] -``` - -And finally, an user mapping to the client's service account: - -```json -{ - "username" : "service-account-my-resource-server", - "enabled" : true, - "serviceAccountClientId" : "hello-world-authz-service", - "realmRoles" : [ "uma_protection"] -} -``` - -In the latter case, we are also granting the *uma_protection* role to the client's service account. As you'll see, that will be necessary in order to get access to the link:../service/protection-api.html[Protection API]. - -=== Creating a Resource Server and Protecting Resources - -Now that we have the *hello-world-authz* realm properly configured, we need to enable the *hello-world-authz-service* as a resource server. For that, click on the *Authorization* in the left menu bar. - -image:../../images/gs-keycloak-authz-page.png[alt="Keycloak Authorization Page"] - -To create a resource server you can click on the *Create* button. - -image:../../images/gs-keycloak-authz-create-rs-page.png[alt="Create Resource Server"] - -From that page you can create a resource server by manually filling that form or you can just import a JSON file with the configuration you want. For this guide, we'll just import a JSON file as follows: - -```json -{ - "clientId": "hello-world-authz-service", - "resources": [ - { - "name": "Hello World Resource" - } - ], - "policies": [ - { - "name": "Only Special Users Policy", - "type": "user", - "logic": "POSITIVE", - "config": { - "users": "[\"alice\"]" - } - }, - { - "name": "Hello World Resource Permission", - "type": "resource", - "config": { - "resources": "[\"Hello World Resource\"]", - "applyPolicies": "[\"Only Special Users Policy\"]" - } - } - ] -} - -``` - -After importing the JSON file above, you would see a page like that: - -image:../../images/gs-authz-hello-rs-created-page.png[alt="Resource Server Successfully Created"] - -You may take some time now exploring the resource server we just created. But first, let's understand what we just created. - -The resource server was created based on the *hello-world-authz-service* client application, as you can see from the following configuration: - -```json -{ - "clientId": "hello-world-authz-service", - ... -} -``` - -What we did was basically tell {{book.project.name}} that we want that client application acting as a resource server, so we can start creating the resources we want to protect as well the permissions - and authorization policies we want to use to actually protect the resources. - -The purpose of this guide is keep things simple to get you started, so our newly created resource server has a single protected resource, as defined by the following configuration: - -```json -{ - ... - "resources": [ - { - "name": "Hello World Resource" - } - ], - ... -} -``` - -The *Hello World Resource* represents a set of one or more resources we want to protect. It can map to a single or to multiple resources in an application. - -In order to protect it, we need to create the authorization policies and permissions we want to apply. Policies define the conditions that must be satisfied to grant a permission. Where a -permission is the link between a resource and the policies(or conditions) we want to enforce when someone wants to access a resource. - -In this example, we have a single policy *Only Special Users Policy*. This policy tells that only the specified users are allowed to access _something_ (we don't know what, yet. That is up to the permission). - -[NOTE] -{{book.project.name}} provides a few link:../policy/overview.html[policy types] that you can start using out-of-the-box. There are policies for RBAC, time constraints or even rules written using JavaScript or JBoss Drools. - -The last step when protecting a resource is to define a permission. For that, we have defined a *Hello World Resource Permission* that links the resource we want to protect, _Hello World Resource_, with the -policy we want to apply to that resource, _Only Special Users Policy_. - -```json -{ - "name": "Hello World Resource Permission", - "type": "resource", - "config": { - "resources": "[\"Hello World Resource\"]", - "applyPolicies": "[\"Only Special Users Policy\"]" - } -} - -``` \ No newline at end of file diff --git a/topics/getting-started/hello-world-entitlement.adoc b/topics/getting-started/hello-world-entitlement.adoc deleted file mode 100755 index 52a3ed08af..0000000000 --- a/topics/getting-started/hello-world-entitlement.adoc +++ /dev/null @@ -1 +0,0 @@ -== Obtaining Permissions using the Entitlement API \ No newline at end of file diff --git a/topics/getting-started/hello-world-servlet-authz.adoc b/topics/getting-started/hello-world-servlet-authz.adoc new file mode 100755 index 0000000000..9f878dc636 --- /dev/null +++ b/topics/getting-started/hello-world-servlet-authz.adoc @@ -0,0 +1,456 @@ +== Securing a Servlet Application + +This guide will show you how to: + +* Create a realm with the necessary configuration to enable fine-grained authorization to a servlet application +* Create a resource server and the resources that must be protected +* Create permissions, authorization policies and how to apply them to your protected resources +* Configure the {{book.project.name}} Authorization Enforcer Filter to your servlet application + +The application we are using in this guide is one of the examples provided by the {{book.project.name}} Demo Distribution. You can find all the source code +under *examples/authz/servlet-authz/*. + +[NOTE] +Before going further, make sure you followed all the instructions in the link:../getting-started/getting-started.html[Getting Started] guide. + +=== About the Servlet Application + +The application we are about to create is a very simple. In a nutshell, it implements the following security requirements: + +* An _Administration Area_ that only administrators can access +* An _User Premium Area_ that only users with a premium plan can access +* A dynamic menu that is generated accordingly with the permissions issued by a {{book.project.name}} Server to an authenticated user + +image:../../images/servlet-authz-app-structure.png[alt="Servlet Authz Application Structure"] + +=== Creating the Servlet Authz Realm + +For this guide, we are going to create a *servlet-authz* realm. Just import the following JSON file to create the new realm: + +```json +{ + "realm": "servlet-authz", + "enabled": true, + "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", + "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", + "requiredCredentials": [ + "password" + ], + "users": [ + { + "username": "alice", + "enabled": true, + "credentials": [ + { + "type": "password", + "value": "alice" + } + ], + "realmRoles": [ + "user" + ], + "clientRoles": { + "servlet-authz-app": [ + "uma_authorization", + "kc_entitlement" + ] + } + }, + { + "username": "jdoe", + "enabled": true, + "credentials": [ + { + "type": "password", + "value": "jdoe" + } + ], + "realmRoles": [ + "user", + "user_premium" + ], + "clientRoles": { + "servlet-authz-app": [ + "uma_authorization", + "kc_entitlement" + ] + } + }, + { + "username": "admin", + "enabled": true, + "credentials": [ + { + "type": "password", + "value": "admin" + } + ], + "realmRoles": [ + "user", + "admin" + ], + "clientRoles": { + "realm-management": [ + "realm-admin" + ], + "servlet-authz-app": [ + "uma_authorization", + "kc_entitlement" + ] + } + }, + { + "username": "service-account-servlet-authz-app", + "enabled": true, + "serviceAccountClientId": "servlet-authz-app", + "realmRoles": [ + "uma_protection" + ] + } + ], + "roles": { + "realm": [ + { + "name": "user", + "description": "User privileges" + }, + { + "name": "admin", + "description": "Administrator privileges" + }, + { + "name": "user_premium", + "description": "User Premium privileges" + }, + { + "name": "uma_protection", + "description": "Allows access to the Protection API" + } + ] + }, + "clients": [ + { + "clientId": "servlet-authz-app", + "enabled": true, + "publicClient": false, + "baseUrl": "/servlet-authz-app", + "adminUrl": "/servlet-authz-app", + "bearerOnly": false, + "serviceAccountsEnabled": true, + "redirectUris": [ + "/servlet-authz-app/*" + ], + "secret": "secret" + } + ] +} +``` +=== Creating a Resource Server and Protecting Resources + +Now that we have the *servlet-authz* realm properly configured, we need to enable the *servlet-authz-app* as a resource server. For that, click on the *Authorization* in the left menu bar. + +image:../../images/gs-keycloak-authz-page.png[alt="Keycloak Authorization Page"] + +To create a resource server you can click on the *Create* button. + +image:../../images/gs-keycloak-authz-create-rs-page.png[alt="Create Resource Server"] + +From that page you can create a resource server by manually filling that form or you can just import a JSON file with the configuration you want. For this guide, we'll just import a JSON file as follows: + +```json +{ + "clientId": "servlet-authz-app", + "allowRemoteResourceManagement": true, + "allowEntitlements": true, + "policyEnforcementMode": "ENFORCING", + "resources": [ + { + "name": "Admin Resource", + "uri": "/protected/admin/*", + "type": "http://servlet-authz/protected/admin", + "scopes": [ + { + "name": "urn:servlet-authz:protected:admin:access" + } + ] + }, + { + "name": "Protected Resource", + "uri": "/*", + "type": "http://servlet-authz/protected/resource", + "scopes": [ + { + "name": "urn:servlet-authz:protected:resource:access" + } + ] + }, + { + "name": "Premium Resource", + "uri": "/protected/premium/*", + "type": "urn:servlet-authz:protected:resource", + "scopes": [ + { + "name": "urn:servlet-authz:protected:premium:access" + } + ] + }, + { + "name": "Main Page", + "type": "urn:servlet-authz:protected:resource", + "scopes": [ + { + "name": "urn:servlet-authz:page:main:actionForAdmin" + }, + { + "name": "urn:servlet-authz:page:main:actionForUser" + }, + { + "name": "urn:servlet-authz:page:main:actionForPremiumUser" + } + ] + } + ], + "policies": [ + { + "name": "Any Admin Policy", + "description": "Defines that adminsitrators can do something", + "type": "role", + "config": { + "roles": "[\"admin\"]" + } + }, + { + "name": "Any User Policy", + "description": "Defines that any user can do something", + "type": "role", + "config": { + "roles": "[\"user\"]" + } + }, + { + "name": "Only Premium User Policy", + "description": "Defines that only premium users can do something", + "type": "role", + "logic": "POSITIVE", + "config": { + "roles": "[\"user_premium\"]" + } + }, + { + "name": "All Users Policy", + "description": "Defines that all users can do something", + "type": "aggregate", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "applyPolicies": "[\"Any User Policy\",\"Any Admin Policy\",\"Only Premium User Policy\"]" + } + }, + { + "name": "Premium Resource Permission", + "description": "A policy that defines access to premium resources", + "type": "resource", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"Premium Resource\"]", + "applyPolicies": "[\"Only Premium User Policy\"]" + } + }, + { + "name": "Administrative Resource Permission", + "description": "A policy that defines access to administrative resources", + "type": "resource", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"Admin Resource\"]", + "applyPolicies": "[\"Any Admin Policy\"]" + } + }, + { + "name": "Protected Resource Permission", + "description": "A policy that defines access to any protected resource", + "type": "resource", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "resources": "[\"Protected Resource\"]", + "applyPolicies": "[\"All Users Policy\"]" + } + }, + { + "name": "Action 1 on Main Page Resource Permission", + "description": "A policy that defines access to action 1 on the main page", + "type": "scope", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "scopes": "[\"urn:servlet-authz:page:main:actionForAdmin\"]", + "applyPolicies": "[\"Any Admin Policy\"]" + } + }, + { + "name": "Action 2 on Main Page Resource Permission", + "description": "A policy that defines access to action 2 on the main page", + "type": "scope", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "scopes": "[\"urn:servlet-authz:page:main:actionForUser\"]", + "applyPolicies": "[\"Any User Policy\"]" + } + }, + { + "name": "Action 3 on Main Page Resource Permission", + "description": "A policy that defines access to action 3 on the main page", + "type": "scope", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "scopes": "[\"urn:servlet-authz:page:main:actionForPremiumUser\"]", + "applyPolicies": "[\"Only Premium User Policy\"]" + } + } + ] +} +``` + +[NOTE] +All this configuration can also be done using the {{book.project.name}} Administration Console. We are using the import tool just for demonstration purposes + +=== A Quick Overview of the Permissions and Policies + +The resource server configuration tells a lot about what we are really protecting. It is basically describing the security requirements we have discussed earlier. + +Fist of all, we define four resources: + +* Admin Resource +* Protected Resource +* Premium Resource +* Main Page + +As the name implies, each of these resources are related with the requirements we previously discussed, representing the different areas or group of resources we want to protect. + +As you may notice, each of these resources (except Main Page) defines an *uri* property. This property represents the path we want to protect and they map directly, or indirectly by using a pattern, +to the resources served by the application. + +Let's take the _Protected Resource_ as an example: + +```json +{ + "name": "Protected Resource", + "uri": "/*", + "type": "http://servlet-authz/protected/resource", + "scopes": [ + { + "name": "urn:servlet-authz:protected:resource:access" + } + ] +}, +``` +This resource represents all resources in the application, as you can see from the pattern used in the *uri* property. It also defines a single scope/action to indicate that users, if granted, can access this resource. + +Now, let's see what are the permissions and authorization policies configured to this resource: + +```json +... +{ + "name": "Protected Resource Permission", + "description": "A policy that defines access to any protected resource", + "type": "resource", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "resources": "[\"Protected Resource\"]", + "applyPolicies": "[\"All Users Policy\"]" + } + }, +... +``` + +The definition above is a permission that links the _Protected Resource_ with the policies we want to apply. In this case, we are applying a single _All Users Policy_. + +Policies define the conditions to be meet in order to access something. In this case, the _All Users Policy_ is composed of two other policies, a special policy type called link:../policy/aggregated-policy.html[Aggregated Policies]. + +```json +... +{ + "name": "All Users Policy", + "description": "Defines that all users can do something", + "type": "aggregate", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "applyPolicies": "[\"Any User Policy\",\"Any Admin Policy\",\"Only Premium User Policy\"]" + } +}, +... +``` + +{{book.project.name}} provides a few built-in policy types (and their respective policy providers) implementing different access control mechanisms (RBAC, GBAC, Rule-based, Time-based, etc) that you can use to build your own policies and permissions. + +Aggregated policies are very useful in order to group related policies together and make policy management less painful. + +=== Configuring the Keycloak Enforcement Filter + +Now that we have all the configuration for our resource server in place, we can configure the authorization enforcement filter to actually protected the resources. + +Just like any other Servlet Filter, you just need to include the following configuration in your web application descriptor (WEB-INF/web.xml): + +```xml + + Keycloak Authorization Enforcer + org.keycloak.authorization.policy.enforcer.servlet.KeycloakAdapterEnforcementFilter + + + + Keycloak Authorization Enforcer + /* + +``` +The *org.keycloak.authorization.policy.enforcer.servlet.KeycloakAdapterEnforcementFilter* is shipped with the {{book.project.name}} OIDC Adapters distribution. In order to make it available to +your application at runtime, you must create a *META-INF/jboss-deployment-structure.xml* at the application root directory. If you are using maven, this file can be placed under *src/main/webapp/META-INF/jboss-deployment-structure.xml*: + +```xml + + + + + + + + + + + +``` + +For last, you need to create a *META-INF/keycloak-authz.json*. If you are using Maven, this file goes inside *src/main/resources*: + +```json +{ + "client": { + "configurationUrl": "http://localhost:8080/auth/realms/servlet-authz/authz/uma_configuration", + "clientId": "servlet-authz-app", + "clientSecret": "secret" + }, + "enforcer": {} +} +``` + +=== Running and Using the Application + +All the source code for this application is at *${KEYCLOAK_DEMO_SERVER_DIR}/examples/authz/servlet-authz/*. + +There you can execute the following command to _deploy_ the application to the running server: + +```bash +mvn clean package wildfly:deploy +``` +That should be enough to get the application properly packaged and deployed to a _running_ {{book.project.name}} server. + +If the application was properly deployed, you can try to access it at http://localhost:8080/auth[http://localhost:8080/servlet-authz-app] and use the following credentials to login into the application: + +If everything is correct, you will be redirect to Keycloak login page. You can login to the application with the following credentials: + +* username: alice / password: alice (regular user) +* username: jdoe / password: jdoe (premium user) +* username: admin / password: admin (administrator) + +To _undeploy_ the application, please execute the following command: + +```bash +mvn wildfly:undeploy +``` \ No newline at end of file diff --git a/topics/getting-started/hello-world.adoc b/topics/getting-started/hello-world.adoc index cb175f4732..6075057c7f 100755 --- a/topics/getting-started/hello-world.adoc +++ b/topics/getting-started/hello-world.adoc @@ -10,6 +10,9 @@ This guide will show you how to: The purpose of this guide is to give you a generic overview of {{book.project.name}} {{book.project.module}} so you can understand some core concepts and start protecting your applications and services despite the platform they are running on. +[NOTE] +Before going further, make sure you followed all the instructions in the link:../getting-started/getting-started.html[Getting Started] guide. + === Creating the Hello World AuthZ Realm For this guide, we are going to create a *hello-world-authz* realm. Just import the following JSON file to create the new realm: @@ -94,7 +97,7 @@ It must have a *client_id*, *client_secret* and *Service Account* enabled: "clients" : [ { "clientId" : "hello-world-authz-service", - "secret" : "7801be7c-437a-44ae-be34-67da32f024eb", + "secret" : "password", "serviceAccountsEnabled" : true, ... } @@ -156,6 +159,9 @@ From that page you can create a resource server by manually filling that form or ``` +[NOTE] +All this configuration can also be done using the {{book.project.name}} Administration Console. We are using the import tool just for demonstration purposes + After importing the JSON file above, you would see a page like that: image:../../images/gs-authz-hello-rs-created-page.png[alt="Resource Server Successfully Created"]