How Trust & Security Works in Gawati

Introduction

This document focuses on how trust and security works in Gawati, what are the components we use, how they interact with each other, and what are the specific configuration choices we have made in Gawati. We cover aspects governing both authentication and authorization in Gawati.

In Gawati we use a third-party open source server called Key Cloak. KeyCloak uses JWT (JSON Web Tokens) to implement security. For a quick introduction to JWT see Understanding JSON Web Tokens .

Note

To install KeyCloak for Gawati use see the Authentication in Gawati .

Realms, Users, Applications

Users in KeyCloak are defined within authentication realms. Applications wanting to authenticate with a Realm, need to be registered and configured on the Realm, a registered Application in KeyCloak is called a Client. Applications can define specific roles which can be assigned to users on the Realm. In the image below we have added a realm called kiribati which will hold all the registered users.

Realm

Client applications wishing to connect need to register, by Add Client, see image below, where we add a test-client. The root url is the URL of the application authenticating with the KeyCloak instance.

Add Client

The test-client can be edited. For use in Gawati we need to change some defaults. Most importantly, we need to change the default Access Type from public to confidential. We do this because, the public method does not provide access to authentication tokens; confidential also requires passing a secret to KeyCloak when initiating any kind of request, and is more secure; finally, in confidential mode, tokens can be introspected on the server side (this is possible when Service Accounts Enabled is switched on).

Client

Enable Service Accounts, Authorization and Direct Access Grants. For application use you may also set Direct Access Grants to off, but some admin tools may not work with the client. Set the rest of the URL parameters as per your application. When Access Type is changed to confidential, a new credentials tab is added which has the secret which has to be passed by clients making requests to KeyCloak.

Credentials

We can create roles specific to the client, in the Roles tab. Roles for a client can also be given a realm wide scope if needed so other clients in the realm can use them.

Roles

The installation tab allows you to export the client configuration and use it within your application to integrate with KeyCloak. This configuration will be used in both client applications, and also in server applications (where it will be used in service accounts mode).

Realm

We export the configuration in Keycloak OIDC JSON format.

Login & Authentication

Login is initiated by the Application by initializing itself with the KeyCloak JSON file shown above, and then initating a call to Login. This redirects the browset to KeyCloak where login is securely done, and then the user is redirected back to the calling application. At this point an authentication access_token is available to the client application. The raw response decoded looks like this:

1
2
3
4
5
6
7
8
9
{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ5dVZmQUxKaF9TanFmdklhcnRtRnlSMFZ5OUlMNnNxRF9TREVaMEk5cFpzIn0.eyJqdGkiOiI1NjU2NmFiZS03ODFiLTQ0NjktYWU2MS0yYTBhMjhhYzYwMjYiLCJleHAiOjE1MjE5MTU0MzksIm5iZiI6MCwiaWF0IjoxNTIxOTE1Mzc5LCJpc3MiOiJodHRwOi8vYXV0aC5nYXdhdGkubG9jYWwvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiYWRtaW4tY2xpIiwic3ViIjoiYjk5YTFjMTAtMDI2Yi00NGJmLTk4ZDEtYzA2NGQyNjA2OGY4IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYWRtaW4tY2xpIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiNjk5ZTk1M2YtMTVlMy00ZGRjLWJkNWUtZjM4Y2E0MGYwY2U5IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6W10sInJlc291cmNlX2FjY2VzcyI6e30sInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIn0.YFNzt_hJaS6eHQe39Qi0Wgqm7kzo2ZUTIuS8XzCL6ohvOnxAMFm-55PTZejjZN6jwrlrdqnc8uxfmvD7Lxy1xuIzyADEFcwXaAXXw4Xc5TMcx-ZWoS7Y8CFjn5QQxIDNbYnBcMiO-DJkrKRjeRTfK27n7ialiMD3-t26fOQiAe0nPY6lLIwfSl31LKSpT23DQsnouFbXYj9FrfUTacQZiku6mTXuEkxDlSwDiQlA_Sk4w2jo2qGtw7wD_qKOun9Jpbrrucm5VRGGluuKzOGnUWV8d2njBOA_-JFxhZOZpRfqzqHj-FqZvTM1FqU57jqwNQAw3FhEYInXxealGh92vg",
    "expires_in": 60,
    "refresh_expires_in": 1800,
    "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ5dVZmQUxKaF9TanFmdklhcnRtRnlSMFZ5OUlMNnNxRF9TREVaMEk5cFpzIn0.eyJqdGkiOiJhYTRhZjU0Mi1iZjI2LTQ5MWEtYjcxNi1hZjA5YzYzN2U4ZGMiLCJleHAiOjE1MjE5MTcxNzksIm5iZiI6MCwiaWF0IjoxNTIxOTE1Mzc5LCJpc3MiOiJodHRwOi8vYXV0aC5nYXdhdGkubG9jYWwvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiYWRtaW4tY2xpIiwic3ViIjoiYjk5YTFjMTAtMDI2Yi00NGJmLTk4ZDEtYzA2NGQyNjA2OGY4IiwidHlwIjoiUmVmcmVzaCIsImF6cCI6ImFkbWluLWNsaSIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjY5OWU5NTNmLTE1ZTMtNGRkYy1iZDVlLWYzOGNhNDBmMGNlOSIsInJlc291cmNlX2FjY2VzcyI6e319.l89VECnHrpQ70SnZ711dQ92mVpNhqpX_KGOWcRQxykODv9cVbfckMAbQ3JIsvkq7GazuJuUh3VL-f2ib7dwPoFsIBNGcQXwdG8Wn-EjIvKDAAZZ0xjIBGJjRr5P24u_U3JPTWM1rWT3XAyQGDk4PLPJlI5RUVJRPN8Gly9fOKbPbD3dwAB6grKBdy9jW3mbAtF6bCEzlzByuK3n17kj5jGzlxsZt21DebPHeVZey3_8r1Mo4Gy2Zutt_Oq7M75cOEtMDBBmsBBrEELBJ0K5tz47L8IspQ_e92bh-ZSkxRJzdj2Sy1CLnhB5CI3z2ifpl0rjLp6RFucjc8HJCAEI-FA",
    "token_type": "bearer",
    "not-before-policy": 0,
    "session_state": "699e953f-15e3-4ddc-bd5e-f38ca40f0ce9"
}

The access_token has only a short life-span, and needs to be periodically updated by the Application, by making a refresh token API call to KeyCloak, to indicate that the user is still active. The access_token contains all the information associated with the Application, that we had configured on the KeyCloak client earlier. The client can make authenticated and unauthenticated API calls to a server side API, but for authenticated Server Side apis, the access_token is passed, and validated at the server end. Validation happens at the server end, by passing the token back to the KeyCloak server, to an introspecting API, which returns a status of active = false if the token is invalidated, or if it is valid returns the full decoded content of the token:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{
    "jti": "0a9c614a-1120-438b-8aa3-db69792df89a",
    "exp": 1522085986,
    "nbf": 0,
    "iat": 1522085686,
    "iss": "http://auth.gawati.local/auth/realms/kiribati",
    "aud": "test-client",
    "sub": "fa3dceab-dd19-4bd2-9f2a-e4aeb9557bfe",
    "typ": "Bearer",
    "azp": "test-client",
    "nonce": "d0de0910-4184-4497-8510-73294ff03cbb",
    "auth_time": 1522085418,
    "session_state": "a448a83c-79c1-49eb-bc86-d6b672a6973f",
    "name": "test kumar",
    "given_name": "test",
    "family_name": "kumar",
    "preferred_username": "test",
    "email": "test@blah.in",
    "acr": "0",
    "allowed-origins": [
        "http://localhost:3000"
    ],
    "realm_access": {
        "roles": [
            "uma_authorization"
        ]
    },
    "resource_access": {
        "test-client": {
            "roles": [
                "test-client.Admin"
            ]
        },
        "gawati-client": {
            "roles": [
                "client.Editor",
                "client.Admin"
            ]
        },
        "account": {
            "roles": [
                "manage-account",
                "manage-account-links",
                "view-profile"
            ]
        }
    },
    "client_id": "test-client",
    "username": "test",
    "active": true
}

The decoded information(for e.g. the roles) can be used by the server API to apply it to business logic - for instance, filter queried data based on the role of the user, and send it back to the client in the API response. Effectively there is an overhead of querying KeyCloak to instrospect the token for every request made to the the server.

Note

There is an alternative approach which avoids the overhead of the request, by making use of signed JWT, where the signature passed by the client is validated by the server API using standard JWT libraries, without querying KeyCloak. We have not implemented this in Gawati yet.