Skip to content

Commit 7d6e1ab

Browse files
committed
trigger msg to webhook when user create and update in README
1 parent 3c2a59e commit 7d6e1ab

File tree

3 files changed

+101
-6
lines changed

3 files changed

+101
-6
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@
33
## TLDR
44
A Keycloak extension that listens for user events (create/register) and forwards them to your webhook.
55

6+
## Additional Information
7+
We customize the project for our purpose.
8+
9+
### Parameter
10+
11+
```
12+
-e KC_SPI_EVENT_LISTENER_KEYCLOAK_EVENTS_WEBHOOK_URL=http://host.docker.internal:8000/sb/api/v1/user/event \
13+
-e KC_SPI_EVENT_LISTENER_KEYCLOAK_EVENTS_WEBHOOK_KEYCLOAK_ISSUER=https://service-name/auth \
14+
-e KC_SPI_EVENT_LISTENER_KEYCLOAK_EVENTS_WEBHOOK_KEYCLOAK_CLIENT_ID={client_id}} \
15+
-e KC_SPI_EVENT_LISTENER_KEYCLOAK_EVENTS_WEBHOOK_KEYCLOAK_CLIENT_SECRET={client_secret}} \
16+
-e KC_SPI_EVENT_LISTENER_KEYCLOAK_EVENTS_WEBHOOK_KEYCLOAK_REALM={realm_name}} \
17+
```
18+
619
## Quick Start
720
```bash
821
# Clone the repository

src/main/java/com/cevher/keycloak/Client.java

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
import org.jboss.logging.Logger;
44

5+
import com.google.gson.JsonObject;
6+
import com.google.gson.JsonParser;
7+
58
import java.io.BufferedReader;
69
import java.io.IOException;
10+
import java.io.InputStream;
711
import java.io.InputStreamReader;
812
import java.io.OutputStream;
913
import java.net.HttpURLConnection;
@@ -12,7 +16,17 @@
1216

1317
public class Client {
1418
private static final Logger log = Logger.getLogger(Client.class);
15-
private static final String WEBHOOK_URL = "WEBHOOK_URL";
19+
private static final String WEBHOOK_URL = "KC_SPI_EVENT_LISTENER_KEYCLOAK_EVENTS_WEBHOOK_URL";
20+
21+
private static final String WEBHOOK_KEYCLOAK_ISSUER = "KC_SPI_EVENT_LISTENER_KEYCLOAK_EVENTS_WEBHOOK_KEYCLOAK_ISSUER";
22+
private static final String WEBHOOK_KEYCLOAK_CLIENT_ID= "KC_SPI_EVENT_LISTENER_KEYCLOAK_EVENTS_WEBHOOK_KEYCLOAK_CLIENT_ID";
23+
private static final String WEBHOOK_KEYCLOAK_CLIENT_SECRET= "KC_SPI_EVENT_LISTENER_KEYCLOAK_EVENTS_WEBHOOK_KEYCLOAK_CLIENT_SECRET";
24+
private static final String WEBHOOK_KEYCLOAK_REALM= "KC_SPI_EVENT_LISTENER_KEYCLOAK_EVENTS_WEBHOOK_KEYCLOAK_REALM";
25+
// KEYCLOAK_ISSUER=https://infrapal.serverlesssalad.com/auth
26+
// KEYCLOAK_CLIENT_ID=ss-backend
27+
// KEYCLOAK_CLIENT_SECRET=lx2kfVGrqRJgwxqpFEc4ot5MTSYyh8A4
28+
29+
1630

1731
public static void postService(String data) throws IOException {
1832
try {
@@ -23,8 +37,11 @@ public static void postService(String data) throws IOException {
2337
throw new IllegalArgumentException("Environment variable WEBHOOK_URL is not set or is empty.");
2438
}
2539

40+
String token = getAuthToken();
41+
2642
URL url = URI.create(urlString).toURL();
2743
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
44+
conn.setRequestProperty("Authorization", "Bearer " + token); // Add token to header
2845
conn.setDoOutput(true);
2946
conn.setRequestMethod("POST");
3047
conn.setRequestProperty("Content-Type", "application/json; utf-8");
@@ -50,4 +67,50 @@ public static void postService(String data) throws IOException {
5067
throw new IOException("Failed to post service: " + e.getMessage(), e);
5168
}
5269
}
70+
71+
private static String getAuthToken() {
72+
// Example: Use Keycloak's Admin Client API to get a token
73+
String issuer = System.getenv(WEBHOOK_KEYCLOAK_ISSUER);
74+
String clientId = System.getenv(WEBHOOK_KEYCLOAK_CLIENT_ID);
75+
String clientSecret = System.getenv(WEBHOOK_KEYCLOAK_CLIENT_SECRET);
76+
String realm = System.getenv(WEBHOOK_KEYCLOAK_REALM);
77+
78+
if (issuer == null || issuer.isEmpty() || clientId == null || clientId.isEmpty() || clientSecret == null || clientSecret.isEmpty() || realm == null || realm.isEmpty()) {
79+
throw new IllegalArgumentException("Environment variable WEBHOOK_KEYCLOAK_ISSUER or WEBHOOK_KEYCLOAK_CLIENT_ID or WEBHOOK_KEYCLOAK_CLIENT_SECRET or WEBHOOK_KEYCLOAK_REALM is not set or is empty.");
80+
}
81+
82+
String authUrl = issuer + "/realms/" + realm + "/protocol/openid-connect/token";
83+
try {
84+
URL url = new URL(authUrl);
85+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
86+
connection.setRequestMethod("POST");
87+
connection.setDoOutput(true);
88+
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
89+
90+
String body = "grant_type=client_credentials&client_id=" + clientId + "&client_secret=" + clientSecret;
91+
try (OutputStream os = connection.getOutputStream()) {
92+
os.write(body.getBytes("utf-8"));
93+
}
94+
95+
if (connection.getResponseCode() == 200) {
96+
try (InputStream is = connection.getInputStream();
97+
BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
98+
StringBuilder response = new StringBuilder();
99+
String line;
100+
while ((line = reader.readLine()) != null) {
101+
response.append(line);
102+
}
103+
104+
// Parse the token from the response
105+
String responseBody = response.toString();
106+
JsonObject jsonResponse = JsonParser.parseString(responseBody).getAsJsonObject();
107+
return jsonResponse.get("access_token").getAsString();
108+
}
109+
} else {
110+
throw new RuntimeException("Failed to get token: " + connection.getResponseCode());
111+
}
112+
} catch (Exception e) {
113+
throw new RuntimeException("Error while obtaining auth token", e);
114+
}
115+
}
53116
}

src/main/java/com/cevher/keycloak/CustomEventListenerProvider.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
import org.keycloak.events.admin.AdminEvent;
88
import org.keycloak.events.admin.OperationType;
99
import org.keycloak.events.admin.ResourceType;
10+
import org.keycloak.models.AuthenticatedClientSessionModel;
1011
import org.keycloak.models.KeycloakSession;
1112
import org.keycloak.models.RealmModel;
1213
import org.keycloak.models.RealmProvider;
1314
import org.keycloak.models.UserModel;
15+
import org.keycloak.models.UserSessionModel;
1416

1517
import java.util.StringJoiner;
1618

@@ -39,7 +41,10 @@ public void onEvent(Event event) {
3941

4042
RealmModel realm = this.model.getRealm(event.getRealmId());
4143
UserModel user = this.session.users().getUserById(realm, event.getUserId());
44+
45+
System.out.println("trigger to update new user in target : user_name" + user.getUsername());
4246
sendUserData(user);
47+
4348
}
4449

4550
}
@@ -56,20 +61,20 @@ public void onEvent(AdminEvent adminEvent, boolean b) {
5661
RealmModel realm = this.model.getRealm(adminEvent.getRealmId());
5762
UserModel user = this.session.users().getUserById(realm, adminEvent.getResourcePath().substring(6));
5863

64+
System.out.println("trigger to update new user in target : user_name" + user.getUsername());
5965
sendUserData(user);
6066
}
6167
}
6268

6369
private void sendUserData(UserModel user) {
6470
String data = """
6571
{
66-
"id": "%s",
72+
"external_id": "%s",
6773
"email": "%s",
68-
"userName": "%s",
69-
"firstName": "%s",
70-
"lastName": "%s"
74+
"first_name": "%s",
75+
"last_name": "%s"
7176
}
72-
""".formatted(user.getId(), user.getEmail(), user.getUsername(), user.getFirstName(), user.getLastName());
77+
""".formatted(user.getId(), user.getEmail(), user.getFirstName(), user.getLastName());
7378
try {
7479
Client.postService(data);
7580
log.debug("A new user has been created and post API");
@@ -136,4 +141,18 @@ private String toString(AdminEvent event) {
136141
return joiner.toString();
137142
}
138143

144+
public String getAccessTokenForUserSession(UserSessionModel userSession, String clientUUID) {
145+
// Get the client session for the specified client UUID
146+
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(clientUUID);
147+
148+
if (clientSession != null) {
149+
// Get the access token from the client session
150+
String accessToken = clientSession.getNote("access_token");
151+
return accessToken;
152+
} else {
153+
// If client session is not found
154+
return null;
155+
}
156+
}
157+
139158
}

0 commit comments

Comments
 (0)