Skip to content

Commit a7603f3

Browse files
committed
feat: ensure required hawk-client user-claims are present
1 parent 2908f13 commit a7603f3

File tree

6 files changed

+100
-9
lines changed

6 files changed

+100
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@
1010

1111
.maven/*
1212
target/*
13+
!target/.gitignore

README.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ To install the extension download the latest release from the [releases page](ht
1616
After the installation of the extension you need to restart the keycloak server.
1717
With the restart the extension will create a bunch of new roles you need to assign to your clients.
1818
To make your life easier, we have created a new role `hawk-client` that combines all the roles needed to access the new endpoints.
19-
20-
Create a new client, or use an existing one, and assign the `hawk-client` role to the "Service account roles" of the client.
21-
This will give your client read-only access to the new endpoints.
22-
23-
If you want to do management operations (like updating the profile structure or managing resource permissions),
24-
you need to assign the corresponding roles to your client: `hawk-manage-profile-structure`, `hawk-manage-profile-data`, `hawk-manage-resource-permissions`.
25-
26-
As a last step, open your "Realm settings" you want to use the client with go to "Events" and add the "hawk-cache-buster" event listener.
19+
The installer will also automatically add a new group of client scopes to your realm called `hawk-client` as well, that you can assign to your clients.
20+
21+
1. Create a new client, or use an existing one
22+
2. Open the client and navigate to the "Service account roles" tab
23+
3. Assign the `(realm-management) hawk-client` role to the client
24+
- If you want to do management operations (like updating the profile structure or managing resource permissions),
25+
you need to assign the corresponding roles to your client: `hawk-manage-profile-structure`, `hawk-manage-profile-data`, `hawk-manage-resource-permissions`.
26+
4. Open the "Client scopes" tab
27+
5. Add the `hawk-client` scope using the "Default" option.
28+
6. Open the "Realm settings" in your main menu
29+
7. Navigate to the "Events" tab and add the `hawk-cache-buster` event listener.
2730

2831
## What's in the box?
2932

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.hawk.keycloak;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.keycloak.models.*;
5+
import org.keycloak.models.utils.KeycloakModelUtils;
6+
import org.keycloak.protocol.oidc.mappers.GroupMembershipMapper;
7+
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
8+
import org.keycloak.protocol.oidc.mappers.UserClientRoleMappingMapper;
9+
import org.keycloak.protocol.oidc.mappers.UserRealmRoleMappingMapper;
10+
11+
import java.util.stream.Stream;
12+
13+
@RequiredArgsConstructor
14+
public class ClientScopeRegistration {
15+
public final static String CLIENT_SCOPE_NAME = "hawk-client";
16+
17+
final private KeycloakSessionFactory sessionFactory;
18+
19+
public void register() {
20+
KeycloakModelUtils.runJobInTransaction(sessionFactory, (KeycloakSession session) -> {
21+
Stream<RealmModel> realms = session.realms().getRealmsStream();
22+
realms.forEach(this::registerInRealm);
23+
});
24+
}
25+
26+
public void registerInRealm(RealmModel realm) {
27+
28+
ClientScopeModel scope = realm.getClientScopesStream()
29+
.filter(s -> s.getName().equals(CLIENT_SCOPE_NAME))
30+
.findFirst()
31+
.orElse(null);
32+
33+
if (scope != null) {
34+
return;
35+
}
36+
37+
// Create the scope
38+
scope = realm.addClientScope(CLIENT_SCOPE_NAME);
39+
scope.setDescription("Required claims for the hawk-client library");
40+
scope.setProtocol("openid-connect");
41+
scope.setIncludeInTokenScope(false);
42+
scope.setDisplayOnConsentScreen(false);
43+
44+
// Realm Roles
45+
ProtocolMapperModel realmRoleMapper = UserRealmRoleMappingMapper.create(
46+
null,
47+
"realm roles",
48+
"hawk.roles.realm",
49+
false,
50+
false,
51+
false,
52+
true
53+
);
54+
realmRoleMapper.getConfig().put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
55+
scope.addProtocolMapper(realmRoleMapper);
56+
57+
// Client Roles
58+
ProtocolMapperModel clientRoleMapper = UserClientRoleMappingMapper.create(
59+
null,
60+
null,
61+
"client roles",
62+
"hawk.roles.client.${client_id}",
63+
false,
64+
false,
65+
false,
66+
true
67+
);
68+
clientRoleMapper.getConfig().put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
69+
scope.addProtocolMapper(clientRoleMapper);
70+
71+
// Groups
72+
ProtocolMapperModel groupMapper = GroupMembershipMapper.create(
73+
"groups",
74+
"hawk.groups",
75+
false,
76+
null,
77+
false,
78+
false,
79+
false
80+
);
81+
groupMapper.getConfig().put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
82+
scope.addProtocolMapper(groupMapper);
83+
}
84+
}

src/main/java/com/hawk/keycloak/HawkResourceProviderFactory.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ public void init(Config.Scope scope) {
2525
@Override
2626
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
2727
java.util.concurrent.Executors.newSingleThreadScheduledExecutor().schedule(
28-
() -> new RoleRegistration(keycloakSessionFactory).register(),
28+
() -> {
29+
new RoleRegistration(keycloakSessionFactory).register();
30+
new ClientScopeRegistration(keycloakSessionFactory).register();
31+
},
2932
1, // delay duration
3033
java.util.concurrent.TimeUnit.SECONDS // delay unit
3134
);
-33 KB
Binary file not shown.
-65.3 KB
Binary file not shown.

0 commit comments

Comments
 (0)