Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/maven/org.bouncycastle-bcprov-jdk…
Browse files Browse the repository at this point in the history
…18on-1.78
  • Loading branch information
omercnet authored Sep 12, 2024
2 parents 6cf5a65 + 24b3585 commit 798db79
Show file tree
Hide file tree
Showing 28 changed files with 381 additions and 53 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ try {
// Handle the error
}

// Update will override all fields as is. Use carefully.
// Update will override all fields as is. Use carefully. Use patch instead if providing select fields.
try {
us.update("[email protected]", UserRequest.builder()
.email("[email protected]")
Expand All @@ -723,7 +723,17 @@ try {
.tenantId("tenant-ID1")
.roleNames(Arrays.asList("role-name1"),
AssociatedTenant.builder()
.tenantId("tenant-ID2")))));
.tenantId("tenant-ID2"))))
.build());
} catch (DescopeException de) {
// Handle the error
}

// Patch will override provided fields but will leave other fields untouched.
try {
us.patch("[email protected]", PatchUserRequest.builder()
.name("Desmond Copeland")
.build());
} catch (DescopeException de) {
// Handle the error
}
Expand Down
2 changes: 1 addition & 1 deletion examples/management-cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<dependency>
<groupId>com.descope</groupId>
<artifactId>java-sdk</artifactId>
<version>1.0.21</version>
<version>1.0.27</version>
</dependency>
<dependency>
<groupId>info.picocli</groupId>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<groupId>com.descope</groupId>
<artifactId>java-sdk</artifactId>
<modelVersion>4.0.0</modelVersion>
<version>1.0.21</version>
<version>1.0.27</version>
<name>${project.groupId}:${project.artifactId}</name>
<description>Java library used to integrate with Descope.</description>
<url>https://github.com/descope/descope-java</url>
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/com/descope/enums/TenantAuthType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.descope.enums;

import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;

public enum TenantAuthType {
OIDC("oidc"),
SAML("saml"),
NONE("none");

@Getter
@JsonValue
private final String value;

TenantAuthType(String value) {
this.value = value;
}
}
3 changes: 2 additions & 1 deletion src/main/java/com/descope/literals/Routes.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public static class ManagementEndPoints {
// User
public static final String CREATE_USER_LINK = "/v1/mgmt/user/create";
public static final String CREATE_USERS_BATCH_LINK = "/v1/mgmt/user/create/batch";
public static final String PATCH_USER_LINK = "/v1/mgmt/user/patch";
public static final String UPDATE_USER_LINK = "/v1/mgmt/user/update";
public static final String DELETE_USER_LINK = "/v1/mgmt/user/delete";
public static final String DELETE_ALL_TEST_USERS_LINK = "/v1/mgmt/user/test/delete/all";
Expand Down Expand Up @@ -125,7 +126,7 @@ public static class ManagementEndPoints {
public static final String LOAD_ALL_TENANTS_LINK = "/v1/mgmt/tenant/all";
public static final String TENANT_SEARCH_ALL_LINK = "/v1/mgmt/tenant/search";
public static final String GET_TENANT_SETTINGS_LINK = "/v1/mgmt/tenant/settings";

// SSO
public static final String SSO_GET_SETTINGS_LINK = "/v1/mgmt/sso/settings";
public static final String SSO_DELETE_SETTINGS_LINK = "/v1/mgmt/sso/settings";
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/descope/model/sso/SSOSAMLSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ public class SSOSAMLSettings {
private String idpCert;
private AttributeMapping attributeMapping;
private List<RoleMapping> roleMappings;
private String spEncryptionKey;
private String spSignKey;
private String subjectNameIdFormat;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ public class SSOSAMLSettingsByMetadata {
private String idpMetadataUrl;
private AttributeMapping attributeMapping;
private List<RoleMapping> roleMappings;
private String spEncryptionKey;
private String spSignKey;
private String subjectNameIdFormat;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ public class SSOSAMLSettingsResponse {
private AttributeMapping attributeMapping;
private List<GroupsMapping> groupsMapping;
private String redirectUrl;
private String spSignCertificate;
private String subjectNameIdFormat;
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@ public class OIDCApplicationRequest {
* The URL where login page is hosted.
*/
private String loginPageUrl;
/**
* Optional determine if the IdP should force the user to re-authenticate.
*/
private Boolean forceAuthentication;
}
12 changes: 12 additions & 0 deletions src/main/java/com/descope/model/ssoapp/SAMLApplicationRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,16 @@ public class SAMLApplicationRequest {
* "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified".
*/
private String subjectNameIdFormat;
/**
* Optional default relay state value that will be used in the SAML request.
*/
private String defaultRelayState;
/**
* Optional determine if the IdP should force the user to re-authenticate.
*/
private Boolean forceAuthentication;
/**
* Optional Target URL to which the user will be redirected upon logout completion.
*/
private String logoutRedirectURL;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public class SSOApplicationOIDCSettings {
private String loginPageUrl;
private String issuer;
private String discoveryUrl;
private Boolean forceAuthentication;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ public class SSOApplicationSAMLSettings {
private List<String> acsAllowedCallbacks;
private String subjectNameIdType;
private String subjectNameIdFormat;
private String defaultRelayState;
private Boolean forceAuthentication;
private String idpLogoutUrl;
private String logoutRedirectURL;
}
4 changes: 4 additions & 0 deletions src/main/java/com/descope/model/tenant/TenantSettings.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.descope.model.tenant;

import com.descope.enums.TenantAuthType;
import com.fasterxml.jackson.annotation.JsonAlias;
import java.util.List;
import lombok.AllArgsConstructor;
Expand All @@ -23,4 +24,7 @@ public class TenantSettings {
Boolean enableInactivity;
Integer inactivityTime;
String inactivityTimeUnit;
@JsonAlias({"JITDisabled"})
Boolean jitDisabled;
TenantAuthType authType; // authType can be either "oidc" or "saml"
}
49 changes: 49 additions & 0 deletions src/main/java/com/descope/model/user/request/PatchUserRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.descope.model.user.request;

import static com.descope.utils.CollectionUtils.addIfNotNull;

import com.descope.model.auth.AssociatedTenant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class PatchUserRequest {
String name;
String givenName;
String middleName;
String familyName;
String phone;
String email;
List<String> roleNames;
List<AssociatedTenant> userTenants;
Map<String, Object> customAttributes;
String picture;
Boolean verifiedEmail;
Boolean verifiedPhone;
List<String> ssoAppIds;

public Map<String, Object> toMap() {
Map<String, Object> m = new HashMap<>();
addIfNotNull(m, "email", email);
addIfNotNull(m, "verifiedEmail", verifiedEmail);
addIfNotNull(m, "phone", phone);
addIfNotNull(m, "verifiedPhone", verifiedPhone);
addIfNotNull(m, "givenName", givenName);
addIfNotNull(m, "middleName", middleName);
addIfNotNull(m, "familyName", familyName);
addIfNotNull(m, "roleNames", roleNames);
addIfNotNull(m, "userTenants", userTenants);
addIfNotNull(m, "customAttributes", customAttributes);
addIfNotNull(m, "picture", picture);
addIfNotNull(m, "ssoAppIDs", ssoAppIds);
return m;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.descope.model.user.request;


import static com.descope.utils.CollectionUtils.addIfNotNull;

import com.descope.model.auth.AssociatedTenant;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ public class UserSearchRequest {
List<UserStatus> statuses;
List<String> emails;
List<String> phones;
List<String> loginIds;
List<String> ssoAppIds;
}
2 changes: 2 additions & 0 deletions src/main/java/com/descope/proxy/ApiProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public interface ApiProxy {

<B, R> R post(URI uri, B body, Class<R> returnClz);

<B, R> R patch(URI uri, B body, Class<R> returnClz);

<B, R> R postAndGetArray(URI uri, B body, TypeReference<R> typeReference);

<B, R> R delete(URI uri, B body, Class<R> returnClz);
Expand Down
15 changes: 13 additions & 2 deletions src/main/java/com/descope/proxy/impl/AbstractProxyImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public R handleResponse(ClassicHttpResponse response) throws HttpException, IOEx
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
final ByteArrayOutputStream bs = new ByteArrayOutputStream();
final TeeInputStream tee = new TeeInputStream(res.getEntity().getContent(), bs, true);

if (res.getCode() < 200 || response.getCode() > 299) {
if (res.getCode() == 429) { // Rate limit from infra
throw new RateLimitExceededException(
Expand Down Expand Up @@ -118,7 +118,7 @@ public R handleResponse(ClassicHttpResponse response) throws HttpException, IOEx
throw ServerCommonException.parseResponseError("Error parsing response", bs.toString(), e);
}
}
}
}
});
}
}
Expand Down Expand Up @@ -167,6 +167,17 @@ protected <B, R> R post(URI uri, B body, TypeReference<R> typeReference) {
return exchange(builder.build(), null, typeReference);
}

@SneakyThrows
protected <B, R> R patch(URI uri, B body, Class<R> returnClz) {
final ClassicRequestBuilder builder = ClassicRequestBuilder.patch(uri);
if (body != null) {
final ObjectMapper objectMapper = new ObjectMapper().setSerializationInclusion(Include.NON_NULL);
final byte[] payload = objectMapper.writeValueAsBytes(body);
builder.setEntity(new ByteArrayEntity(payload, ContentType.APPLICATION_JSON));
}
return exchange(builder.build(), returnClz, null);
}

protected <R> R get(URI uri, Class<R> returnClz) {
return exchange(ClassicRequestBuilder.get(uri).build(), returnClz, null);
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/descope/proxy/impl/ApiProxyImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public <B, R> R post(URI uri, B body, Class<R> returnClz) {
return super.post(uri, body, returnClz);
}

@Override
public <B, R> R patch(URI uri, B body, Class<R> returnClz) {
return super.patch(uri, body, returnClz);
}

@Override
public <B, R> R postAndGetArray(URI uri, B body, TypeReference<R> typeReference) {
return super.post(uri, body, typeReference);
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/descope/sdk/auth/TOTPService.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@ AuthenticationInfo signInCode(
LoginOptions loginOptions)
throws DescopeException;

/**
* Use to verify a SignIn/SignUp based on the given loginID.
*
* @param loginId - User login ID
* @param code - code to verify
* @param loginOptions - {@link LoginOptions LoginOptions}
* @param refreshToken - Refresh Token
* @return a list of cookies
* @throws DescopeException - error upon failure
*/
AuthenticationInfo signInCode(
String loginId,
String code,
LoginOptions loginOptions,
String refreshToken)
throws DescopeException;

/**
* Set a seed to an existing user, so the user can use an authenticator app.
*
Expand All @@ -45,4 +62,16 @@ AuthenticationInfo signInCode(
*/
TOTPResponse updateUser(String loginId)
throws DescopeException;


/**
* Set a seed to an existing user, so the user can use an authenticator app.
*
* @param loginId - User login ID
* @param refreshToken - Refresh Token
* @return TOTPResponse
* @throws DescopeException - error upon failure
*/
TOTPResponse updateUser(String loginId, String refreshToken)
throws DescopeException;
}
36 changes: 30 additions & 6 deletions src/main/java/com/descope/sdk/auth/impl/TOTPServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.descope.model.user.User;
import com.descope.proxy.ApiProxy;
import com.descope.sdk.auth.TOTPService;
import com.descope.utils.JwtUtils;
import java.net.URI;
import org.apache.commons.lang3.StringUtils;

Expand All @@ -40,29 +41,52 @@ public TOTPResponse signUp(String loginId, User user) throws DescopeException {
@Override
public AuthenticationInfo signInCode(String loginId, String code, LoginOptions loginOptions)
throws DescopeException {
return signInCode(loginId, code, loginOptions, null);
}

@Override
public AuthenticationInfo signInCode(String loginId, String code, LoginOptions loginOptions, String refreshToken)
throws DescopeException {
if (StringUtils.isBlank(loginId)) {
throw ServerCommonException.invalidArgument("loginId");
}

AuthenticationVerifyRequestBody authenticationVerifyRequestBody =
new AuthenticationVerifyRequestBody(loginId, code, loginOptions);
AuthenticationVerifyRequestBody authenticationVerifyRequestBody = new AuthenticationVerifyRequestBody(loginId, code,
loginOptions);
URI totpVerifyCode = composeVerifyTOTPCodeURL();
ApiProxy apiProxy = getApiProxy();
JWTResponse jwtResponse =
apiProxy.post(totpVerifyCode, authenticationVerifyRequestBody, JWTResponse.class);
ApiProxy apiProxy;
if (JwtUtils.isJWTRequired(loginOptions)) {
if (StringUtils.isBlank(refreshToken)) {
throw ServerCommonException.invalidArgument("refreshToken");
}
apiProxy = getApiProxy(refreshToken);
} else {
apiProxy = getApiProxy();
}
JWTResponse jwtResponse = apiProxy.post(totpVerifyCode, authenticationVerifyRequestBody, JWTResponse.class);

return getAuthenticationInfo(jwtResponse);
}

@Override
public TOTPResponse updateUser(String loginId) throws DescopeException {
return updateUser(loginId, null);
}

@Override
public TOTPResponse updateUser(String loginId, String refreshToken) throws DescopeException {
if (StringUtils.isBlank(loginId)) {
throw ServerCommonException.invalidArgument("loginId");
}

URI totpUpdateUser = composeUpdateTOTPURL();
TotpSignUpRequestBody signUpRequest = TotpSignUpRequestBody.builder().loginId(loginId).build();
ApiProxy apiProxy = getApiProxy();
ApiProxy apiProxy;
if (StringUtils.isBlank(refreshToken)) {
apiProxy = getApiProxy();
} else {
apiProxy = getApiProxy(refreshToken);
}
return apiProxy.post(totpUpdateUser, signUpRequest, TOTPResponse.class);
}

Expand Down
Loading

0 comments on commit 798db79

Please sign in to comment.