4

I am trying to secure a REST API using keycloak authorization mechanisms. My API is in NodeJS with express.
Say I have this API:

http://www.example.com/api/v1/houses

The endpoint supports GET/POST/PUT/DELETE. A house has a name and an owner:

{
  name: 'myhouse',
  owner: 'smith'
}

Everybody can view houses. You can also create houses, and automatically become the owner. Only the owner can delete a house. It's similar to the photoz example.

Using Keycloak Connect in bearer-only mode works with nodeJS express:

router.get('/houses*', keycloakProtect(), myHandler)

But this provides only Authentication, not Authorization. Basically it just checks that you provided the correct token. KeycloakProtect provides a rudimentary authorization mechanism, based only on role names. However, I would like to use the full power of client authorizations (with resources, scopes and policies)... Is there any NodeJS support for that? If no, how to use the Keycloak API for that?

cdupont
  • 1,138
  • 10
  • 17

2 Answers2

4

I found a beginning of answer using the API:

TOKEN=`curl -X POST  -H "Content-Type: application/x-www-form-urlencoded" -d 'username=username&password=password&grant_type=password&client_id=myclient&client_secret=myclientsecret' "http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token" | jq .access_token -r`

curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" -d '{
    "permissions" : [
        {
            "resource_set_name" : "Houses",
            "scopes" : [
                "view"
            ]
        }
    ]
}'  "http://localhost:8080/auth/realms/myrealm/authz/entitlement/myclient"

The second call will reply with 200 if authorized and 403 if not.

To define authorization policies in Keycloak, switch on "Authorizations" in your client. On the new "Authorization" tab:

  • Settings
    • Enable "remote resource management"
  • Resource Create one:
    • name: Houses
    • scopes: create, view, update, delete
    • uri: /houses/*
  • Scopes create 4 scopes: create, view, update, delete
  • Policies Create a role based policy with:
    • name: public_role_policy
    • description: user must have role "public" to be allowed
    • realm roles: public
  • Permissions Create one with:
    • name: "public role allows to view houses"
    • resource: Houses
    • scopes: view
    • policy: public_role_policy

You must also create a realm role "public" and give it to your users.

Next what you need to do is to create resources remotely. First get a client token:

TOKEN=`curl -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'grant_type=client_credentials&client_id=myclient&client_secret=myclientsecret'
"http://localhost:8080/auth/realms/${realm_name}/protocol/openid-connect/token" | jq .access_token -r`

Then create resources:

curl -X POST "http://localhost:8080/auth/realms/myrealm/authz/protection/resource_set" -H "Authorization: Bearer $TOKEN" -d '{
    "name": "My house",
    "uri": "/houses/123",
    "scopes": [
      {
        "id": "da776461-c1f5-4904-a559-1ca04d9f53a9",
        "name": "view"
      },
      {
        "id": "2615157c-f588-4e2b-ba1c-720fe8394215",
        "name": "manage"
      }
    ],
    "owner": "0892e431-5daf-413e-b4cf-eaee121ee447"
}'
cdupont
  • 1,138
  • 10
  • 17
  • Somehow i'm getting 404 when I query the `entitlement` api. Can you share with me your realm configurations? – mateeyow Oct 01 '18 at 03:54
  • @mateeyow In recent version of Keycloak entitlement endpoint has been removed. It has been merged with the token endpoint. The token endpoint can give you authorizations as well: https://www.keycloak.org/docs/latest/authorization_services/index.html#_policy_evaluation_overview – cdupont Oct 01 '18 at 08:05
1

I moved a bit further with the similar task. But I don't create resources. Maybe your approach is better. Don't know.

To check the owner of the house I am going to use a database check — just get a user login from a Keycloak token and check that a specified house is owned by the user in the application database.

v-ladynev/keycloak-nodejs-example

v.ladynev
  • 19,275
  • 8
  • 46
  • 67