Skip to content
This repository was archived by the owner on Jan 9, 2026. It is now read-only.

Commit a8a8bc3

Browse files
User Management example (#51)
* User Management example * Add support for user identities * usermanagement -> user_management * Delete unneeded files * follow convention for module naming * Update java-usermanagement-example/README.md Co-authored-by: Michael Hadley <m@mthadley.com> * Update SDK version --------- Co-authored-by: Michael Hadley <m@mthadley.com>
1 parent 4e510d0 commit a8a8bc3

14 files changed

Lines changed: 685 additions & 1 deletion

File tree

buildSrc/src/main/kotlin/com.workos.java.examples.java-application-conventions.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ dependencies {
99

1010
implementation("gg.jte:jte:1.12.0")
1111

12-
implementation("com.workos:workos:2.9.1")
12+
implementation("com.workos:workos:3.1.0-beta.user-management1")
1313

1414
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.0")
1515

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
connection.project.dir=..
2+
eclipse.preferences.version=1
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
If your SaaS product’s backend is built with Java—or a JVM-compatible language such as Kotlin, Groovy, Scala, or Clojure—and you want to incorporate WorkOS’ User Management functionality, you can do a dry-run using this example Java app. It makes use of the [WorkOS Kotlin SDK](https://github.com/workos/workos-kotlin).
2+
3+
If you get stuck while following the steps below and aren't able to resolve the issue by reading our [API reference](https://workos.com/docs/reference) or [User Management Setup Guide](https://workos.com/docs/user-management/guide), please reach out to us at support@workos.com so we can help!
4+
5+
## Prerequisites
6+
A free WorkOS account, and each of these installed on your machine:
7+
- Java version 1.8+
8+
- The Java Development Kit (JDK), which includes the Java Runtime Environment (JRE)
9+
10+
## Clone the Java app
11+
1. In your CLI, navigate to the directory into which you want to clone the Java example app git repo:
12+
```bash
13+
$ cd ~/Desktop
14+
```
15+
16+
2. Clone the main Java example app repo:
17+
```bash
18+
# HTTPS
19+
$ git clone https://github.com/workos/java-example-applications.git
20+
21+
or
22+
23+
# SSH
24+
$ git clone git@github.com:workos/java-example-applications.git
25+
```
26+
27+
3. Navigate to the cloned repo:
28+
```bash
29+
$ cd java-example-applications/
30+
```
31+
32+
## Securely store the environment variables
33+
4. Obtain and make note of your WorkOS API key and WorkOS Client ID from the WorkOS Dashboard. The locations of these values are shown in the screenshots below.
34+
35+
![Screenshot of the WorkOS dashboard showing where to locate the API key](https://assets-global.website-files.com/5f03ef1d331a69193fae6dcd/61986a545cae6987e741c044_TXlyTFBXjAfHZwhb9l-YRvpdj3LCCSXX5frveCFXh1Ywlc482yvdpKHDDRl9QKH3CXbsCwCj9Sya4DAmxvvK293sREyeTJJW8NidhsDgc5lXSU15H6cFpHIlXaAeqHXge259YQju.png)
36+
37+
![Screenshot of the WorkOS dashboard showing where to locate the Client ID](https://assets-global.website-files.com/5f03ef1d331a69193fae6dcd/61986a53882d3a558ae819ee_-ZbW48EgfBtiMuTQEDAaV0UtSxw2wt6Mx-NAX5YxIdI87AZT3bI5w_7jS6tHk-TlG0aHC08AD-l_wr3v_RmUMzSyTehrLIk8D5A7hQ5UskvPVeuXec-9yf6pLTBxkm68PF3kHsqv.png)
38+
39+
5. Create a .env file in the java-example-applications/ directory to store the environment variables:
40+
```bash
41+
$ touch .env
42+
```
43+
44+
6. Open the new .env file with your preferred text editor and replace the placeholder values for WORKOS_API_KEY and WORKOS_CLIENT_ID.
45+
```bash
46+
WORKOS_API_KEY=your_api_key_here
47+
WORKOS_CLIENT_ID=your_project_id_here
48+
```
49+
50+
The .env file is listed in this repo's .gitignore file, so your sensitive information will not be checked into version control. This is an important consideration for keeping sensitive information such as API keys private. The WorkOS Kotlin SDK will read your API key and Client ID from the .env file.
51+
52+
## Set up User Management with WorkOS
53+
7. Create an [Organization](https://dashboard.workos.com/organizations) and an [SSO Connection](https://workos.com/docs/user-management/guide/introduction) in the Organization in your WorkOS Dashboard.
54+
8. Copy the Organization ID from the organization that you just set up and add it to the same .env file that you created in step 6. The .env file should now look like this:
55+
```bash
56+
WORKOS_API_KEY=your_api_key_here
57+
WORKOS_CLIENT_ID=your_project_id_here
58+
WORKOS_ORGANIZATION_ID=your_organization_id_here
59+
```
60+
61+
10. Add http://localhost:7001/callback as the default Redirect URI in the Configuration section of the WorkOS Dashboard:
62+
63+
![A screenshot of te default Redirect URI in the WorkOS dashboard](https://assets-global.website-files.com/5f03ef1d331a69193fae6dcd/619d4e48d8ad3f0711f3b1e3_Screen%20Shot%202021-11-23%20at%2012.24.34%20PM.png)
64+
65+
## Test the integration
66+
9. Start the server by running this command in the CLI while you’re in the java-example-applications/ directory:
67+
```bash
68+
$ ./gradlew :java-usermanagement-example:run
69+
```
70+
71+
10. Navigate to http://localhost:7001. Click the “Login” button. You’ll be prompted to sign in using the identity provider (IdP) you configured during the setup.
72+
73+
11. Once you’re signed in, the webpage will display the user information for the logged-in user.
74+
75+
Nice work! You just set up User Management for your Java app!
76+
77+
## Need help?
78+
If you get stuck while following the steps below and aren't able to resolve the issue by reading our [API reference](https://workos.com/docs/reference) or [User Management Setup Guide](https://workos.com/docs/user-management/guide), please reach out to us at support@workos.com so we can help!
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
plugins {
2+
id("com.workos.java.examples.java-application-conventions")
3+
}
4+
5+
repositories {
6+
flatDir {
7+
dirs("libs")
8+
dirs("build/libs")
9+
}
10+
}
11+
12+
13+
application {
14+
mainClass.set("com.workos.java.examples.UserManagementApp")
15+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.workos.java.examples;
2+
3+
import com.workos.WorkOS;
4+
import com.workos.usermanagement.models.Identity;
5+
import com.workos.usermanagement.models.User;
6+
import com.workos.usermanagement.types.UserManagementProviderEnumType;
7+
import io.github.cdimascio.dotenv.Dotenv;
8+
import io.javalin.Javalin;
9+
import io.javalin.http.Context;
10+
import io.javalin.http.staticfiles.Location;
11+
import java.util.Map;
12+
13+
14+
public class UserManagementApp {
15+
private final WorkOS workos;
16+
private final String clientId;
17+
18+
public UserManagementApp() {
19+
Dotenv env = Dotenv.configure().directory("../.env").load();
20+
21+
Javalin app = Javalin.create(config -> {
22+
config.addStaticFiles("src/resources", Location.EXTERNAL);
23+
}).start(7001);
24+
25+
workos = new WorkOS(env.get("WORKOS_API_KEY"));
26+
clientId = env.get("WORKOS_CLIENT_ID");
27+
28+
app.get("/", this::isLoggedIn);
29+
app.post("/login", this::login);
30+
app.get("/callback", this::callback);
31+
app.get("logout", this::logout);
32+
}
33+
34+
public void login(Context ctx) {
35+
String loginMethod = ctx.formParam("login_method");
36+
37+
String url =
38+
workos
39+
.userManagement
40+
.getAuthorizationUrl(clientId, "http://localhost:7001/callback")
41+
.provider(UserManagementProviderEnumType.valueOf(loginMethod))
42+
.build();
43+
44+
ctx.redirect(url);
45+
}
46+
47+
public void callback(Context ctx) {
48+
String code = ctx.queryParam("code");
49+
50+
assert code != null;
51+
52+
User user = workos.userManagement.authenticateWithCode(clientId, code, null).getUser();
53+
Identity[] identities = workos.userManagement.getUserIdentities(user.getId());
54+
ctx.sessionAttribute("user", user);
55+
ctx.sessionAttribute("identities", identities);
56+
57+
ctx.redirect("/");
58+
}
59+
60+
public void isLoggedIn(Context ctx) {
61+
if (ctx.sessionAttribute("user") != null){
62+
ctx.render("user.jte", Map.of("user", ctx.sessionAttribute("user"), "identities", ctx.sessionAttribute("identities")));
63+
} else {
64+
ctx.render("home.jte");
65+
}
66+
}
67+
68+
public void logout(Context ctx ) {
69+
ctx.sessionAttribute("user", null);
70+
ctx.redirect("/");
71+
}
72+
73+
public static void main(String[] args) {
74+
new UserManagementApp();
75+
}
76+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<link rel="stylesheet" href="main.css">
2+
3+
<body class="height-100vh">
4+
<div class="logged_in_nav">
5+
<div class="flex">
6+
<div>
7+
<img src="images/workos-logo-with-text.png" alt="workos logo">
8+
</div>
9+
10+
</div>
11+
<div class="flex">
12+
<a href="https://workos.com/docs" target="_blank"><button class='button nav-item'>Documentation</button></a>
13+
<a href="https://workos.com/docs/reference" target="_blank"><button class='button nav-item'>API
14+
Reference</button></a>
15+
<a href="https://workos.com/blog" target="_blank"><button
16+
class='button nav-item blog-nav-button'>Blog</button></a>
17+
<a href="https://workos.com/" target="_blank"><button class='button button-outline'>WorkOS</button></a>
18+
</div>
19+
</div>
20+
<div class="flex flex_column height-80vh">
21+
<div class='flex height-40vh'>
22+
<div class="card height-315 width-335">
23+
<form method="POST" action="/login" class="mb-0">
24+
<div class='flex_column'>
25+
<div>
26+
<span>Log in</span>
27+
</div>
28+
<hr style="width:100%; margin-top: 15px; margin-bottom: 20px;">
29+
<button id="Google" name="login_method" value="GoogleOAuth" class="card login_button google_button">
30+
<span>Google OAuth</span>
31+
</button>
32+
<button id="Microsoft" name="login_method" value="MicrosoftOAuth" class="card login_button microsoft_button">
33+
<span>Microsoft OAuth</span>
34+
</button>
35+
<button id="SAML" name="login_method" value="saml" class="card login_button saml_button mb-0">
36+
<span>Enterprise SAML</span>
37+
</button>
38+
</div>
39+
</form>
40+
</div>
41+
</div>
42+
</div>
43+
</body>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
@param com.workos.usermanagement.models.User user
2+
@param com.workos.usermanagement.models.Identity[] identities
3+
4+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
5+
<link rel="stylesheet" href="main.css">
6+
7+
<div class="logged_in_nav">
8+
<div class="flex">
9+
<div>
10+
<img src="images/workos-logo-with-text.png" alt="workos logo">
11+
</div>
12+
13+
</div>
14+
<div class="flex">
15+
<a href="https://workos.com/docs" target="_blank"><button class='button nav-item'>Documentation</button></a>
16+
<a href="https://workos.com/docs/reference" target="_blank"><button class='button nav-item'>API
17+
Reference</button></a>
18+
<a href="https://workos.com/blog" target="_blank"><button
19+
class='button nav-item blog-nav-button'>Blog</button></a>
20+
<a href="https://workos.com/" target="_blank"><button class='button button-outline'>WorkOS</button></a>
21+
</div>
22+
</div>
23+
<div class='flex'>
24+
<div class="logged_in_div_right">
25+
<div class="flex_column">
26+
<table>
27+
<tr>
28+
<th>User</th>
29+
</tr>
30+
<tr>
31+
<td>First Name: <code>${user.getFirstName()}</code></td>
32+
</tr>
33+
<tr>
34+
<td>Last Name: <code>${user.getLastName()}</code></td>
35+
</tr>
36+
<tr>
37+
<td>Email: <code>${user.getEmail()}</code></td>
38+
</tr>
39+
<tr>
40+
<td>ID: <code>${user.getId()}</code></td>
41+
</tr>
42+
<tr>
43+
<td>Email Verified: <code>${user.getEmailVerified()}</code></td>
44+
</tr>
45+
<tr>
46+
<td>Identities: <code>${java.util.Arrays.stream(identities).map(i -> i.toString()).toList().toString()}</code></td>
47+
</tr>
48+
</table>
49+
<div class="flex width-40vw">
50+
<a href="/logout"><button class='button'>Logout</button></a>
51+
</div>
52+
</div>
53+
</div>
54+
</div>
5.68 KB
Loading
3.24 KB
Loading
4.87 KB
Loading

0 commit comments

Comments
 (0)