Skip to content

Commit a6ff3cf

Browse files
authored
Support mgmt login apis (#153)
* feat: added support for management login APIs, including CLI access * test: added unit tests * chore: styling fixes * chore: more styling issues 😤 * chore: more styling issues 😤 * chore: more styling issues 😤 * chore: more styling issues 😤 * build: updating private key used by unit tests * chore: more styling issues * build: updating pom.xml version
1 parent 08e2d9f commit a6ff3cf

File tree

16 files changed

+643
-41
lines changed

16 files changed

+643
-41
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.descope;
2+
3+
import com.descope.client.DescopeClient;
4+
import com.descope.exception.DescopeException;
5+
import com.descope.model.magiclink.LoginOptions;
6+
import java.util.concurrent.Callable;
7+
import picocli.CommandLine.Command;
8+
import picocli.CommandLine.Option;
9+
10+
@Command(name = "jwt-signin", description = "Sign in and receive verified JWT")
11+
public class JwtSignIn extends HelpBase implements Callable<Integer> {
12+
13+
@Option(names = {"-l", "--login-id"}, description = "Login ID", required = true)
14+
String loginId;
15+
16+
@Option(names = {"-j", "--jwt"}, description = "JWT token for authentication", required = false)
17+
String jwt;
18+
19+
@Override
20+
public Integer call() {
21+
try {
22+
LoginOptions loginOptions = new LoginOptions();
23+
loginOptions.setJwt(jwt); // Optional JWT input
24+
25+
var client = new DescopeClient(); // Assume Client is properly initialized
26+
var authInfo = client.getManagementServices().getJwtService().signIn(loginId, loginOptions);
27+
28+
System.out.println("Sign-in successful!");
29+
System.out.println("Session JWT: " + authInfo.getToken().getJwt());
30+
System.out.println("Refresh JWT: " + authInfo.getRefreshToken().getJwt());
31+
System.out.println("User ID: " + authInfo.getUser().getUserId());
32+
33+
return 0; // Success
34+
} catch (DescopeException e) {
35+
System.err.println("Error during sign-in: " + e.getMessage());
36+
return 1; // Error
37+
}
38+
}
39+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.descope;
2+
3+
import com.descope.client.DescopeClient;
4+
import com.descope.exception.DescopeException;
5+
import com.descope.model.jwt.MgmtSignUpUser;
6+
import com.descope.model.user.User;
7+
import java.util.Map;
8+
import java.util.concurrent.Callable;
9+
import picocli.CommandLine.Command;
10+
import picocli.CommandLine.Option;
11+
12+
@Command(name = "jwt-signup", description = "Sign up and receive verified JWT")
13+
public class JwtSignUp extends HelpBase implements Callable<Integer> {
14+
15+
@Option(names = {"-l", "--login-id"}, description = "Login ID", required = true)
16+
String loginId;
17+
18+
@Option(names = {"--email"}, description = "Email address")
19+
String email;
20+
21+
@Option(names = {"--phone"}, description = "Phone number")
22+
String phone;
23+
24+
@Option(names = {"--name"}, description = "User's full name")
25+
String name;
26+
27+
@Option(names = {"--verified-email"}, description = "Mark email as verified (true/false)")
28+
boolean verifiedEmail;
29+
30+
@Option(names = {"--verified-phone"}, description = "Mark phone as verified (true/false)")
31+
boolean verifiedPhone;
32+
33+
@Option(names = {"--sso-app-id"}, description = "SSO App ID")
34+
String ssoAppId;
35+
36+
@Option(names = {"--custom-claims"}, description = "Custom claims (JSON format)")
37+
String customClaimsJson;
38+
39+
@Override
40+
public Integer call() {
41+
try {
42+
43+
// Create User object if any user-related field is set
44+
User user = null;
45+
if (email != null || phone != null || name != null) {
46+
user = new User();
47+
user.setEmail(email);
48+
user.setPhone(phone);
49+
user.setName(name);
50+
}
51+
52+
// Parse custom claims JSON if provided
53+
Map<String, Object> customClaims = null;
54+
if (customClaimsJson != null && !customClaimsJson.isEmpty()) {
55+
customClaims = parseJsonToMap(customClaimsJson);
56+
}
57+
58+
// Build the MgmtSignUpUser object
59+
var signUpUser = new MgmtSignUpUser();
60+
signUpUser.setUser(user);
61+
signUpUser.setVerifiedEmail(verifiedEmail);
62+
signUpUser.setVerifiedPhone(verifiedPhone);
63+
signUpUser.setSsoAppId(ssoAppId);
64+
signUpUser.setCustomClaims(customClaims);
65+
66+
var client = new DescopeClient(); // Assume Client is properly initialized
67+
var authInfo = client.getManagementServices().getJwtService().signUp(loginId, signUpUser);
68+
69+
System.out.println("Signup successful!");
70+
System.out.println("Session JWT: " + authInfo.getToken().getJwt());
71+
System.out.println("Refresh JWT: " + authInfo.getRefreshToken().getJwt());
72+
System.out.println("User ID: " + authInfo.getUser().getUserId());
73+
74+
return 0; // Success
75+
} catch (DescopeException e) {
76+
System.err.println("Error during sign-up: " + e.getMessage());
77+
return 1; // Error
78+
}
79+
}
80+
81+
private Map<String, Object> parseJsonToMap(String json) {
82+
try {
83+
return new com.fasterxml.jackson.databind.ObjectMapper().readValue(json, Map.class);
84+
} catch (Exception e) {
85+
System.err.println("Invalid custom claims JSON format: " + json);
86+
return null;
87+
}
88+
}
89+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.descope;
2+
3+
import com.descope.client.DescopeClient;
4+
import com.descope.exception.DescopeException;
5+
import com.descope.model.jwt.MgmtSignUpUser;
6+
import com.descope.model.user.User;
7+
import java.util.Map;
8+
import java.util.concurrent.Callable;
9+
import picocli.CommandLine.Command;
10+
import picocli.CommandLine.Option;
11+
12+
@Command(name = "jwt-signuporin", description = "Sign up and receive verified JWT")
13+
public class JwtSignUpOrIn extends HelpBase implements Callable<Integer> {
14+
15+
@Option(names = {"-l", "--login-id"}, description = "Login ID", required = true)
16+
String loginId;
17+
18+
@Option(names = {"--email"}, description = "Email address")
19+
String email;
20+
21+
@Option(names = {"--phone"}, description = "Phone number")
22+
String phone;
23+
24+
@Option(names = {"--name"}, description = "User's full name")
25+
String name;
26+
27+
@Option(names = {"--verified-email"}, description = "Mark email as verified (true/false)")
28+
boolean verifiedEmail;
29+
30+
@Option(names = {"--verified-phone"}, description = "Mark phone as verified (true/false)")
31+
boolean verifiedPhone;
32+
33+
@Option(names = {"--sso-app-id"}, description = "SSO App ID")
34+
String ssoAppId;
35+
36+
@Option(names = {"--custom-claims"}, description = "Custom claims (JSON format)")
37+
String customClaimsJson;
38+
39+
@Override
40+
public Integer call() {
41+
try {
42+
43+
// Create User object if any user-related field is set
44+
User user = null;
45+
if (email != null || phone != null || name != null) {
46+
user = new User();
47+
user.setEmail(email);
48+
user.setPhone(phone);
49+
user.setName(name);
50+
}
51+
52+
// Parse custom claims JSON if provided
53+
Map<String, Object> customClaims = null;
54+
if (customClaimsJson != null && !customClaimsJson.isEmpty()) {
55+
customClaims = parseJsonToMap(customClaimsJson);
56+
}
57+
58+
// Build the MgmtSignUpUser object
59+
var signUpUser = new MgmtSignUpUser();
60+
signUpUser.setUser(user);
61+
signUpUser.setVerifiedEmail(verifiedEmail);
62+
signUpUser.setVerifiedPhone(verifiedPhone);
63+
signUpUser.setSsoAppId(ssoAppId);
64+
signUpUser.setCustomClaims(customClaims);
65+
66+
var client = new DescopeClient(); // Assume Client is properly initialized
67+
var authInfo = client.getManagementServices().getJwtService().signUpOrIn(loginId, signUpUser);
68+
69+
System.out.println("Signuporin successful!");
70+
System.out.println("Session JWT: " + authInfo.getToken().getJwt());
71+
System.out.println("Refresh JWT: " + authInfo.getRefreshToken().getJwt());
72+
System.out.println("User ID: " + authInfo.getUser().getUserId());
73+
74+
return 0; // Success
75+
} catch (DescopeException e) {
76+
System.err.println("Error during sign-up: " + e.getMessage());
77+
return 1; // Error
78+
}
79+
}
80+
81+
private Map<String, Object> parseJsonToMap(String json) {
82+
try {
83+
return new com.fasterxml.jackson.databind.ObjectMapper().readValue(json, Map.class);
84+
} catch (Exception e) {
85+
System.err.println("Invalid custom claims JSON format: " + json);
86+
return null;
87+
}
88+
}
89+
}

examples/management-cli/src/main/java/com/descope/ManagementCLI.java

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,36 @@
66
import picocli.CommandLine.Option;
77

88
@Command(name = "management-cli", subcommands = {
9-
UserCreate.class,
10-
UserUpdate.class,
11-
UserDelete.class,
12-
UserLoad.class,
13-
UserSearch.class,
14-
AccessKeyCreate.class,
15-
AccessKeyUpdate.class,
16-
AccessKeyDelete.class,
17-
AccessKeyLoad.class,
18-
AccessKeySearch.class,
19-
TenantCreate.class,
20-
TenantLoad.class,
21-
TenantUpdate.class,
22-
TenantDelete.class,
23-
PermissionCreate.class,
24-
PermissionUpdate.class,
25-
PermissionDelete.class,
26-
PermissionLoadAll.class,
27-
RoleCreate.class,
28-
RoleDelete.class,
29-
RoleUpdate.class,
30-
RoleLoadAll.class,
31-
AuditSearch.class,
32-
AuditCreate.class
9+
UserCreate.class,
10+
UserUpdate.class,
11+
UserDelete.class,
12+
UserLoad.class,
13+
UserSearch.class,
14+
AccessKeyCreate.class,
15+
AccessKeyUpdate.class,
16+
AccessKeyDelete.class,
17+
AccessKeyLoad.class,
18+
AccessKeySearch.class,
19+
TenantCreate.class,
20+
TenantLoad.class,
21+
TenantUpdate.class,
22+
TenantDelete.class,
23+
PermissionCreate.class,
24+
PermissionUpdate.class,
25+
PermissionDelete.class,
26+
PermissionLoadAll.class,
27+
RoleCreate.class,
28+
RoleDelete.class,
29+
RoleUpdate.class,
30+
RoleLoadAll.class,
31+
AuditSearch.class,
32+
AuditCreate.class,
33+
JwtSignIn.class,
34+
JwtSignUp.class,
35+
JwtSignUpOrIn.class
3336
})
3437
public class ManagementCLI implements Callable<Integer> {
35-
@Option(names = { "-h", "--help"}, usageHelp = true, description = "show this help message and exit")
38+
@Option(names = { "-h", "--help" }, usageHelp = true, description = "show this help message and exit")
3639
boolean help;
3740

3841
static CommandLine cli;

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<groupId>com.descope</groupId>
55
<artifactId>java-sdk</artifactId>
66
<modelVersion>4.0.0</modelVersion>
7-
<version>1.0.32</version>
7+
<version>1.0.33</version>
88
<name>${project.groupId}:${project.artifactId}</name>
99
<description>Java library used to integrate with Descope.</description>
1010
<url>https://github.com/descope/descope-java</url>

src/main/java/com/descope/literals/Routes.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ public static class ManagementEndPoints {
161161

162162
// JWT
163163
public static final String UPDATE_JWT_LINK = "/v1/mgmt/jwt/update";
164+
public static final String MANAGEMENT_SIGN_IN = "/v1/mgmt/auth/signin";
165+
public static final String MANAGEMENT_SIGN_UP = "/v1/mgmt/auth/signup";
166+
public static final String MANAGEMENT_SIGN_UP_OR_IN = "/v1/mgmt/auth/signup-in";
164167

165168
// Access key
166169
public static final String MANAGEMENT_ACCESS_KEY_CREATE_LINK = "/v1/mgmt/accesskey/create";

src/main/java/com/descope/model/auth/AuthenticationInfo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
@Data
99
@AllArgsConstructor
1010
public class AuthenticationInfo {
11-
private Token token;
11+
private Token token; // session token
1212
private Token refreshToken;
1313
private UserResponse user;
1414
private Boolean firstSeen;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.descope.model.jwt;
2+
3+
import com.descope.model.user.User;
4+
import java.util.Map;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Builder;
7+
import lombok.Data;
8+
import lombok.NoArgsConstructor;
9+
10+
@Data
11+
@AllArgsConstructor
12+
@NoArgsConstructor
13+
@Builder
14+
public class MgmtSignUpUser {
15+
private User user;
16+
boolean verifiedEmail;
17+
boolean verifiedPhone;
18+
String ssoAppId;
19+
Map<String, Object> customClaims;
20+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.descope.model.jwt.request;
2+
3+
import java.util.Map;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
8+
@Data
9+
@AllArgsConstructor
10+
@NoArgsConstructor
11+
public class ManagementSignInRequest {
12+
private String loginId;
13+
private boolean stepup;
14+
private boolean mfa;
15+
private boolean revokeOtherSessions;
16+
private Map<String, Object> customClaims;
17+
private String jwt;
18+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.descope.model.jwt.request;
2+
3+
import com.descope.model.user.User;
4+
import java.util.Map;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
9+
@Data
10+
@AllArgsConstructor
11+
@NoArgsConstructor
12+
public class ManagementSignUpRequest {
13+
private String loginId;
14+
private User user;
15+
private boolean emailVerified;
16+
private boolean phoneVerified;
17+
private String ssoAppId;
18+
private Map<String, Object> customClaims;
19+
}

0 commit comments

Comments
 (0)