From a9c17fb9e7a94fd742c42ff9a66206091d33de81 Mon Sep 17 00:00:00 2001 From: Steven Wong Date: Thu, 25 Jul 2024 22:24:56 +0800 Subject: [PATCH 01/14] Update codeowner file with new GitHub team name --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 60f116c0..7958e8bd 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @auth0/dx-sdks-engineer +* @auth0/project-dx-sdks-engineer-codeowner From 7c036e750467f7f8eca523a2f33859ab5970c44e Mon Sep 17 00:00:00 2001 From: Jak Spalding <191585+jak@users.noreply.github.com> Date: Wed, 26 Jun 2024 16:24:39 +0100 Subject: [PATCH 02/14] feat: add sessions and refresh tokens --- .../com/auth0/client/mgmt/UsersEntity.java | 99 +++++++++++ .../filter/CheckpointPaginationFilter.java | 38 +++++ .../users/refreshtokens/RefreshToken.java | 97 +++++++++++ .../refreshtokens/RefreshTokensPage.java | 44 +++++ .../users/refreshtokens/ResourceServer.java | 30 ++++ .../mgmt/users/sessions/Authentication.java | 21 +++ .../users/sessions/AuthenticationMethod.java | 39 +++++ .../json/mgmt/users/sessions/Client.java | 19 +++ .../json/mgmt/users/sessions/Device.java | 55 ++++++ .../json/mgmt/users/sessions/Session.java | 104 ++++++++++++ .../mgmt/users/sessions/SessionsPage.java | 44 +++++ .../java/com/auth0/client/MockServer.java | 2 + .../auth0/client/mgmt/UsersEntityTest.java | 157 ++++++++++++++++++ .../CheckpointPaginationFilterTest.java | 37 +++++ .../refreshtokens/RefreshTokensPageTest.java | 44 +++++ .../mgmt/users/sessions/SessionsPageTest.java | 50 ++++++ .../resources/mgmt/user_refresh_tokens.json | 44 +++++ src/test/resources/mgmt/user_sessions.json | 35 ++++ 18 files changed, 959 insertions(+) create mode 100644 src/main/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilter.java create mode 100644 src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java create mode 100644 src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java create mode 100644 src/main/java/com/auth0/json/mgmt/users/refreshtokens/ResourceServer.java create mode 100644 src/main/java/com/auth0/json/mgmt/users/sessions/Authentication.java create mode 100644 src/main/java/com/auth0/json/mgmt/users/sessions/AuthenticationMethod.java create mode 100644 src/main/java/com/auth0/json/mgmt/users/sessions/Client.java create mode 100644 src/main/java/com/auth0/json/mgmt/users/sessions/Device.java create mode 100644 src/main/java/com/auth0/json/mgmt/users/sessions/Session.java create mode 100644 src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java create mode 100644 src/test/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilterTest.java create mode 100644 src/test/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPageTest.java create mode 100644 src/test/java/com/auth0/json/mgmt/users/sessions/SessionsPageTest.java create mode 100644 src/test/resources/mgmt/user_refresh_tokens.json create mode 100644 src/test/resources/mgmt/user_sessions.json diff --git a/src/main/java/com/auth0/client/mgmt/UsersEntity.java b/src/main/java/com/auth0/client/mgmt/UsersEntity.java index 6d06a3b6..9ee4bfa6 100644 --- a/src/main/java/com/auth0/client/mgmt/UsersEntity.java +++ b/src/main/java/com/auth0/client/mgmt/UsersEntity.java @@ -13,6 +13,8 @@ import com.auth0.json.mgmt.users.RecoveryCode; import com.auth0.json.mgmt.users.User; import com.auth0.json.mgmt.users.UsersPage; +import com.auth0.json.mgmt.users.refreshtokens.RefreshTokensPage; +import com.auth0.json.mgmt.users.sessions.SessionsPage; import com.auth0.net.EmptyBodyRequest; import com.auth0.net.BaseRequest; import com.auth0.net.Request; @@ -787,6 +789,103 @@ public Request updateAuthenticationMethodById(String userI return request; } + /** + * Get refresh tokens for a user + * A token with {@code read:refresh_tokens} is needed. + * See https://auth0.com/docs/api/management/v2/users/get-refresh-tokens-for-user + * + * @param userId the role id + * @param filter an optional pagination filter + * @return a Request to execute + */ + public Request listRefreshTokens(String userId, CheckpointPaginationFilter filter) { + Asserts.assertNotNull(userId, "user id"); + HttpUrl.Builder builder = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("refresh-tokens"); + if (filter != null) { + for (Map.Entry e : filter.getAsMap().entrySet()) { + builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); + } + } + String url = builder.build().toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Delete all refresh tokens for a user. + * A token with scope {@code delete:refresh_tokens} is needed. + * See https://auth0.com/docs/api/management/v2/users/delete-refresh-tokens-for-user + * + * @param userId the user to delete the refresh tokens for + * @return a Request to execute. + */ + public Request deleteRefreshTokens(String userId) { + Asserts.assertNotNull(userId, "user ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("refresh-tokens") + .build() + .toString(); + + return new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); + } + + + /** + * Get sessions for user + * A token with {@code read:sessions} is needed. + * See https://auth0.com/docs/api/management/v2/users/get-sessions-for-user + * + * @param userId the role id + * @param filter an optional pagination filter + * @return a Request to execute + */ + public Request listSessions(String userId, CheckpointPaginationFilter filter) { + Asserts.assertNotNull(userId, "user id"); + HttpUrl.Builder builder = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("sessions"); + if (filter != null) { + for (Map.Entry e : filter.getAsMap().entrySet()) { + builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); + } + } + String url = builder.build().toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Delete sessions for user + * A token with scope {@code delete:sessions} is needed. + * See https://auth0.com/docs/api/management/v2/users/delete-sessions-for-user + * + * @param userId the user to delete the sessions for + * @return a Request to execute. + */ + public Request deleteSessions(String userId) { + Asserts.assertNotNull(userId, "user ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("sessions") + .build() + .toString(); + + return new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); + } + private static void encodeAndAddQueryParam(HttpUrl.Builder builder, BaseFilter filter) { if (filter != null) { for (Map.Entry e : filter.getAsMap().entrySet()) { diff --git a/src/main/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilter.java b/src/main/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilter.java new file mode 100644 index 00000000..1f881b7c --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilter.java @@ -0,0 +1,38 @@ +package com.auth0.client.mgmt.filter; + +public class CheckpointPaginationFilter extends BaseFilter { + + /** + * Return results inside an object that contains the total result count (true) or as a direct array of results (false, default). + * + * @param includeTotals whether to include or not total result count. + * @return this filter instance + */ + public CheckpointPaginationFilter withTotals(boolean includeTotals) { + parameters.put("include_totals", includeTotals); + return this; + } + + /** + * Optional ID from which to start selection (exclusive). + * + * @param from the ID from which to start selection. This can be obtained from the {@code next} field returned from + * a checkpoint-paginated result. + * @return this filter instance. + */ + public CheckpointPaginationFilter withFrom(String from) { + parameters.put("from", from); + return this; + } + + /** + * Number of results per page. Defaults to 50. + * + * @param take the amount of entries to retrieve per page. + * @return this filter instance. + */ + public CheckpointPaginationFilter withTake(int take) { + parameters.put("take", take); + return this; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java new file mode 100644 index 00000000..1551f4dd --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java @@ -0,0 +1,97 @@ +package com.auth0.json.mgmt.users.refreshtokens; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Date; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RefreshToken { + @JsonProperty("id") + private String id; + @JsonProperty("user_id") + private String userId; + @JsonProperty("created_at") + private Date createdAt; + @JsonProperty("idle_expires_at") + private Date idleExpiresAt; + @JsonProperty("expires_at") + private Date expiresAt; + @JsonProperty("client_id") + private String clientId; + @JsonProperty("session_id") + private String sessionId; + @JsonProperty("rotating") + private Boolean rotating; + @JsonProperty("resource_servers") + private List resourceServers; + + /** + * @return The ID of the refresh token + */ + public String getId() { + return id; + } + + /** + * @return ID of the user which can be used when interacting with other APIs. + */ + public String getUserId() { + return userId; + } + + /** + * @return The date and time when the refresh token was created + */ + public Date getCreatedAt() { + return createdAt; + } + + /** + * + * @return The date and time when the refresh token will expire if idle + */ + public Date getIdleExpiresAt() { + return idleExpiresAt; + } + + /** + * + * @return The date and time when the refresh token will expire + */ + public Date getExpiresAt() { + return expiresAt; + } + + /** + * @return ID of the client application granted with this refresh token + */ + public String getClientId() { + return clientId; + } + + /** + * + * @return ID of the authenticated session used to obtain this refresh-token + */ + public String getSessionId() { + return sessionId; + } + + /** + * @return True if the token is a rotating refresh token + */ + public Boolean isRotating() { + return rotating; + } + + /** + * @return A list of the resource server IDs associated to this refresh-token and their granted scopes + */ + public List getResourceServers() { + return resourceServers; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java new file mode 100644 index 00000000..224c0b62 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java @@ -0,0 +1,44 @@ +package com.auth0.json.mgmt.users.refreshtokens; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * This does not extend com.auth0.json.mgmt.Page because the URL only supports "next" and "take" pagination. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RefreshTokensPage { + @JsonProperty("total") + private Integer total; + + @JsonProperty("next") + private String next; + + @JsonProperty("tokens") + private List tokens; + + /** + * @return the total number of refresh tokens. This is only present when `include_totals` is passed as a query parameter. + */ + public Integer getTotal() { + return total; + } + + /** + * @return the token ID from which to start selection for a new page + */ + public String getNext() { + return next; + } + + /** + * @return the list of Tokens + */ + public List getTokens() { + return tokens; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/ResourceServer.java b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/ResourceServer.java new file mode 100644 index 00000000..b423de41 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/ResourceServer.java @@ -0,0 +1,30 @@ +package com.auth0.json.mgmt.users.refreshtokens; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ResourceServer { + @JsonProperty("audience") + private String audience; + @JsonProperty("scopes") + private List scopes; + + /** + * @return Resource server ID + */ + public String getAudience() { + return audience; + } + + /** + * @return List of scopes for the refresh token + */ + public List getScopes() { + return scopes; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/Authentication.java b/src/main/java/com/auth0/json/mgmt/users/sessions/Authentication.java new file mode 100644 index 00000000..dd9ba115 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/sessions/Authentication.java @@ -0,0 +1,21 @@ +package com.auth0.json.mgmt.users.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Authentication { + @JsonProperty("methods") + private List methods; + + /** + * @return Contains the authentication methods a user has completed during their session + */ + public List getMethods() { + return methods; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/AuthenticationMethod.java b/src/main/java/com/auth0/json/mgmt/users/sessions/AuthenticationMethod.java new file mode 100644 index 00000000..c55634c5 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/sessions/AuthenticationMethod.java @@ -0,0 +1,39 @@ +package com.auth0.json.mgmt.users.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Date; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class AuthenticationMethod { + @JsonProperty("name") + private String name; + @JsonProperty("timestamp") + private Date timestamp; + @JsonProperty("type") + private String type; + + /** + * @return One of: "federated", "passkey", "pwd", "sms", "email", "mfa", "mock" or a custom method denoted by a URL + */ + public String getName() { + return name; + } + + /** + * @return Timestamp of when the signal was received + */ + public Date getTimestamp() { + return timestamp; + } + + /** + * @return A specific MFA factor. Only present when "name" is set to "mfa" + */ + public String getType() { + return type; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/Client.java b/src/main/java/com/auth0/json/mgmt/users/sessions/Client.java new file mode 100644 index 00000000..aa51c6e9 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/sessions/Client.java @@ -0,0 +1,19 @@ +package com.auth0.json.mgmt.users.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Client { + @JsonProperty("client_id") + private String clientId; + + /** + * @return ID of client for the session + */ + public String getClientId() { + return clientId; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/Device.java b/src/main/java/com/auth0/json/mgmt/users/sessions/Device.java new file mode 100644 index 00000000..1665c6ed --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/sessions/Device.java @@ -0,0 +1,55 @@ +package com.auth0.json.mgmt.users.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Device { + @JsonProperty("initial_ip") + private String initialIP; + @JsonProperty("initial_asn") + private String initialASN; + @JsonProperty("last_user_agent") + private String lastUserAgent; + @JsonProperty("last_ip") + private String lastIP; + @JsonProperty("last_asn") + private String lastASN; + + /** + * @return First IP address associated with this session + */ + public String getInitialIP() { + return initialIP; + } + + /** + * @return First autonomous system number associated with this session + */ + public String getInitialASN() { + return initialASN; + } + + /** + * @return Last user agent of the device from which this user logged in + */ + public String getLastUserAgent() { + return lastUserAgent; + } + + /** + * @return Last IP address from which this user logged in + */ + public String getLastIP() { + return lastIP; + } + + /** + * @return Last autonomous system number from which this user logged in + */ + public String getLastASN() { + return lastASN; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/Session.java b/src/main/java/com/auth0/json/mgmt/users/sessions/Session.java new file mode 100644 index 00000000..ae0fe6c6 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/sessions/Session.java @@ -0,0 +1,104 @@ +package com.auth0.json.mgmt.users.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Date; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Session { + @JsonProperty("id") + private String id; + @JsonProperty("user_id") + private String userId; + @JsonProperty("created_at") + private Date createdAt; + @JsonProperty("updated_at") + private Date updatedAt; + @JsonProperty("authenticated_at") + private Date authenticatedAt; + @JsonProperty("idle_expires_at") + private Date idleExpiresAt; + @JsonProperty("expires_at") + private Date expiresAt; + @JsonProperty("device") + private Device device; + @JsonProperty("clients") + private List clients; + @JsonProperty("authentication") + private Authentication authentication; + + /** + * @return The ID of the session + */ + public String getId() { + return id; + } + + /** + * @return ID of the user which can be used when interacting with other APIs. + */ + public String getUserId() { + return userId; + } + + /** + * + * @return The date and time when the session was created + */ + public Date getCreatedAt() { + return createdAt; + } + + /** + * @return The date and time when the session was last updated + */ + public Date getUpdatedAt() { + return updatedAt; + } + + /** + * @return The date and time when the session was last authenticated + */ + public Date getAuthenticatedAt() { + return authenticatedAt; + } + + /** + * @return The date and time when the session will expire if idle + */ + public Date getIdleExpiresAt() { + return idleExpiresAt; + } + + /** + * @return The date and time when the session will expire + */ + public Date getExpiresAt() { + return expiresAt; + } + + /** + * @return Metadata related to the device used in the session + */ + public Device getDevice() { + return device; + } + + /** + * @return List of client details for the session + */ + public List getClients() { + return clients; + } + + /** + * @return Details about authentication signals obtained during the login flow + */ + public Authentication getAuthentication() { + return authentication; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java b/src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java new file mode 100644 index 00000000..da536451 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java @@ -0,0 +1,44 @@ +package com.auth0.json.mgmt.users.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * This does not extend com.auth0.json.mgmt.Page because the URL only supports "next" and "take" pagination. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class SessionsPage { + @JsonProperty("total") + private Integer total; + + @JsonProperty("next") + private String next; + + @JsonProperty("sessions") + private List sessions; + + /** + * @return the total number of refresh tokens. This is only present when `include_totals` is passed as a query parameter. + */ + public Integer getTotal() { + return total; + } + + /** + * @return the token ID from which to start selection for a new page + */ + public String getNext() { + return next; + } + + /** + * @return the list of Sessions + */ + public List getSessions() { + return sessions; + } +} diff --git a/src/test/java/com/auth0/client/MockServer.java b/src/test/java/com/auth0/client/MockServer.java index 9df874b2..5b162e67 100644 --- a/src/test/java/com/auth0/client/MockServer.java +++ b/src/test/java/com/auth0/client/MockServer.java @@ -78,6 +78,8 @@ public class MockServer { public static final String MGMT_USERS_PAGED_LIST = "src/test/resources/mgmt/users_paged_list.json"; public static final String MGMT_USER_PERMISSIONS_PAGED_LIST = "src/test/resources/mgmt/user_permissions_paged_list.json"; public static final String MGMT_USER_ROLES_PAGED_LIST = "src/test/resources/mgmt/user_roles_paged_list.json"; + public static final String MGMT_USER_REFRESH_TOKENS = "src/test/resources/mgmt/user_refresh_tokens.json"; + public static final String MGMT_USER_SESSIONS = "src/test/resources/mgmt/user_sessions.json"; public static final String MGMT_USER = "src/test/resources/mgmt/user.json"; public static final String MGMT_RECOVERY_CODE = "src/test/resources/mgmt/recovery_code.json"; public static final String MGMT_IDENTITIES_LIST = "src/test/resources/mgmt/identities_list.json"; diff --git a/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java b/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java index 61f519c9..a2556ee5 100644 --- a/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java @@ -4,6 +4,7 @@ import com.auth0.client.mgmt.filter.LogEventFilter; import com.auth0.client.mgmt.filter.PageFilter; import com.auth0.client.mgmt.filter.UserFilter; +import com.auth0.client.mgmt.filter.CheckpointPaginationFilter; import com.auth0.json.mgmt.guardian.Enrollment; import com.auth0.json.mgmt.logevents.LogEvent; import com.auth0.json.mgmt.logevents.LogEventsPage; @@ -17,6 +18,8 @@ import com.auth0.json.mgmt.users.UsersPage; import com.auth0.json.mgmt.users.authenticationmethods.AuthenticationMethod; import com.auth0.json.mgmt.users.authenticationmethods.AuthenticationMethodsPage; +import com.auth0.json.mgmt.users.refreshtokens.RefreshTokensPage; +import com.auth0.json.mgmt.users.sessions.SessionsPage; import com.auth0.net.Request; import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; @@ -1348,4 +1351,158 @@ public void shouldInvalidateRememberedBrowsers() throws Exception { assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/users/userId/multifactor/actions/invalidate-remember-browser")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } + + @Test + public void shouldListRefreshTokensWithoutFilter() throws Exception { + Request request = api.users().listRefreshTokens("1", null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_REFRESH_TOKENS, 200); + RefreshTokensPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/refresh-tokens")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getTokens(), hasSize(2)); + } + + @Test + public void shouldListRefreshTokensWithPage() throws Exception { + CheckpointPaginationFilter filter = new CheckpointPaginationFilter().withFrom("tokenId2").withTake(5); + Request request = api.users().listRefreshTokens("1", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_REFRESH_TOKENS, 200); + RefreshTokensPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/refresh-tokens")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("from", "tokenId2")); + assertThat(recordedRequest, hasQueryParameter("take", "5")); + + assertThat(response, is(notNullValue())); + assertThat(response.getTokens(), hasSize(2)); + } + + @Test + public void shouldListRefreshTokensWithTotal() throws Exception { + CheckpointPaginationFilter filter = new CheckpointPaginationFilter().withTotals(true); + Request request = api.users().listRefreshTokens("1", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_REFRESH_TOKENS, 200); + RefreshTokensPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/refresh-tokens")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); + + assertThat(response, is(notNullValue())); + assertThat(response.getTokens(), hasSize(2)); + assertThat(response.getTotal(), is(11)); + } + + @Test + public void shouldNotDeleteRefreshTokensWithNullUserId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().deleteRefreshTokens(null), + "'user ID' cannot be null!"); + } + + @Test + public void shouldDeleteRefreshTokens() throws Exception { + Request request = api.users().deleteRefreshTokens("1"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1/refresh-tokens")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldListSessionsWithoutFilter() throws Exception { + Request request = api.users().listSessions("1", null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_SESSIONS, 200); + SessionsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/sessions")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getSessions(), hasSize(1)); + } + + @Test + public void shouldListSessionsWithPage() throws Exception { + CheckpointPaginationFilter filter = new CheckpointPaginationFilter().withFrom("sessionId3").withTake(9); + Request request = api.users().listSessions("1", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_SESSIONS, 200); + SessionsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/sessions")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("from", "sessionId3")); + assertThat(recordedRequest, hasQueryParameter("take", "9")); + + assertThat(response, is(notNullValue())); + assertThat(response.getSessions(), hasSize(1)); + } + + @Test + public void shouldListSessionsWithTotal() throws Exception { + CheckpointPaginationFilter filter = new CheckpointPaginationFilter().withTotals(true); + Request request = api.users().listSessions("1", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_SESSIONS, 200); + SessionsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/sessions")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); + + assertThat(response, is(notNullValue())); + assertThat(response.getSessions(), hasSize(1)); + assertThat(response.getTotal(), is(9)); + } + + @Test + public void shouldNotDeleteSessionsWithNullUserId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().deleteRefreshTokens(null), + "'user ID' cannot be null!"); + } + + @Test + public void shouldDeleteSessions() throws Exception { + Request request = api.users().deleteSessions("1"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1/sessions")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } } diff --git a/src/test/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilterTest.java new file mode 100644 index 00000000..69cb4641 --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilterTest.java @@ -0,0 +1,37 @@ +package com.auth0.client.mgmt.filter; + +import org.hamcrest.Matchers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +public class CheckpointPaginationFilterTest { + + private CheckpointPaginationFilter filter; + + @BeforeEach + public void setUp() { + filter = new CheckpointPaginationFilter(); + } + + @Test + public void shouldIncludeTotals() { + CheckpointPaginationFilter instance = filter.withTotals(true); + + assertThat(filter, is(instance)); + assertThat(filter.getAsMap(), is(notNullValue())); + assertThat(filter.getAsMap(), Matchers.hasEntry("include_totals", true)); + } + + @Test + public void shouldIncludeCheckpointParams() { + CheckpointPaginationFilter instance = filter.withFrom("abc123").withTake(2); + + assertThat(filter.getAsMap(), is(notNullValue())); + assertThat(filter.getAsMap(), Matchers.hasEntry("from", "abc123")); + assertThat(filter.getAsMap(), Matchers.hasEntry("take", 2)); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPageTest.java b/src/test/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPageTest.java new file mode 100644 index 00000000..b0e701eb --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPageTest.java @@ -0,0 +1,44 @@ +package com.auth0.json.mgmt.users.refreshtokens; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; + +public class RefreshTokensPageTest extends JsonTest { + private static final String json = "{\n\"tokens\": [\n{\n\"id\": \"tokenId1\",\n\"user_id\": \"userId1\",\n\"created_at\": \"2024-06-26T09:10:26.643Z\",\n\"updated_at\": \"2024-06-26T09:10:27.131Z\",\n\"expires_at\": \"2024-07-03T09:10:26.643Z\",\n\"client_id\": \"clientId1\",\n\"session_id\": \"sessionId1\",\n\"rotating\": false,\n\"resource_servers\": [\n{\n\"audience\": \"https://api.example.com\",\n\"scopes\": [\n\"read:examples\",\n\"write:examples\"\n]\n}\n]\n},\n{\n\"id\": \"tokenId2\",\n\"user_id\": \"userId1\",\n\"created_at\": \"2024-06-26T09:10:26.643Z\",\n\"updated_at\": \"2024-06-26T09:10:27.131Z\",\n\"expires_at\": \"2024-07-03T09:10:26.643Z\",\n\"client_id\": \"clientId2\",\n\"session_id\": \"sessionId2\",\n\"rotating\": true,\n\"resource_servers\": [\n{\n\"audience\": \"https://api.example.com\",\n\"scopes\": [\n\"read:examples\",\n\"write:examples\"\n]\n}\n]\n}\n],\n\"next\": \"token1\"\n}\n"; + private static final String jsonWithTotal = "{\n\"tokens\": [\n{\n\"id\": \"tokenId1\",\n\"user_id\": \"userId1\",\n\"created_at\": \"2024-06-26T09:10:26.643Z\",\n\"updated_at\": \"2024-06-26T09:10:27.131Z\",\n\"expires_at\": \"2024-07-03T09:10:26.643Z\",\n\"client_id\": \"clientId1\",\n\"session_id\": \"sessionId1\",\n\"rotating\": false,\n\"resource_servers\": [\n{\n\"audience\": \"https://api.example.com\",\n\"scopes\": [\n\"read:examples\",\n\"write:examples\"\n]\n}\n]\n},\n{\n\"id\": \"tokenId2\",\n\"user_id\": \"userId1\",\n\"created_at\": \"2024-06-26T09:10:26.643Z\",\n\"updated_at\": \"2024-06-26T09:10:27.131Z\",\n\"expires_at\": \"2024-07-03T09:10:26.643Z\",\n\"client_id\": \"clientId2\",\n\"session_id\": \"sessionId2\",\n\"rotating\": true,\n\"resource_servers\": [\n{\n\"audience\": \"https://api.example.com\",\n\"scopes\": [\n\"read:examples\",\n\"write:examples\"\n]\n}\n]\n}\n],\n\"next\": \"token1\",\n\"total\": 11\n}\n"; + + @Test + public void shouldDeserialize() throws Exception { + RefreshTokensPage page = fromJSON(json, RefreshTokensPage.class); + + assertThat(page.getTotal(), is(nullValue())); + assertThat(page.getNext(), is("token1")); + + assertThat(page.getTokens().size(), is(2)); + assertThat(page.getTokens().get(0).getId(), is("tokenId1")); + assertThat(page.getTokens().get(0).getUserId(), is("userId1")); + assertThat(page.getTokens().get(0).getCreatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getTokens().get(0).getIdleExpiresAt(), is(nullValue())); + assertThat(page.getTokens().get(0).getExpiresAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + assertThat(page.getTokens().get(0).getClientId(), is("clientId1")); + assertThat(page.getTokens().get(0).getSessionId(), is("sessionId1")); + assertThat(page.getTokens().get(0).isRotating(), is(false)); + + assertThat(page.getTokens().get(0).getResourceServers().size(), is(1)); + assertThat(page.getTokens().get(0).getResourceServers().get(0).getAudience(), is("https://api.example.com")); + assertThat(page.getTokens().get(0).getResourceServers().get(0).getScopes().size(), is(2)); + assertThat(page.getTokens().get(0).getResourceServers().get(0).getScopes().get(0), is("read:examples")); + assertThat(page.getTokens().get(0).getResourceServers().get(0).getScopes().get(1), is("write:examples")); + } + + @Test + public void shouldDeserializeWithTotal() throws Exception { + RefreshTokensPage page = fromJSON(jsonWithTotal, RefreshTokensPage.class); + + assertThat(page.getTotal(), is(11)); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/users/sessions/SessionsPageTest.java b/src/test/java/com/auth0/json/mgmt/users/sessions/SessionsPageTest.java new file mode 100644 index 00000000..6fdcf2dc --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/users/sessions/SessionsPageTest.java @@ -0,0 +1,50 @@ +package com.auth0.json.mgmt.users.sessions; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; + +public class SessionsPageTest extends JsonTest { + private static final String json = "{\"sessions\":[{\"id\":\"sessionId1\",\n\"user_id\":\"userId1\",\n\"created_at\":\"2024-06-26T09:10:26.643Z\",\n\"updated_at\":\"2024-06-26T09:10:27.131Z\",\n\"authenticated_at\":\"2024-06-26T09:10:26.643Z\",\n\"authentication\":{\n\"methods\":[\n{\n\"name\":\"pwd\",\n\"timestamp\":\"2024-06-26T09:10:26.643Z\"\n}\n]\n},\n\"idle_expires_at\":\"2024-06-26T09:40:27.131Z\",\n\"expires_at\":\"2024-07-03T09:10:26.643Z\",\n\"device\":{\n\"initial_asn\":\"1234\",\n\"initial_ip\":\"203.0.113.1\",\n\"last_user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n\"last_ip\":\"203.0.113.1\",\n\"last_asn\":\"1234\"\n},\n\"clients\":[\n{\n\"client_id\":\"clientId1\"\n}\n]\n}\n],\n\"next\":\"sessionId1\"\n}\n"; + private static final String jsonWithTotals = "{\"sessions\":[{\"id\":\"sessionId1\",\n\"user_id\":\"userId1\",\n\"created_at\":\"2024-06-26T09:10:26.643Z\",\n\"updated_at\":\"2024-06-26T09:10:27.131Z\",\n\"authenticated_at\":\"2024-06-26T09:10:26.643Z\",\n\"authentication\":{\n\"methods\":[\n{\n\"name\":\"pwd\",\n\"timestamp\":\"2024-06-26T09:10:26.643Z\"\n}\n]\n},\n\"idle_expires_at\":\"2024-06-26T09:40:27.131Z\",\n\"expires_at\":\"2024-07-03T09:10:26.643Z\",\n\"device\":{\n\"initial_asn\":\"1234\",\n\"initial_ip\":\"203.0.113.1\",\n\"last_user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n\"last_ip\":\"203.0.113.1\",\n\"last_asn\":\"1234\"\n},\n\"clients\":[\n{\n\"client_id\":\"clientId1\"\n}\n]\n}\n],\n\"next\":\"sessionId1\",\n\"total\":11\n}\n"; + + @Test + public void shouldDeserialize() throws Exception { + SessionsPage page = fromJSON(json, SessionsPage.class); + + assertThat(page.getTotal(), is(nullValue())); + assertThat(page.getNext(), is("sessionId1")); + assertThat(page.getSessions().size(), is(1)); + assertThat(page.getSessions().get(0).getId(), is("sessionId1")); + assertThat(page.getSessions().get(0).getUserId(), is("userId1")); + assertThat(page.getSessions().get(0).getCreatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getSessions().get(0).getUpdatedAt(), is(parseJSONDate("2024-06-26T09:10:27.131Z"))); + assertThat(page.getSessions().get(0).getAuthenticatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getSessions().get(0).getIdleExpiresAt(), is(parseJSONDate("2024-06-26T09:40:27.131Z"))); + assertThat(page.getSessions().get(0).getExpiresAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + + assertThat(page.getSessions().get(0).getDevice().getInitialASN(), is("1234")); + assertThat(page.getSessions().get(0).getDevice().getInitialIP(), is("203.0.113.1")); + assertThat(page.getSessions().get(0).getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + assertThat(page.getSessions().get(0).getDevice().getLastIP(), is("203.0.113.1")); + assertThat(page.getSessions().get(0).getDevice().getLastASN(), is("1234")); + + assertThat(page.getSessions().get(0).getClients().size(), is(1)); + assertThat(page.getSessions().get(0).getClients().get(0).getClientId(), is("clientId1")); + + assertThat(page.getSessions().get(0).getAuthentication().getMethods().size(), is(1)); + assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getName(), is("pwd")); + assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getTimestamp(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getType(), is(nullValue())); + } + + @Test + public void shouldDeserializeWithTotals() throws Exception { + SessionsPage page = fromJSON(jsonWithTotals, SessionsPage.class); + + assertThat(page.getTotal(), is(11)); + } +} diff --git a/src/test/resources/mgmt/user_refresh_tokens.json b/src/test/resources/mgmt/user_refresh_tokens.json new file mode 100644 index 00000000..c1ed7aa9 --- /dev/null +++ b/src/test/resources/mgmt/user_refresh_tokens.json @@ -0,0 +1,44 @@ +{ + "tokens": [ + { + "id": "tokenId1", + "user_id": "userId1", + "created_at": "2024-06-26T09:10:26.643Z", + "updated_at": "2024-06-26T09:10:27.131Z", + "expires_at": "2024-07-03T09:10:26.643Z", + "client_id": "clientId1", + "session_id": "sessionId1", + "rotating": false, + "resource_servers": [ + { + "audience": "https://api.example.com", + "scopes": [ + "read:examples", + "write:examples" + ] + } + ] + }, + { + "id": "tokenId2", + "user_id": "userId1", + "created_at": "2024-06-26T09:10:26.643Z", + "updated_at": "2024-06-26T09:10:27.131Z", + "expires_at": "2024-07-03T09:10:26.643Z", + "client_id": "clientId2", + "session_id": "sessionId2", + "rotating": true, + "resource_servers": [ + { + "audience": "https://api.example.com", + "scopes": [ + "read:examples", + "write:examples" + ] + } + ] + } + ], + "next": "token1", + "total": 11 +} diff --git a/src/test/resources/mgmt/user_sessions.json b/src/test/resources/mgmt/user_sessions.json new file mode 100644 index 00000000..750b127e --- /dev/null +++ b/src/test/resources/mgmt/user_sessions.json @@ -0,0 +1,35 @@ +{ + "sessions": [ + { + "id": "sessionId1", + "user_id": "userId1", + "created_at": "2024-06-26T09:10:26.643Z", + "updated_at": "2024-06-26T09:10:27.131Z", + "authenticated_at": "2024-06-26T09:10:26.643Z", + "authentication": { + "methods": [ + { + "name": "pwd", + "timestamp": "2024-06-26T09:10:26.643Z" + } + ] + }, + "idle_expires_at": "2024-06-26T09:40:27.131Z", + "expires_at": "2024-07-03T09:10:26.643Z", + "device": { + "initial_asn": "1234", + "initial_ip": "203.0.113.1", + "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_ip": "203.0.113.1", + "last_asn": "1234" + }, + "clients": [ + { + "client_id": "clientId1" + } + ] + } + ], + "next": "sessionId1", + "total": 9 +} From e03801f9556bb198f386a0a6c75b75183c5874eb Mon Sep 17 00:00:00 2001 From: Jak S <191585+jak@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:16:46 +0100 Subject: [PATCH 03/14] Merge branch 'master' into add-user-refresh-tokens From e2e099ce9c9fc9c7a9bae456b86503dd226ba0bc Mon Sep 17 00:00:00 2001 From: Tanya Sinha Date: Mon, 2 Sep 2024 13:20:12 +0530 Subject: [PATCH 04/14] =?UTF-8?q?Changed=20pull=5Frequest=5Ftarget=20to=20?= =?UTF-8?q?pull=5Frequest=20and=20removed=20the=20authorize=E2=80=A6=20(#6?= =?UTF-8?q?60)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/semgrep.yml | 10 +--------- .github/workflows/snyk.yml | 10 +--------- build.gradle | 2 +- 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index fc7d2eeb..202d6af6 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -2,7 +2,7 @@ name: Semgrep on: merge_group: - pull_request_target: + pull_request: types: - opened - synchronize @@ -20,16 +20,8 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} jobs: - authorize: - name: Authorize - environment: ${{ github.actor != 'dependabot[bot]' && github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && 'external' || 'internal' }} - runs-on: ubuntu-latest - steps: - - run: true run: - needs: authorize # Require approval before running on forked pull requests - name: Check for Vulnerabilities runs-on: ubuntu-latest diff --git a/.github/workflows/snyk.yml b/.github/workflows/snyk.yml index 3a4a8709..186ff3f2 100644 --- a/.github/workflows/snyk.yml +++ b/.github/workflows/snyk.yml @@ -3,7 +3,7 @@ name: Snyk on: merge_group: workflow_dispatch: - pull_request_target: + pull_request: types: - opened - synchronize @@ -21,16 +21,8 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} jobs: - authorize: - name: Authorize - environment: ${{ github.actor != 'dependabot[bot]' && github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && 'external' || 'internal' }} - runs-on: ubuntu-latest - steps: - - run: true check: - needs: authorize - name: Check for Vulnerabilities runs-on: ubuntu-latest diff --git a/build.gradle b/build.gradle index c5f9e54e..c91c8fcc 100644 --- a/build.gradle +++ b/build.gradle @@ -85,7 +85,7 @@ dependencies { implementation "com.squareup.okio:okio:3.5.0" implementation "com.squareup.okhttp3:logging-interceptor:${okhttpVersion}" - implementation "com.fasterxml.jackson.core:jackson-databind:2.14.2" + implementation "com.fasterxml.jackson.core:jackson-databind:2.15.0" implementation "com.auth0:java-jwt:4.4.0" implementation "net.jodah:failsafe:2.4.4" From a0b5c6bb00ac175a9be17527f83830b7c1e87d5c Mon Sep 17 00:00:00 2001 From: tanya-sinha_atko Date: Tue, 3 Sep 2024 21:33:12 +0530 Subject: [PATCH 05/14] Added few fields in RefreshToken and Session and modified minor changes --- .../com/auth0/client/mgmt/UsersEntity.java | 8 +-- .../json/mgmt/users/refreshtokens/Device.java | 64 +++++++++++++++++++ .../users/refreshtokens/RefreshToken.java | 18 ++++++ .../refreshtokens/RefreshTokensPage.java | 2 +- .../json/mgmt/users/sessions/Device.java | 9 +++ .../json/mgmt/users/sessions/Session.java | 2 + .../mgmt/users/sessions/SessionsPage.java | 2 +- .../auth0/client/mgmt/UsersEntityTest.java | 9 +-- 8 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/auth0/json/mgmt/users/refreshtokens/Device.java diff --git a/src/main/java/com/auth0/client/mgmt/UsersEntity.java b/src/main/java/com/auth0/client/mgmt/UsersEntity.java index 9ee4bfa6..450069e1 100644 --- a/src/main/java/com/auth0/client/mgmt/UsersEntity.java +++ b/src/main/java/com/auth0/client/mgmt/UsersEntity.java @@ -798,8 +798,8 @@ public Request updateAuthenticationMethodById(String userI * @param filter an optional pagination filter * @return a Request to execute */ - public Request listRefreshTokens(String userId, CheckpointPaginationFilter filter) { - Asserts.assertNotNull(userId, "user id"); + public Request listRefreshTokens(String userId, PageFilter filter) { + Asserts.assertNotNull(userId, "user ID"); HttpUrl.Builder builder = baseUrl .newBuilder() .addPathSegments("api/v2/users") @@ -847,8 +847,8 @@ public Request deleteRefreshTokens(String userId) { * @param filter an optional pagination filter * @return a Request to execute */ - public Request listSessions(String userId, CheckpointPaginationFilter filter) { - Asserts.assertNotNull(userId, "user id"); + public Request listSessions(String userId, PageFilter filter) { + Asserts.assertNotNull(userId, "user ID"); HttpUrl.Builder builder = baseUrl .newBuilder() .addPathSegments("api/v2/users") diff --git a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/Device.java b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/Device.java new file mode 100644 index 00000000..7b2bc23c --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/Device.java @@ -0,0 +1,64 @@ +package com.auth0.json.mgmt.users.refreshtokens; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Device { + @JsonProperty("initial_ip") + private String initialIp; + @JsonProperty("initial_asn") + private String initialAsn; + @JsonProperty("initial_user_agent") + private String initialUserAgent; + @JsonProperty("last_ip") + private String lastIp; + @JsonProperty("last_asn") + private String lastAsn; + @JsonProperty("last_user_agent") + private String lastUserAgent; + + /** + * @return First IP address associated with this session + */ + public String getInitialIp() { + return initialIp; + } + + /** + * @return First autonomous system number associated with this session + */ + public String getInitialAsn() { + return initialAsn; + } + + /** + * @return First user agent associated with this session + */ + public String getInitialUserAgent() { + return initialUserAgent; + } + + /** + * @return Last IP address from which this user logged in + */ + public String getLastIp() { + return lastIp; + } + + /** + * @return Last autonomous system number from which this user logged in + */ + public String getLastAsn() { + return lastAsn; + } + + /** + * @return Last user agent of the device from which this user logged in + */ + public String getLastUserAgent() { + return lastUserAgent; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java index 1551f4dd..23536b88 100644 --- a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java +++ b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java @@ -20,6 +20,8 @@ public class RefreshToken { private Date idleExpiresAt; @JsonProperty("expires_at") private Date expiresAt; + @JsonProperty("device") + private Device device; @JsonProperty("client_id") private String clientId; @JsonProperty("session_id") @@ -28,6 +30,8 @@ public class RefreshToken { private Boolean rotating; @JsonProperty("resource_servers") private List resourceServers; + @JsonProperty("last_exchanged_at") + private Date lastExchangedAt; /** * @return The ID of the refresh token @@ -66,6 +70,13 @@ public Date getExpiresAt() { return expiresAt; } + /** + * @return Device information + */ + public Device getDevice() { + return device; + } + /** * @return ID of the client application granted with this refresh token */ @@ -94,4 +105,11 @@ public Boolean isRotating() { public List getResourceServers() { return resourceServers; } + + /** + * @return The date and time when the refresh token was last exchanged + */ + public Date getLastExchangedAt() { + return lastExchangedAt; + } } diff --git a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java index 224c0b62..06d7fd0e 100644 --- a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java +++ b/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java @@ -7,7 +7,7 @@ import java.util.List; /** - * This does not extend com.auth0.json.mgmt.Page because the URL only supports "next" and "take" pagination. + * Class that represents a page of Refresh Tokens. */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/Device.java b/src/main/java/com/auth0/json/mgmt/users/sessions/Device.java index 1665c6ed..590dc8cc 100644 --- a/src/main/java/com/auth0/json/mgmt/users/sessions/Device.java +++ b/src/main/java/com/auth0/json/mgmt/users/sessions/Device.java @@ -7,6 +7,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(JsonInclude.Include.NON_NULL) public class Device { + @JsonProperty("initial_user_agent") + private String initialUserAgent; @JsonProperty("initial_ip") private String initialIP; @JsonProperty("initial_asn") @@ -18,6 +20,13 @@ public class Device { @JsonProperty("last_asn") private String lastASN; + /** + * @return First user agent associated with this session + */ + public String getInitialUserAgent() { + return initialUserAgent; + } + /** * @return First IP address associated with this session */ diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/Session.java b/src/main/java/com/auth0/json/mgmt/users/sessions/Session.java index ae0fe6c6..f8d4b916 100644 --- a/src/main/java/com/auth0/json/mgmt/users/sessions/Session.java +++ b/src/main/java/com/auth0/json/mgmt/users/sessions/Session.java @@ -24,6 +24,8 @@ public class Session { private Date idleExpiresAt; @JsonProperty("expires_at") private Date expiresAt; + @JsonProperty("last_interacted_at") + private Date lastInteractedAt; @JsonProperty("device") private Device device; @JsonProperty("clients") diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java b/src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java index da536451..8d763ecd 100644 --- a/src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java +++ b/src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java @@ -7,7 +7,7 @@ import java.util.List; /** - * This does not extend com.auth0.json.mgmt.Page because the URL only supports "next" and "take" pagination. + * Class that represents a given Page of Sessions. Related to the {@link com.auth0.client.mgmt.UsersEntity} entity. */ @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java b/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java index a2556ee5..1630ee34 100644 --- a/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java @@ -5,6 +5,7 @@ import com.auth0.client.mgmt.filter.PageFilter; import com.auth0.client.mgmt.filter.UserFilter; import com.auth0.client.mgmt.filter.CheckpointPaginationFilter; +import com.auth0.json.mgmt.Page; import com.auth0.json.mgmt.guardian.Enrollment; import com.auth0.json.mgmt.logevents.LogEvent; import com.auth0.json.mgmt.logevents.LogEventsPage; @@ -1371,7 +1372,7 @@ public void shouldListRefreshTokensWithoutFilter() throws Exception { @Test public void shouldListRefreshTokensWithPage() throws Exception { - CheckpointPaginationFilter filter = new CheckpointPaginationFilter().withFrom("tokenId2").withTake(5); + PageFilter filter = new PageFilter().withFrom("tokenId2").withTake(5); Request request = api.users().listRefreshTokens("1", filter); assertThat(request, is(notNullValue())); @@ -1391,7 +1392,7 @@ public void shouldListRefreshTokensWithPage() throws Exception { @Test public void shouldListRefreshTokensWithTotal() throws Exception { - CheckpointPaginationFilter filter = new CheckpointPaginationFilter().withTotals(true); + PageFilter filter = new PageFilter().withTotals(true); Request request = api.users().listRefreshTokens("1", filter); assertThat(request, is(notNullValue())); @@ -1448,7 +1449,7 @@ public void shouldListSessionsWithoutFilter() throws Exception { @Test public void shouldListSessionsWithPage() throws Exception { - CheckpointPaginationFilter filter = new CheckpointPaginationFilter().withFrom("sessionId3").withTake(9); + PageFilter filter = new PageFilter().withFrom("sessionId3").withTake(9); Request request = api.users().listSessions("1", filter); assertThat(request, is(notNullValue())); @@ -1468,7 +1469,7 @@ public void shouldListSessionsWithPage() throws Exception { @Test public void shouldListSessionsWithTotal() throws Exception { - CheckpointPaginationFilter filter = new CheckpointPaginationFilter().withTotals(true); + PageFilter filter = new PageFilter().withTotals(true); Request request = api.users().listSessions("1", filter); assertThat(request, is(notNullValue())); From 507f8c38834a5c76bb7a46f69472bff15c1d131c Mon Sep 17 00:00:00 2001 From: tanya-sinha_atko Date: Thu, 5 Sep 2024 14:29:23 +0530 Subject: [PATCH 06/14] added support for /session and /refreshTokens API's and updated relevant test cases --- .../com/auth0/client/mgmt/ManagementAPI.java | 16 ++ .../client/mgmt/RefreshTokensEntity.java | 66 +++++++ .../com/auth0/client/mgmt/SessionsEntity.java | 67 +++++++ .../com/auth0/client/mgmt/UsersEntity.java | 4 +- .../filter/CheckpointPaginationFilter.java | 38 ---- .../{users => }/refreshtokens/Device.java | 2 +- .../refreshtokens/RefreshToken.java | 2 +- .../refreshtokens/RefreshTokensPage.java | 2 +- .../refreshtokens/ResourceServer.java | 2 +- .../{users => }/sessions/Authentication.java | 2 +- .../sessions/AuthenticationMethod.java | 2 +- .../mgmt/{users => }/sessions/Client.java | 2 +- .../mgmt/{users => }/sessions/Device.java | 2 +- .../mgmt/{users => }/sessions/Session.java | 2 +- .../{users => }/sessions/SessionsPage.java | 2 +- .../java/com/auth0/client/MockServer.java | 2 + .../client/mgmt/RefreshTokensEntityTest.java | 61 ++++++ .../auth0/client/mgmt/SessionsEntityTest.java | 61 ++++++ .../auth0/client/mgmt/UsersEntityTest.java | 6 +- .../CheckpointPaginationFilterTest.java | 37 ---- .../mgmt/refreshtokens/RefreshTokenTest.java | 86 +++++++++ .../refreshtokens/RefreshTokensPageTest.java | 175 ++++++++++++++++++ .../auth0/json/mgmt/sessions/SessionTest.java | 91 +++++++++ .../json/mgmt/sessions/SessionsPageTest.java | 121 ++++++++++++ .../refreshtokens/RefreshTokensPageTest.java | 44 ----- .../mgmt/users/sessions/SessionsPageTest.java | 50 ----- src/test/resources/mgmt/refresh_token.json | 28 +++ src/test/resources/mgmt/session.json | 30 +++ .../resources/mgmt/user_refresh_tokens.json | 25 ++- src/test/resources/mgmt/user_sessions.json | 1 + 30 files changed, 841 insertions(+), 188 deletions(-) create mode 100644 src/main/java/com/auth0/client/mgmt/RefreshTokensEntity.java create mode 100644 src/main/java/com/auth0/client/mgmt/SessionsEntity.java delete mode 100644 src/main/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilter.java rename src/main/java/com/auth0/json/mgmt/{users => }/refreshtokens/Device.java (97%) rename src/main/java/com/auth0/json/mgmt/{users => }/refreshtokens/RefreshToken.java (98%) rename src/main/java/com/auth0/json/mgmt/{users => }/refreshtokens/RefreshTokensPage.java (95%) rename src/main/java/com/auth0/json/mgmt/{users => }/refreshtokens/ResourceServer.java (93%) rename src/main/java/com/auth0/json/mgmt/{users => }/sessions/Authentication.java (92%) rename src/main/java/com/auth0/json/mgmt/{users => }/sessions/AuthenticationMethod.java (95%) rename src/main/java/com/auth0/json/mgmt/{users => }/sessions/Client.java (91%) rename src/main/java/com/auth0/json/mgmt/{users => }/sessions/Device.java (97%) rename src/main/java/com/auth0/json/mgmt/{users => }/sessions/Session.java (98%) rename src/main/java/com/auth0/json/mgmt/{users => }/sessions/SessionsPage.java (96%) create mode 100644 src/test/java/com/auth0/client/mgmt/RefreshTokensEntityTest.java create mode 100644 src/test/java/com/auth0/client/mgmt/SessionsEntityTest.java delete mode 100644 src/test/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilterTest.java create mode 100644 src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokenTest.java create mode 100644 src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPageTest.java create mode 100644 src/test/java/com/auth0/json/mgmt/sessions/SessionTest.java create mode 100644 src/test/java/com/auth0/json/mgmt/sessions/SessionsPageTest.java delete mode 100644 src/test/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPageTest.java delete mode 100644 src/test/java/com/auth0/json/mgmt/users/sessions/SessionsPageTest.java create mode 100644 src/test/resources/mgmt/refresh_token.json create mode 100644 src/test/resources/mgmt/session.json diff --git a/src/main/java/com/auth0/client/mgmt/ManagementAPI.java b/src/main/java/com/auth0/client/mgmt/ManagementAPI.java index cf7ec088..5ac89afb 100644 --- a/src/main/java/com/auth0/client/mgmt/ManagementAPI.java +++ b/src/main/java/com/auth0/client/mgmt/ManagementAPI.java @@ -364,6 +364,22 @@ public KeysEntity keys() { return new KeysEntity(client, baseUrl, tokenProvider); } + /** + * Getter for the Prompts Entity + * @return the Prompts Entity + */ + public RefreshTokensEntity refreshTokens() { + return new RefreshTokensEntity(client, baseUrl, tokenProvider); + } + + /** + * Getter for the Prompts Entity + * @return the Prompts Entity + */ + public SessionsEntity sessions() { + return new SessionsEntity(client, baseUrl, tokenProvider); + } + /** * Builder for {@link ManagementAPI} API client instances. */ diff --git a/src/main/java/com/auth0/client/mgmt/RefreshTokensEntity.java b/src/main/java/com/auth0/client/mgmt/RefreshTokensEntity.java new file mode 100644 index 00000000..6911aef2 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/RefreshTokensEntity.java @@ -0,0 +1,66 @@ +package com.auth0.client.mgmt; + +import com.auth0.json.mgmt.refreshtokens.RefreshToken; +import com.auth0.net.BaseRequest; +import com.auth0.net.Request; +import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.utils.Asserts; +import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.HttpUrl; + +/** + * Class that provides an implementation of the Refresh Tokens methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/Refresh_Tokens + *

+ * This class is not thread-safe. + * @see ManagementAPI + */ +@SuppressWarnings("WeakerAccess") +public class RefreshTokensEntity extends BaseManagementEntity{ + + RefreshTokensEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); + } + + /** + * Request the refresh token for a given refresh token ID. + * A token with scope {@code read:refresh_tokens} is needed. + * See https://auth0.com/docs/api/management/v2/refresh-tokens/get-refresh-token + * @param refreshTokenId the refresh token ID. + * @return a Request to execute. + */ + public Request get(String refreshTokenId){ + Asserts.assertNotNull(refreshTokenId, "refresh token ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/refresh-tokens") + .addPathSegment(refreshTokenId) + .build() + .toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Delete the refresh token for a given refresh token ID. + * * A token with scope {@code delete:refresh_tokens} is needed. + * See https://auth0.com/docs/api/management/v2/refresh-tokens/delete-refresh-token + * @param refreshTokenId the refresh token ID. + * @return a Request to execute. + */ + public Request delete(String refreshTokenId){ + Asserts.assertNotNull(refreshTokenId, "refresh token ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/refresh-tokens") + .addPathSegment(refreshTokenId) + .build() + .toString(); + + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } +} diff --git a/src/main/java/com/auth0/client/mgmt/SessionsEntity.java b/src/main/java/com/auth0/client/mgmt/SessionsEntity.java new file mode 100644 index 00000000..6ed853ee --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/SessionsEntity.java @@ -0,0 +1,67 @@ +package com.auth0.client.mgmt; + +import com.auth0.json.mgmt.sessions.Session; +import com.auth0.net.BaseRequest; +import com.auth0.net.Request; +import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.utils.Asserts; +import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.HttpUrl; + + +/** + * Class that provides an implementation of the Sessions methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/Sessions + *

+ * This class is not thread-safe. + * @see ManagementAPI + */ +@SuppressWarnings("WeakerAccess") +public class SessionsEntity extends BaseManagementEntity{ + + SessionsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); + } + + /** + * Request the session for a given session ID. + * A token with scope {@code read:sessions} is needed. + * See https://auth0.com/docs/api/management/v2/sessions/get-session + * @param sessionId the session ID. + * @return a Request to execute. + */ + public Request get(String sessionId){ + Asserts.assertNotNull(sessionId, "session ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/sessions") + .addPathSegment(sessionId) + .build() + .toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Delete the session for a given session ID. + * A token with scope {@code delete:sessions} is needed. + * See https://auth0.com/docs/api/management/v2/sessions/delete-session + * @param sessionId the session ID. + * @return a Request to execute. + */ + public Request delete(String sessionId){ + Asserts.assertNotNull(sessionId, "session ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/sessions") + .addPathSegment(sessionId) + .build() + .toString(); + + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } +} diff --git a/src/main/java/com/auth0/client/mgmt/UsersEntity.java b/src/main/java/com/auth0/client/mgmt/UsersEntity.java index 450069e1..ac3e3548 100644 --- a/src/main/java/com/auth0/client/mgmt/UsersEntity.java +++ b/src/main/java/com/auth0/client/mgmt/UsersEntity.java @@ -13,8 +13,8 @@ import com.auth0.json.mgmt.users.RecoveryCode; import com.auth0.json.mgmt.users.User; import com.auth0.json.mgmt.users.UsersPage; -import com.auth0.json.mgmt.users.refreshtokens.RefreshTokensPage; -import com.auth0.json.mgmt.users.sessions.SessionsPage; +import com.auth0.json.mgmt.refreshtokens.RefreshTokensPage; +import com.auth0.json.mgmt.sessions.SessionsPage; import com.auth0.net.EmptyBodyRequest; import com.auth0.net.BaseRequest; import com.auth0.net.Request; diff --git a/src/main/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilter.java b/src/main/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilter.java deleted file mode 100644 index 1f881b7c..00000000 --- a/src/main/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilter.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.auth0.client.mgmt.filter; - -public class CheckpointPaginationFilter extends BaseFilter { - - /** - * Return results inside an object that contains the total result count (true) or as a direct array of results (false, default). - * - * @param includeTotals whether to include or not total result count. - * @return this filter instance - */ - public CheckpointPaginationFilter withTotals(boolean includeTotals) { - parameters.put("include_totals", includeTotals); - return this; - } - - /** - * Optional ID from which to start selection (exclusive). - * - * @param from the ID from which to start selection. This can be obtained from the {@code next} field returned from - * a checkpoint-paginated result. - * @return this filter instance. - */ - public CheckpointPaginationFilter withFrom(String from) { - parameters.put("from", from); - return this; - } - - /** - * Number of results per page. Defaults to 50. - * - * @param take the amount of entries to retrieve per page. - * @return this filter instance. - */ - public CheckpointPaginationFilter withTake(int take) { - parameters.put("take", take); - return this; - } -} diff --git a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/Device.java b/src/main/java/com/auth0/json/mgmt/refreshtokens/Device.java similarity index 97% rename from src/main/java/com/auth0/json/mgmt/users/refreshtokens/Device.java rename to src/main/java/com/auth0/json/mgmt/refreshtokens/Device.java index 7b2bc23c..e83e6133 100644 --- a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/Device.java +++ b/src/main/java/com/auth0/json/mgmt/refreshtokens/Device.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt.users.refreshtokens; +package com.auth0.json.mgmt.refreshtokens; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java b/src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshToken.java similarity index 98% rename from src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java rename to src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshToken.java index 23536b88..2efc36b0 100644 --- a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshToken.java +++ b/src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshToken.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt.users.refreshtokens; +package com.auth0.json.mgmt.refreshtokens; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java b/src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPage.java similarity index 95% rename from src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java rename to src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPage.java index 06d7fd0e..9aea796c 100644 --- a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPage.java +++ b/src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPage.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt.users.refreshtokens; +package com.auth0.json.mgmt.refreshtokens; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/ResourceServer.java b/src/main/java/com/auth0/json/mgmt/refreshtokens/ResourceServer.java similarity index 93% rename from src/main/java/com/auth0/json/mgmt/users/refreshtokens/ResourceServer.java rename to src/main/java/com/auth0/json/mgmt/refreshtokens/ResourceServer.java index b423de41..748b2e1d 100644 --- a/src/main/java/com/auth0/json/mgmt/users/refreshtokens/ResourceServer.java +++ b/src/main/java/com/auth0/json/mgmt/refreshtokens/ResourceServer.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt.users.refreshtokens; +package com.auth0.json.mgmt.refreshtokens; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/Authentication.java b/src/main/java/com/auth0/json/mgmt/sessions/Authentication.java similarity index 92% rename from src/main/java/com/auth0/json/mgmt/users/sessions/Authentication.java rename to src/main/java/com/auth0/json/mgmt/sessions/Authentication.java index dd9ba115..177c1469 100644 --- a/src/main/java/com/auth0/json/mgmt/users/sessions/Authentication.java +++ b/src/main/java/com/auth0/json/mgmt/sessions/Authentication.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt.users.sessions; +package com.auth0.json.mgmt.sessions; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/AuthenticationMethod.java b/src/main/java/com/auth0/json/mgmt/sessions/AuthenticationMethod.java similarity index 95% rename from src/main/java/com/auth0/json/mgmt/users/sessions/AuthenticationMethod.java rename to src/main/java/com/auth0/json/mgmt/sessions/AuthenticationMethod.java index c55634c5..012a29d6 100644 --- a/src/main/java/com/auth0/json/mgmt/users/sessions/AuthenticationMethod.java +++ b/src/main/java/com/auth0/json/mgmt/sessions/AuthenticationMethod.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt.users.sessions; +package com.auth0.json.mgmt.sessions; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/Client.java b/src/main/java/com/auth0/json/mgmt/sessions/Client.java similarity index 91% rename from src/main/java/com/auth0/json/mgmt/users/sessions/Client.java rename to src/main/java/com/auth0/json/mgmt/sessions/Client.java index aa51c6e9..7ac383e6 100644 --- a/src/main/java/com/auth0/json/mgmt/users/sessions/Client.java +++ b/src/main/java/com/auth0/json/mgmt/sessions/Client.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt.users.sessions; +package com.auth0.json.mgmt.sessions; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/Device.java b/src/main/java/com/auth0/json/mgmt/sessions/Device.java similarity index 97% rename from src/main/java/com/auth0/json/mgmt/users/sessions/Device.java rename to src/main/java/com/auth0/json/mgmt/sessions/Device.java index 590dc8cc..cf3fe395 100644 --- a/src/main/java/com/auth0/json/mgmt/users/sessions/Device.java +++ b/src/main/java/com/auth0/json/mgmt/sessions/Device.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt.users.sessions; +package com.auth0.json.mgmt.sessions; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/Session.java b/src/main/java/com/auth0/json/mgmt/sessions/Session.java similarity index 98% rename from src/main/java/com/auth0/json/mgmt/users/sessions/Session.java rename to src/main/java/com/auth0/json/mgmt/sessions/Session.java index f8d4b916..c231770e 100644 --- a/src/main/java/com/auth0/json/mgmt/users/sessions/Session.java +++ b/src/main/java/com/auth0/json/mgmt/sessions/Session.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt.users.sessions; +package com.auth0.json.mgmt.sessions; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java b/src/main/java/com/auth0/json/mgmt/sessions/SessionsPage.java similarity index 96% rename from src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java rename to src/main/java/com/auth0/json/mgmt/sessions/SessionsPage.java index 8d763ecd..10d58e9d 100644 --- a/src/main/java/com/auth0/json/mgmt/users/sessions/SessionsPage.java +++ b/src/main/java/com/auth0/json/mgmt/sessions/SessionsPage.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt.users.sessions; +package com.auth0.json.mgmt.sessions; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/test/java/com/auth0/client/MockServer.java b/src/test/java/com/auth0/client/MockServer.java index 5b162e67..f8ee2189 100644 --- a/src/test/java/com/auth0/client/MockServer.java +++ b/src/test/java/com/auth0/client/MockServer.java @@ -78,6 +78,8 @@ public class MockServer { public static final String MGMT_USERS_PAGED_LIST = "src/test/resources/mgmt/users_paged_list.json"; public static final String MGMT_USER_PERMISSIONS_PAGED_LIST = "src/test/resources/mgmt/user_permissions_paged_list.json"; public static final String MGMT_USER_ROLES_PAGED_LIST = "src/test/resources/mgmt/user_roles_paged_list.json"; + public static final String MGMT_REFRESH_TOKEN = "src/test/resources/mgmt/refresh_token.json"; + public static final String MGMT_SESSION = "src/test/resources/mgmt/session.json"; public static final String MGMT_USER_REFRESH_TOKENS = "src/test/resources/mgmt/user_refresh_tokens.json"; public static final String MGMT_USER_SESSIONS = "src/test/resources/mgmt/user_sessions.json"; public static final String MGMT_USER = "src/test/resources/mgmt/user.json"; diff --git a/src/test/java/com/auth0/client/mgmt/RefreshTokensEntityTest.java b/src/test/java/com/auth0/client/mgmt/RefreshTokensEntityTest.java new file mode 100644 index 00000000..69ef2684 --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/RefreshTokensEntityTest.java @@ -0,0 +1,61 @@ +package com.auth0.client.mgmt; + +import com.auth0.json.mgmt.refreshtokens.RefreshToken; +import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.Test; + +import static com.auth0.AssertsUtil.verifyThrows; +import static com.auth0.client.MockServer.MGMT_REFRESH_TOKEN; +import static com.auth0.client.RecordedRequestMatcher.hasHeader; +import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class RefreshTokensEntityTest extends BaseMgmtEntityTest{ + + @Test + public void shouldThrowOnGetWithNullRefreshTokenId() { + verifyThrows(IllegalArgumentException.class, + () -> api.refreshTokens().get(null), + "'refresh token ID' cannot be null!"); + } + + @Test + public void shouldGetRefreshToken() throws Exception { + Request request = api.refreshTokens().get("refresh_token_ID"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_REFRESH_TOKEN, 200); + RefreshToken response =request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/refresh-tokens/refresh_token_ID")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnDeleteWithNullRefreshTokenId() { + verifyThrows(IllegalArgumentException.class, + () -> api.refreshTokens().delete(null), + "'refresh token ID' cannot be null!"); + } + + @Test + public void shouldDeleteRefreshToken() throws Exception { + Request request = api.refreshTokens().delete("refresh_token_ID"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/refresh-tokens/refresh_token_ID")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } +} diff --git a/src/test/java/com/auth0/client/mgmt/SessionsEntityTest.java b/src/test/java/com/auth0/client/mgmt/SessionsEntityTest.java new file mode 100644 index 00000000..a1e847ff --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/SessionsEntityTest.java @@ -0,0 +1,61 @@ +package com.auth0.client.mgmt; + +import com.auth0.json.mgmt.sessions.Session; +import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.Test; + +import static com.auth0.AssertsUtil.verifyThrows; +import static com.auth0.client.MockServer.MGMT_SESSION; +import static com.auth0.client.RecordedRequestMatcher.hasHeader; +import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class SessionsEntityTest extends BaseMgmtEntityTest{ + @Test + public void getSessionShouldThrowOnNullSessionId() { + verifyThrows(IllegalArgumentException.class, + () -> api.sessions().get(null), + "'session ID' cannot be null!"); + } + + @Test + public void shouldGetSession() throws Exception { + Request request = api.sessions().get("session_ID"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_SESSION, 200); + Session response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/sessions/session_ID")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void deleteSessionShouldThrowOnNullSessionId() { + verifyThrows(IllegalArgumentException.class, + () -> api.sessions().delete(null), + "'session ID' cannot be null!"); + } + + @Test + public void shouldDeleteSession() throws Exception { + Request request = api.sessions().delete("session_ID"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/sessions/session_ID")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + +} diff --git a/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java b/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java index 1630ee34..59da2b86 100644 --- a/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java @@ -4,8 +4,6 @@ import com.auth0.client.mgmt.filter.LogEventFilter; import com.auth0.client.mgmt.filter.PageFilter; import com.auth0.client.mgmt.filter.UserFilter; -import com.auth0.client.mgmt.filter.CheckpointPaginationFilter; -import com.auth0.json.mgmt.Page; import com.auth0.json.mgmt.guardian.Enrollment; import com.auth0.json.mgmt.logevents.LogEvent; import com.auth0.json.mgmt.logevents.LogEventsPage; @@ -19,8 +17,8 @@ import com.auth0.json.mgmt.users.UsersPage; import com.auth0.json.mgmt.users.authenticationmethods.AuthenticationMethod; import com.auth0.json.mgmt.users.authenticationmethods.AuthenticationMethodsPage; -import com.auth0.json.mgmt.users.refreshtokens.RefreshTokensPage; -import com.auth0.json.mgmt.users.sessions.SessionsPage; +import com.auth0.json.mgmt.refreshtokens.RefreshTokensPage; +import com.auth0.json.mgmt.sessions.SessionsPage; import com.auth0.net.Request; import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; diff --git a/src/test/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilterTest.java deleted file mode 100644 index 69cb4641..00000000 --- a/src/test/java/com/auth0/client/mgmt/filter/CheckpointPaginationFilterTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.auth0.client.mgmt.filter; - -import org.hamcrest.Matchers; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -public class CheckpointPaginationFilterTest { - - private CheckpointPaginationFilter filter; - - @BeforeEach - public void setUp() { - filter = new CheckpointPaginationFilter(); - } - - @Test - public void shouldIncludeTotals() { - CheckpointPaginationFilter instance = filter.withTotals(true); - - assertThat(filter, is(instance)); - assertThat(filter.getAsMap(), is(notNullValue())); - assertThat(filter.getAsMap(), Matchers.hasEntry("include_totals", true)); - } - - @Test - public void shouldIncludeCheckpointParams() { - CheckpointPaginationFilter instance = filter.withFrom("abc123").withTake(2); - - assertThat(filter.getAsMap(), is(notNullValue())); - assertThat(filter.getAsMap(), Matchers.hasEntry("from", "abc123")); - assertThat(filter.getAsMap(), Matchers.hasEntry("take", 2)); - } -} diff --git a/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokenTest.java b/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokenTest.java new file mode 100644 index 00000000..35e7d700 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokenTest.java @@ -0,0 +1,86 @@ +package com.auth0.json.mgmt.refreshtokens; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class RefreshTokenTest extends JsonTest { + + private static final String json = "{\n" + + " \"id\": \"tokenId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"idle_expires_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"client_id\": \"clientId1\",\n" + + " \"session_id\": \"sessionId1\",\n" + + " \"rotating\": false,\n" + + " \"resource_servers\": [\n" + + " {\n" + + " \"audience\": \"https://api.example.com\",\n" + + " \"scopes\": [\n" + + " \"read:examples\",\n" + + " \"write:examples\"\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"last_exchanged_at\": \"2024-07-03T09:10:26.643Z\"\n" + + "}"; + + private static final String readOnlyJson = "{\n" + + " \"user_id\": \"userId1\",\n" + + " \"client_id\": \"clientId1\",\n" + + " \"session_id\": \"sessionId1\"\n" + + "}"; + + @Test + public void shouldDeserialize() throws Exception { + RefreshToken refreshToken = fromJSON(json, RefreshToken.class); + assertThat(refreshToken, is(notNullValue())); + + assertThat(refreshToken.getId(), is("tokenId1")); + assertThat(refreshToken.getUserId(), is("userId1")); + assertThat(refreshToken.getCreatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(refreshToken.getIdleExpiresAt(), is(parseJSONDate("2024-06-26T09:10:27.131Z"))); + assertThat(refreshToken.getExpiresAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + + assertThat(refreshToken.getDevice(), is(notNullValue())); + assertThat(refreshToken.getDevice().getInitialAsn(), is("1234")); + assertThat(refreshToken.getDevice().getInitialIp(), is("203.0.113.1")); + assertThat(refreshToken.getDevice().getInitialUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + assertThat(refreshToken.getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + assertThat(refreshToken.getDevice().getLastIp(), is("203.0.113.1")); + assertThat(refreshToken.getDevice().getLastAsn(), is("1234")); + + assertThat(refreshToken.getClientId(), is("clientId1")); + assertThat(refreshToken.getSessionId(), is("sessionId1")); + assertThat(refreshToken.isRotating(), is(false)); + + assertThat(refreshToken.getResourceServers(), is(notNullValue())); + assertThat(refreshToken.getResourceServers().get(0).getAudience(), is("https://api.example.com")); + assertThat(refreshToken.getResourceServers().get(0).getScopes(), is(notNullValue())); + assertThat(refreshToken.getResourceServers().get(0).getScopes().get(0), is("read:examples")); + assertThat(refreshToken.getResourceServers().get(0).getScopes().get(1), is("write:examples")); + + assertThat(refreshToken.getLastExchangedAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + } + + @Test + public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { + RefreshToken refreshToken = fromJSON(readOnlyJson, RefreshToken.class); + assertThat(refreshToken, is(notNullValue())); + assertThat(refreshToken.getUserId(), is("userId1")); + assertThat(refreshToken.getClientId(), is("clientId1")); + assertThat(refreshToken.getSessionId(), is("sessionId1")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPageTest.java b/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPageTest.java new file mode 100644 index 00000000..f86c7df7 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPageTest.java @@ -0,0 +1,175 @@ +package com.auth0.json.mgmt.refreshtokens; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; + +public class RefreshTokensPageTest extends JsonTest { + private static final String json = "{\n" + + " \"tokens\": [\n" + + " {\n" + + " \"id\": \"tokenId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"client_id\": \"clientId1\",\n" + + " \"session_id\": \"sessionId1\",\n" + + " \"rotating\": false,\n" + + " \"resource_servers\": [\n" + + " {\n" + + " \"audience\": \"https://api.example.com\",\n" + + " \"scopes\": [\n" + + " \"read:examples\",\n" + + " \"write:examples\"\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"last_exchanged_at\": \"2024-07-03T09:10:26.643Z\"\n" + + " },\n" + + " {\n" + + " \"id\": \"tokenId2\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"client_id\": \"clientId2\",\n" + + " \"session_id\": \"sessionId2\",\n" + + " \"rotating\": true,\n" + + " \"resource_servers\": [\n" + + " {\n" + + " \"audience\": \"https://api.example.com\",\n" + + " \"scopes\": [\n" + + " \"read:examples\",\n" + + " \"write:examples\"\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"last_exchanged_at\": \"2024-07-03T09:10:26.643Z\"\n" + + " }\n" + + " ],\n" + + " \"next\": \"token1\"\n" + + "}"; + + private static final String jsonWithTotal = "{\n" + + " \"tokens\": [\n" + + " {\n" + + " \"id\": \"tokenId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"client_id\": \"clientId1\",\n" + + " \"session_id\": \"sessionId1\",\n" + + " \"rotating\": false,\n" + + " \"resource_servers\": [\n" + + " {\n" + + " \"audience\": \"https://api.example.com\",\n" + + " \"scopes\": [\n" + + " \"read:examples\",\n" + + " \"write:examples\"\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"last_exchanged_at\": \"2024-07-03T09:10:26.643Z\"\n" + + " },\n" + + " {\n" + + " \"id\": \"tokenId2\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"client_id\": \"clientId2\",\n" + + " \"session_id\": \"sessionId2\",\n" + + " \"rotating\": true,\n" + + " \"resource_servers\": [\n" + + " {\n" + + " \"audience\": \"https://api.example.com\",\n" + + " \"scopes\": [\n" + + " \"read:examples\",\n" + + " \"write:examples\"\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"last_exchanged_at\": \"2024-07-03T09:10:26.643Z\"\n" + + " }\n" + + " ],\n" + + " \"next\": \"token1\",\n" + + " \"total\": 11\n" + + "}"; + @Test + public void shouldDeserialize() throws Exception { + RefreshTokensPage page = fromJSON(json, RefreshTokensPage.class); + + assertThat(page.getTotal(), is(nullValue())); + assertThat(page.getNext(), is("token1")); + + assertThat(page.getTokens().size(), is(2)); + assertThat(page.getTokens().get(0).getId(), is("tokenId1")); + assertThat(page.getTokens().get(0).getUserId(), is("userId1")); + assertThat(page.getTokens().get(0).getCreatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getTokens().get(0).getIdleExpiresAt(), is(nullValue())); + assertThat(page.getTokens().get(0).getExpiresAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + + assertThat(page.getTokens().get(0).getDevice().getInitialIp(), is("203.0.113.1")); + assertThat(page.getTokens().get(0).getDevice().getInitialAsn(), is("1234")); + assertThat(page.getTokens().get(0).getDevice().getInitialUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + assertThat(page.getTokens().get(0).getDevice().getLastIp(), is("203.0.113.1")); + assertThat(page.getTokens().get(0).getDevice().getLastAsn(), is("1234")); + assertThat(page.getTokens().get(0).getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + + assertThat(page.getTokens().get(0).getClientId(), is("clientId1")); + assertThat(page.getTokens().get(0).getSessionId(), is("sessionId1")); + assertThat(page.getTokens().get(0).isRotating(), is(false)); + + assertThat(page.getTokens().get(0).getResourceServers().size(), is(1)); + assertThat(page.getTokens().get(0).getResourceServers().get(0).getAudience(), is("https://api.example.com")); + assertThat(page.getTokens().get(0).getResourceServers().get(0).getScopes().size(), is(2)); + assertThat(page.getTokens().get(0).getResourceServers().get(0).getScopes().get(0), is("read:examples")); + assertThat(page.getTokens().get(0).getResourceServers().get(0).getScopes().get(1), is("write:examples")); + + assertThat(page.getTokens().get(0).getLastExchangedAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + } + + @Test + public void shouldDeserializeWithTotal() throws Exception { + RefreshTokensPage page = fromJSON(jsonWithTotal, RefreshTokensPage.class); + + assertThat(page.getTotal(), is(11)); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/sessions/SessionTest.java b/src/test/java/com/auth0/json/mgmt/sessions/SessionTest.java new file mode 100644 index 00000000..8ed3d2c2 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/sessions/SessionTest.java @@ -0,0 +1,91 @@ +package com.auth0.json.mgmt.sessions; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class SessionTest extends JsonTest { + + private static final String json = "{\n" + + " \"id\": \"sessionId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-09-04T06:41:46.145Z\",\n" + + " \"updated_at\": \"2024-09-04T06:41:46.621Z\",\n" + + " \"authenticated_at\": \"2024-09-04T06:41:46.145Z\",\n" + + " \"authentication\": {\n" + + " \"methods\": [\n" + + " {\n" + + " \"name\": \"federated\",\n" + + " \"timestamp\": \"2024-09-04T06:41:46.145Z\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"idle_expires_at\": \"2024-09-07T06:41:46.622Z\",\n" + + " \"expires_at\": \"2024-09-11T06:41:46.145Z\",\n" + + " \"device\": {\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36\",\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"134.1.15.0\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"134.1.15.0\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"clients\": [\n" + + " {\n" + + " \"client_id\": \"clientId1\"\n" + + " }\n" + + " ]\n" + + "}"; + + private static final String readOnlyJson = "{\n" + + " \"user_id\": \"userId1\",\n" + + " \"clients\": [\n" + + " {\n" + + " \"client_id\": \"clientId1\"\n" + + " }\n" + + " ]\n" + + "}"; + + @Test + public void shouldDeserialize() throws Exception { + Session session = fromJSON(json, Session.class); + + assertThat(session, is(notNullValue())); + assertThat(session.getId(), is("sessionId1")); + assertThat(session.getUserId(), is("userId1")); + assertThat(session.getCreatedAt(), is(parseJSONDate("2024-09-04T06:41:46.145Z"))); + assertThat(session.getUpdatedAt(), is(parseJSONDate("2024-09-04T06:41:46.621Z"))); + assertThat(session.getAuthenticatedAt(), is(parseJSONDate("2024-09-04T06:41:46.145Z"))); + + assertThat(session.getAuthentication().getMethods(), is(notNullValue())); + assertThat(session.getAuthentication().getMethods().get(0).getName(), is("federated")); + assertThat(session.getAuthentication().getMethods().get(0).getTimestamp(), is(parseJSONDate("2024-09-04T06:41:46.145Z"))); + + assertThat(session.getIdleExpiresAt(), is(parseJSONDate("2024-09-07T06:41:46.622Z"))); + assertThat(session.getExpiresAt(), is(parseJSONDate("2024-09-11T06:41:46.145Z"))); + + assertThat(session.getDevice(), is(notNullValue())); + assertThat(session.getDevice().getInitialASN(), is("1234")); + assertThat(session.getDevice().getInitialIP(), is("134.1.15.0")); + assertThat(session.getDevice().getInitialUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")); + assertThat(session.getDevice().getLastASN(), is("1234")); + assertThat(session.getDevice().getLastIP(), is("134.1.15.0")); + assertThat(session.getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")); + + assertThat(session.getClients(), is(notNullValue())); + assertThat(session.getClients().get(0).getClientId(), is("clientId1")); + } + + @Test + public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { + Session session = fromJSON(readOnlyJson, Session.class); + assertThat(session, is(notNullValue())); + assertThat(session.getUserId(), is("userId1")); + assertThat(session.getClients().get(0).getClientId(), is("clientId1")); + } + + +} diff --git a/src/test/java/com/auth0/json/mgmt/sessions/SessionsPageTest.java b/src/test/java/com/auth0/json/mgmt/sessions/SessionsPageTest.java new file mode 100644 index 00000000..12d28899 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/sessions/SessionsPageTest.java @@ -0,0 +1,121 @@ +package com.auth0.json.mgmt.sessions; + +import com.auth0.json.JsonTest; +import com.auth0.json.mgmt.sessions.SessionsPage; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; + +public class SessionsPageTest extends JsonTest { + private static final String json = "{\n" + + " \"sessions\": [\n" + + " {\n" + + " \"id\": \"sessionId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"authenticated_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"authentication\": {\n" + + " \"methods\": [\n" + + " {\n" + + " \"name\": \"pwd\",\n" + + " \"timestamp\": \"2024-06-26T09:10:26.643Z\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"idle_expires_at\": \"2024-06-26T09:40:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"clients\": [\n" + + " {\n" + + " \"client_id\": \"clientId1\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"next\": \"sessionId1\"\n" + + "}"; + private static final String jsonWithTotals = "{\n" + + " \"sessions\": [\n" + + " {\n" + + " \"id\": \"sessionId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"authenticated_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"authentication\": {\n" + + " \"methods\": [\n" + + " {\n" + + " \"name\": \"pwd\",\n" + + " \"timestamp\": \"2024-06-26T09:10:26.643Z\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"idle_expires_at\": \"2024-06-26T09:40:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36\",\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"clients\": [\n" + + " {\n" + + " \"client_id\": \"clientId1\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"next\": \"sessionId1\",\n" + + " \"total\": 11\n" + + "}"; + + @Test + public void shouldDeserialize() throws Exception { + SessionsPage page = fromJSON(json, SessionsPage.class); + + assertThat(page.getTotal(), is(nullValue())); + assertThat(page.getNext(), is("sessionId1")); + assertThat(page.getSessions().size(), is(1)); + assertThat(page.getSessions().get(0).getId(), is("sessionId1")); + assertThat(page.getSessions().get(0).getUserId(), is("userId1")); + assertThat(page.getSessions().get(0).getCreatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getSessions().get(0).getUpdatedAt(), is(parseJSONDate("2024-06-26T09:10:27.131Z"))); + assertThat(page.getSessions().get(0).getAuthenticatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getSessions().get(0).getIdleExpiresAt(), is(parseJSONDate("2024-06-26T09:40:27.131Z"))); + assertThat(page.getSessions().get(0).getExpiresAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + + assertThat(page.getSessions().get(0).getDevice().getInitialASN(), is("1234")); + assertThat(page.getSessions().get(0).getDevice().getInitialIP(), is("203.0.113.1")); + assertThat(page.getSessions().get(0).getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + assertThat(page.getSessions().get(0).getDevice().getLastIP(), is("203.0.113.1")); + assertThat(page.getSessions().get(0).getDevice().getLastASN(), is("1234")); + assertThat(page.getSessions().get(0).getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + + assertThat(page.getSessions().get(0).getClients().size(), is(1)); + assertThat(page.getSessions().get(0).getClients().get(0).getClientId(), is("clientId1")); + + assertThat(page.getSessions().get(0).getAuthentication().getMethods().size(), is(1)); + assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getName(), is("pwd")); + assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getTimestamp(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getType(), is(nullValue())); + } + + @Test + public void shouldDeserializeWithTotals() throws Exception { + SessionsPage page = fromJSON(jsonWithTotals, SessionsPage.class); + + assertThat(page.getTotal(), is(11)); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPageTest.java b/src/test/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPageTest.java deleted file mode 100644 index b0e701eb..00000000 --- a/src/test/java/com/auth0/json/mgmt/users/refreshtokens/RefreshTokensPageTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.auth0.json.mgmt.users.refreshtokens; - -import com.auth0.json.JsonTest; -import org.junit.jupiter.api.Test; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; - -public class RefreshTokensPageTest extends JsonTest { - private static final String json = "{\n\"tokens\": [\n{\n\"id\": \"tokenId1\",\n\"user_id\": \"userId1\",\n\"created_at\": \"2024-06-26T09:10:26.643Z\",\n\"updated_at\": \"2024-06-26T09:10:27.131Z\",\n\"expires_at\": \"2024-07-03T09:10:26.643Z\",\n\"client_id\": \"clientId1\",\n\"session_id\": \"sessionId1\",\n\"rotating\": false,\n\"resource_servers\": [\n{\n\"audience\": \"https://api.example.com\",\n\"scopes\": [\n\"read:examples\",\n\"write:examples\"\n]\n}\n]\n},\n{\n\"id\": \"tokenId2\",\n\"user_id\": \"userId1\",\n\"created_at\": \"2024-06-26T09:10:26.643Z\",\n\"updated_at\": \"2024-06-26T09:10:27.131Z\",\n\"expires_at\": \"2024-07-03T09:10:26.643Z\",\n\"client_id\": \"clientId2\",\n\"session_id\": \"sessionId2\",\n\"rotating\": true,\n\"resource_servers\": [\n{\n\"audience\": \"https://api.example.com\",\n\"scopes\": [\n\"read:examples\",\n\"write:examples\"\n]\n}\n]\n}\n],\n\"next\": \"token1\"\n}\n"; - private static final String jsonWithTotal = "{\n\"tokens\": [\n{\n\"id\": \"tokenId1\",\n\"user_id\": \"userId1\",\n\"created_at\": \"2024-06-26T09:10:26.643Z\",\n\"updated_at\": \"2024-06-26T09:10:27.131Z\",\n\"expires_at\": \"2024-07-03T09:10:26.643Z\",\n\"client_id\": \"clientId1\",\n\"session_id\": \"sessionId1\",\n\"rotating\": false,\n\"resource_servers\": [\n{\n\"audience\": \"https://api.example.com\",\n\"scopes\": [\n\"read:examples\",\n\"write:examples\"\n]\n}\n]\n},\n{\n\"id\": \"tokenId2\",\n\"user_id\": \"userId1\",\n\"created_at\": \"2024-06-26T09:10:26.643Z\",\n\"updated_at\": \"2024-06-26T09:10:27.131Z\",\n\"expires_at\": \"2024-07-03T09:10:26.643Z\",\n\"client_id\": \"clientId2\",\n\"session_id\": \"sessionId2\",\n\"rotating\": true,\n\"resource_servers\": [\n{\n\"audience\": \"https://api.example.com\",\n\"scopes\": [\n\"read:examples\",\n\"write:examples\"\n]\n}\n]\n}\n],\n\"next\": \"token1\",\n\"total\": 11\n}\n"; - - @Test - public void shouldDeserialize() throws Exception { - RefreshTokensPage page = fromJSON(json, RefreshTokensPage.class); - - assertThat(page.getTotal(), is(nullValue())); - assertThat(page.getNext(), is("token1")); - - assertThat(page.getTokens().size(), is(2)); - assertThat(page.getTokens().get(0).getId(), is("tokenId1")); - assertThat(page.getTokens().get(0).getUserId(), is("userId1")); - assertThat(page.getTokens().get(0).getCreatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); - assertThat(page.getTokens().get(0).getIdleExpiresAt(), is(nullValue())); - assertThat(page.getTokens().get(0).getExpiresAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); - assertThat(page.getTokens().get(0).getClientId(), is("clientId1")); - assertThat(page.getTokens().get(0).getSessionId(), is("sessionId1")); - assertThat(page.getTokens().get(0).isRotating(), is(false)); - - assertThat(page.getTokens().get(0).getResourceServers().size(), is(1)); - assertThat(page.getTokens().get(0).getResourceServers().get(0).getAudience(), is("https://api.example.com")); - assertThat(page.getTokens().get(0).getResourceServers().get(0).getScopes().size(), is(2)); - assertThat(page.getTokens().get(0).getResourceServers().get(0).getScopes().get(0), is("read:examples")); - assertThat(page.getTokens().get(0).getResourceServers().get(0).getScopes().get(1), is("write:examples")); - } - - @Test - public void shouldDeserializeWithTotal() throws Exception { - RefreshTokensPage page = fromJSON(jsonWithTotal, RefreshTokensPage.class); - - assertThat(page.getTotal(), is(11)); - } -} diff --git a/src/test/java/com/auth0/json/mgmt/users/sessions/SessionsPageTest.java b/src/test/java/com/auth0/json/mgmt/users/sessions/SessionsPageTest.java deleted file mode 100644 index 6fdcf2dc..00000000 --- a/src/test/java/com/auth0/json/mgmt/users/sessions/SessionsPageTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.auth0.json.mgmt.users.sessions; - -import com.auth0.json.JsonTest; -import org.junit.jupiter.api.Test; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; - -public class SessionsPageTest extends JsonTest { - private static final String json = "{\"sessions\":[{\"id\":\"sessionId1\",\n\"user_id\":\"userId1\",\n\"created_at\":\"2024-06-26T09:10:26.643Z\",\n\"updated_at\":\"2024-06-26T09:10:27.131Z\",\n\"authenticated_at\":\"2024-06-26T09:10:26.643Z\",\n\"authentication\":{\n\"methods\":[\n{\n\"name\":\"pwd\",\n\"timestamp\":\"2024-06-26T09:10:26.643Z\"\n}\n]\n},\n\"idle_expires_at\":\"2024-06-26T09:40:27.131Z\",\n\"expires_at\":\"2024-07-03T09:10:26.643Z\",\n\"device\":{\n\"initial_asn\":\"1234\",\n\"initial_ip\":\"203.0.113.1\",\n\"last_user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n\"last_ip\":\"203.0.113.1\",\n\"last_asn\":\"1234\"\n},\n\"clients\":[\n{\n\"client_id\":\"clientId1\"\n}\n]\n}\n],\n\"next\":\"sessionId1\"\n}\n"; - private static final String jsonWithTotals = "{\"sessions\":[{\"id\":\"sessionId1\",\n\"user_id\":\"userId1\",\n\"created_at\":\"2024-06-26T09:10:26.643Z\",\n\"updated_at\":\"2024-06-26T09:10:27.131Z\",\n\"authenticated_at\":\"2024-06-26T09:10:26.643Z\",\n\"authentication\":{\n\"methods\":[\n{\n\"name\":\"pwd\",\n\"timestamp\":\"2024-06-26T09:10:26.643Z\"\n}\n]\n},\n\"idle_expires_at\":\"2024-06-26T09:40:27.131Z\",\n\"expires_at\":\"2024-07-03T09:10:26.643Z\",\n\"device\":{\n\"initial_asn\":\"1234\",\n\"initial_ip\":\"203.0.113.1\",\n\"last_user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n\"last_ip\":\"203.0.113.1\",\n\"last_asn\":\"1234\"\n},\n\"clients\":[\n{\n\"client_id\":\"clientId1\"\n}\n]\n}\n],\n\"next\":\"sessionId1\",\n\"total\":11\n}\n"; - - @Test - public void shouldDeserialize() throws Exception { - SessionsPage page = fromJSON(json, SessionsPage.class); - - assertThat(page.getTotal(), is(nullValue())); - assertThat(page.getNext(), is("sessionId1")); - assertThat(page.getSessions().size(), is(1)); - assertThat(page.getSessions().get(0).getId(), is("sessionId1")); - assertThat(page.getSessions().get(0).getUserId(), is("userId1")); - assertThat(page.getSessions().get(0).getCreatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); - assertThat(page.getSessions().get(0).getUpdatedAt(), is(parseJSONDate("2024-06-26T09:10:27.131Z"))); - assertThat(page.getSessions().get(0).getAuthenticatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); - assertThat(page.getSessions().get(0).getIdleExpiresAt(), is(parseJSONDate("2024-06-26T09:40:27.131Z"))); - assertThat(page.getSessions().get(0).getExpiresAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); - - assertThat(page.getSessions().get(0).getDevice().getInitialASN(), is("1234")); - assertThat(page.getSessions().get(0).getDevice().getInitialIP(), is("203.0.113.1")); - assertThat(page.getSessions().get(0).getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); - assertThat(page.getSessions().get(0).getDevice().getLastIP(), is("203.0.113.1")); - assertThat(page.getSessions().get(0).getDevice().getLastASN(), is("1234")); - - assertThat(page.getSessions().get(0).getClients().size(), is(1)); - assertThat(page.getSessions().get(0).getClients().get(0).getClientId(), is("clientId1")); - - assertThat(page.getSessions().get(0).getAuthentication().getMethods().size(), is(1)); - assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getName(), is("pwd")); - assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getTimestamp(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); - assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getType(), is(nullValue())); - } - - @Test - public void shouldDeserializeWithTotals() throws Exception { - SessionsPage page = fromJSON(jsonWithTotals, SessionsPage.class); - - assertThat(page.getTotal(), is(11)); - } -} diff --git a/src/test/resources/mgmt/refresh_token.json b/src/test/resources/mgmt/refresh_token.json new file mode 100644 index 00000000..8ea37353 --- /dev/null +++ b/src/test/resources/mgmt/refresh_token.json @@ -0,0 +1,28 @@ +{ + "id": "tokenId1", + "user_id": "userId1", + "created_at": "2024-06-26T09:10:26.643Z", + "idle_expires_at": "2024-06-26T09:10:27.131Z", + "expires_at": "2024-07-03T09:10:26.643Z", + "device": { + "initial_asn": "1234", + "initial_ip": "203.0.113.1", + "initial_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_ip": "203.0.113.1", + "last_asn": "1234" + }, + "client_id": "clientId1", + "session_id": "sessionId1", + "rotating": false, + "resource_servers": [ + { + "audience": "https://api.example.com", + "scopes": [ + "read:examples", + "write:examples" + ] + } + ], + "last_exchanged_at": "2024-07-03T09:10:26.643Z" +} diff --git a/src/test/resources/mgmt/session.json b/src/test/resources/mgmt/session.json new file mode 100644 index 00000000..07251c3c --- /dev/null +++ b/src/test/resources/mgmt/session.json @@ -0,0 +1,30 @@ +{ + "id": "sessionId1", + "user_id": "userId1", + "created_at": "2024-09-04T06:41:46.145Z", + "updated_at": "2024-09-04T06:41:46.621Z", + "authenticated_at": "2024-09-04T06:41:46.145Z", + "authentication": { + "methods": [ + { + "name": "federated", + "timestamp": "2024-09-04T06:41:46.145Z" + } + ] + }, + "idle_expires_at": "2024-09-07T06:41:46.622Z", + "expires_at": "2024-09-11T06:41:46.145Z", + "device": { + "initial_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", + "initial_asn": "1234", + "initial_ip": "134.1.15.0", + "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", + "last_ip": "134.1.15.0", + "last_asn": "1234" + }, + "clients": [ + { + "client_id": "clientId1" + } + ] +} diff --git a/src/test/resources/mgmt/user_refresh_tokens.json b/src/test/resources/mgmt/user_refresh_tokens.json index c1ed7aa9..18c77eb6 100644 --- a/src/test/resources/mgmt/user_refresh_tokens.json +++ b/src/test/resources/mgmt/user_refresh_tokens.json @@ -4,8 +4,16 @@ "id": "tokenId1", "user_id": "userId1", "created_at": "2024-06-26T09:10:26.643Z", - "updated_at": "2024-06-26T09:10:27.131Z", + "idle_expires_at": "2024-06-26T09:10:27.131Z", "expires_at": "2024-07-03T09:10:26.643Z", + "device": { + "initial_asn": "1234", + "initial_ip": "203.0.113.1", + "initial_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_ip": "203.0.113.1", + "last_asn": "1234" + }, "client_id": "clientId1", "session_id": "sessionId1", "rotating": false, @@ -17,14 +25,24 @@ "write:examples" ] } - ] + ], + "last_exchanged_at": "2024-07-03T09:10:26.643Z" }, { "id": "tokenId2", "user_id": "userId1", "created_at": "2024-06-26T09:10:26.643Z", "updated_at": "2024-06-26T09:10:27.131Z", + "idle_expires_at": "2024-06-26T09:10:27.131Z", "expires_at": "2024-07-03T09:10:26.643Z", + "device": { + "initial_asn": "1234", + "initial_ip": "203.0.113.1", + "initial_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_ip": "203.0.113.1", + "last_asn": "1234" + }, "client_id": "clientId2", "session_id": "sessionId2", "rotating": true, @@ -36,7 +54,8 @@ "write:examples" ] } - ] + ], + "last_exchanged_at": "2024-07-03T09:10:26.643Z" } ], "next": "token1", diff --git a/src/test/resources/mgmt/user_sessions.json b/src/test/resources/mgmt/user_sessions.json index 750b127e..71c9b754 100644 --- a/src/test/resources/mgmt/user_sessions.json +++ b/src/test/resources/mgmt/user_sessions.json @@ -17,6 +17,7 @@ "idle_expires_at": "2024-06-26T09:40:27.131Z", "expires_at": "2024-07-03T09:10:26.643Z", "device": { + "initial_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", "initial_asn": "1234", "initial_ip": "203.0.113.1", "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", From 35195d5ee7f6fd22913421616ebde2f69f5fa037 Mon Sep 17 00:00:00 2001 From: tanya-sinha_atko Date: Fri, 6 Sep 2024 14:03:16 +0530 Subject: [PATCH 07/14] Updated javadoc to correctly state the entity type --- src/main/java/com/auth0/client/mgmt/ManagementAPI.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/auth0/client/mgmt/ManagementAPI.java b/src/main/java/com/auth0/client/mgmt/ManagementAPI.java index 5ac89afb..acffaeb3 100644 --- a/src/main/java/com/auth0/client/mgmt/ManagementAPI.java +++ b/src/main/java/com/auth0/client/mgmt/ManagementAPI.java @@ -365,16 +365,16 @@ public KeysEntity keys() { } /** - * Getter for the Prompts Entity - * @return the Prompts Entity + * Getter for the RefreshTokens Entity + * @return the RefreshTokens Entity */ public RefreshTokensEntity refreshTokens() { return new RefreshTokensEntity(client, baseUrl, tokenProvider); } /** - * Getter for the Prompts Entity - * @return the Prompts Entity + * Getter for the Sessions Entity + * @return the Sessions Entity */ public SessionsEntity sessions() { return new SessionsEntity(client, baseUrl, tokenProvider); From 0da62969324cb7b1dd1ea698612fd5569a0342df Mon Sep 17 00:00:00 2001 From: tanya-sinha_atko Date: Mon, 9 Sep 2024 17:32:15 +0530 Subject: [PATCH 08/14] updated workflow secrets to use ossr-token --- .github/actions/maven-publish/action.yml | 6 +++--- .github/workflows/java-release.yml | 4 ++-- .github/workflows/release.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/maven-publish/action.yml b/.github/actions/maven-publish/action.yml index ee477061..2152527e 100644 --- a/.github/actions/maven-publish/action.yml +++ b/.github/actions/maven-publish/action.yml @@ -3,7 +3,7 @@ name: Publish release to Java inputs: ossr-username: required: true - ossr-password: + ossr-token: required: true signing-key: required: true @@ -36,9 +36,9 @@ runs: - name: Publish Java shell: bash if: inputs.is-android == 'false' - run: ./gradlew clean assemble sign publishMavenJavaPublicationToMavenRepository -PisSnapshot=false -Pversion="${{ inputs.version }}" -PossrhUsername="${{ inputs.ossr-username }}" -PossrhPassword="${{ inputs.ossr-password }}" -PsigningKey="${{ inputs.signing-key }}" -PsigningPassword="${{ inputs.signing-password }}" + run: ./gradlew clean assemble sign publishMavenJavaPublicationToMavenRepository -PisSnapshot=false -Pversion="${{ inputs.version }}" -PossrhUsername="${{ inputs.ossr-username }}" -PossrhPassword="${{ inputs.ossr-token }}" -PsigningKey="${{ inputs.signing-key }}" -PsigningPassword="${{ inputs.signing-password }}" - name: Publish Android shell: bash if: inputs.is-android == 'true' - run: ./gradlew clean assemble sign publishAndroidLibraryPublicationToMavenRepository -PisSnapshot=false -Pversion="${{ inputs.version }}" -PossrhUsername="${{ inputs.ossr-username }}" -PossrhPassword="${{ inputs.ossr-password }}" -PsigningKey="${{ inputs.signing-key }}" -PsigningPassword="${{ inputs.signing-password }}" + run: ./gradlew clean assemble sign publishAndroidLibraryPublicationToMavenRepository -PisSnapshot=false -Pversion="${{ inputs.version }}" -PossrhUsername="${{ inputs.ossr-username }}" -PossrhPassword="${{ inputs.ossr-token }}" -PsigningKey="${{ inputs.signing-key }}" -PsigningPassword="${{ inputs.signing-password }}" diff --git a/.github/workflows/java-release.yml b/.github/workflows/java-release.yml index 3f81eb14..6795ffa0 100644 --- a/.github/workflows/java-release.yml +++ b/.github/workflows/java-release.yml @@ -12,7 +12,7 @@ on: secrets: ossr-username: required: true - ossr-password: + ossr-token: required: true signing-key: required: true @@ -73,7 +73,7 @@ jobs: is-android: ${{ inputs.is-android }} version: ${{ steps.get_version.outputs.version }} ossr-username: ${{ secrets.ossr-username }} - ossr-password: ${{ secrets.ossr-password }} + ossr-token: ${{ secrets.ossr-token }} signing-key: ${{ secrets.signing-key }} signing-password: ${{ secrets.signing-password }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 63482cca..17648ff4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: is-android: false secrets: ossr-username: ${{ secrets.OSSR_USERNAME }} - ossr-password: ${{ secrets.OSSR_PASSWORD }} + ossr-token: ${{ secrets.OSSR_TOKEN }} signing-key: ${{ secrets.SIGNING_KEY }} signing-password: ${{ secrets.SIGNING_PASSWORD }} github-token: ${{ secrets.GITHUB_TOKEN }} From 51a8f82e3e3f005bd150be16cb54fb37c8ca2ac8 Mon Sep 17 00:00:00 2001 From: tanya-sinha_atko Date: Mon, 9 Sep 2024 18:34:45 +0530 Subject: [PATCH 09/14] updated action.yml file --- .github/actions/maven-publish/action.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/actions/maven-publish/action.yml b/.github/actions/maven-publish/action.yml index 2152527e..33336593 100644 --- a/.github/actions/maven-publish/action.yml +++ b/.github/actions/maven-publish/action.yml @@ -33,12 +33,11 @@ runs: - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 # pin@1.1.0 - - name: Publish Java + - name: Publish Android/Java Packages to Maven shell: bash - if: inputs.is-android == 'false' - run: ./gradlew clean assemble sign publishMavenJavaPublicationToMavenRepository -PisSnapshot=false -Pversion="${{ inputs.version }}" -PossrhUsername="${{ inputs.ossr-username }}" -PossrhPassword="${{ inputs.ossr-token }}" -PsigningKey="${{ inputs.signing-key }}" -PsigningPassword="${{ inputs.signing-password }}" - - - name: Publish Android - shell: bash - if: inputs.is-android == 'true' - run: ./gradlew clean assemble sign publishAndroidLibraryPublicationToMavenRepository -PisSnapshot=false -Pversion="${{ inputs.version }}" -PossrhUsername="${{ inputs.ossr-username }}" -PossrhPassword="${{ inputs.ossr-token }}" -PsigningKey="${{ inputs.signing-key }}" -PsigningPassword="${{ inputs.signing-password }}" + run: ./gradlew publish -PisSnapshot=false --stacktrace + env: + MAVEN_USERNAME: ${{ inputs.ossr-username }} + MAVEN_PASSWORD: ${{ inputs.ossr-token }} + SIGNING_KEY: ${{ inputs.signing-key}} + SIGNING_PASSWORD: ${{ inputs.signing-password}} From 34b83534d996b08f0df352be54789ce659831f30 Mon Sep 17 00:00:00 2001 From: Tanya Sinha Date: Wed, 11 Sep 2024 18:27:07 +0530 Subject: [PATCH 10/14] Release 2.13.0 (#663) --- .version | 2 +- CHANGELOG.md | 6 ++++++ README.md | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.version b/.version index d8b69897..fb2c0766 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.12.0 +2.13.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index f255a77a..f9a6f400 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## [2.13.0](https://github.com/auth0/auth0-java/tree/2.13.0) (2024-09-11) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.12.0...2.13.0) + +**Added** +- Add sessions and refresh tokens to Users Management API [\#661](https://github.com/auth0/auth0-java/pull/661) ([tanya732](https://github.com/tanya732)) + ## [2.12.0](https://github.com/auth0/auth0-java/tree/2.12.0) (2024-05-29) [Full Changelog](https://github.com/auth0/auth0-java/compare/2.11.0...2.12.0) diff --git a/README.md b/README.md index 0b52bb87..dc686268 100644 --- a/README.md +++ b/README.md @@ -34,14 +34,14 @@ Add the dependency via Maven: com.auth0 auth0 - 2.12.0 + 2.13.0 ``` or Gradle: ```gradle -implementation 'com.auth0:auth0:2.12.0' +implementation 'com.auth0:auth0:2.13.0' ``` ### Configure the SDK From 8671a1df93965bdcf49cf86375e950434e6458e0 Mon Sep 17 00:00:00 2001 From: Tanya Sinha Date: Fri, 20 Sep 2024 17:20:05 +0530 Subject: [PATCH 11/14] Fix maven release changes (#665) --- .github/actions/maven-publish/action.yml | 9 +- .github/workflows/java-release.yml | 6 +- build.gradle | 107 ++++++++++++++++------ gradle.properties | 21 +++++ gradle/maven-publish.gradle | 111 +++++++++++++++++++++++ gradle/versioning.gradle | 17 ++++ settings.gradle | 3 - 7 files changed, 230 insertions(+), 44 deletions(-) create mode 100644 gradle.properties create mode 100644 gradle/maven-publish.gradle create mode 100644 gradle/versioning.gradle diff --git a/.github/actions/maven-publish/action.yml b/.github/actions/maven-publish/action.yml index 33336593..2e0c5412 100644 --- a/.github/actions/maven-publish/action.yml +++ b/.github/actions/maven-publish/action.yml @@ -1,6 +1,8 @@ name: Publish release to Java inputs: + java-version: + required: true ossr-username: required: true ossr-token: @@ -9,12 +11,7 @@ inputs: required: true signing-password: required: true - java-version: - required: true - is-android: - required: true - version: - required: true + runs: using: composite diff --git a/.github/workflows/java-release.yml b/.github/workflows/java-release.yml index 6795ffa0..cc38e928 100644 --- a/.github/workflows/java-release.yml +++ b/.github/workflows/java-release.yml @@ -6,9 +6,7 @@ on: java-version: required: true type: string - is-android: - required: true - type: string + secrets: ossr-username: required: true @@ -70,8 +68,6 @@ jobs: - uses: ./.github/actions/maven-publish with: java-version: ${{ inputs.java-version }} - is-android: ${{ inputs.is-android }} - version: ${{ steps.get_version.outputs.version }} ossr-username: ${{ secrets.ossr-username }} ossr-token: ${{ secrets.ossr-token }} signing-key: ${{ secrets.signing-key }} diff --git a/build.gradle b/build.gradle index c91c8fcc..21a25440 100644 --- a/build.gradle +++ b/build.gradle @@ -1,43 +1,30 @@ +buildscript { + repositories { + jcenter() + } + + dependencies { + // https://github.com/melix/japicmp-gradle-plugin/issues/36 + classpath 'com.google.guava:guava:31.1-jre' + } +} + + plugins { id 'java' id 'jacoco' - id 'com.auth0.gradle.oss-library.java' + id 'me.champeau.gradle.japicmp' version '0.2.9' } repositories { mavenCentral() } -group = 'com.auth0' -logger.lifecycle("Using version ${version} for ${name} group $group") - -def signingKey = findProperty('signingKey') -def signingKeyPwd = findProperty('signingPassword') - -oss { - name 'auth0' - repository 'auth0-java' - organization 'auth0' - description 'Java client library for the Auth0 platform.' - baselineCompareVersion '2.0.0' - testInJavaVersions = [8, 11, 17] - skipAssertSigningConfiguration true - - developers { - auth0 { - displayName = 'Auth0' - email = 'oss@auth0.com' - } - lbalmaceda { - displayName = 'Luciano Balmaceda' - email = 'luciano.balmaceda@auth0.com' - } - } -} +apply from: rootProject.file('gradle/versioning.gradle') -signing { - useInMemoryPgpKeys(signingKey, signingKeyPwd) -} +version = getVersionFromFile() +group = GROUP +logger.lifecycle("Using version ${version} for ${name} group $group") jacocoTestReport { reports { @@ -63,6 +50,61 @@ compileTestJava { options.compilerArgs << "-Xlint:deprecation" << "-Werror" } +import me.champeau.gradle.japicmp.JapicmpTask + +project.afterEvaluate { + + def versions = project.ext.testInJavaVersions + for (pluginJavaTestVersion in versions) { + def taskName = "testInJava-${pluginJavaTestVersion}" + tasks.register(taskName, Test) { + def versionToUse = taskName.split("-").getAt(1) as Integer + description = "Runs unit tests on Java version ${versionToUse}." + project.logger.quiet("Test will be running in ${versionToUse}") + group = 'verification' + javaLauncher.set(javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(versionToUse) + }) + shouldRunAfter(tasks.named('test')) + } + tasks.named('check') { + dependsOn(taskName) + } + } + + project.configure(project) { + def baselineVersion = project.ext.baselineCompareVersion + task('apiDiff', type: JapicmpTask, dependsOn: 'jar') { + oldClasspath = files(getBaselineJar(project, baselineVersion)) + newClasspath = files(jar.archiveFile) + onlyModified = true + failOnModification = true + ignoreMissingClasses = true + htmlOutputFile = file("$buildDir/reports/apiDiff/apiDiff.html") + txtOutputFile = file("$buildDir/reports/apiDiff/apiDiff.txt") + doLast { + project.logger.quiet("Comparing against baseline version ${baselineVersion}") + } + } + } +} + +private static File getBaselineJar(Project project, String baselineVersion) { + // Use detached configuration: https://github.com/square/okhttp/blob/master/build.gradle#L270 + def group = project.group + try { + def baseline = "${project.group}:${project.name}:$baselineVersion" + project.group = 'virtual_group_for_japicmp' + def dependency = project.dependencies.create(baseline + "@jar") + return project.configurations.detachedConfiguration(dependency).files.find { + it.name == "${project.name}-${baselineVersion}.jar" + } + } finally { + project.group = group + } +} + + test { testLogging { events "skipped", "failed" @@ -75,6 +117,9 @@ ext { okhttpVersion = '4.11.0' hamcrestVersion = '2.2' jupiterVersion = '5.9.3' + + baselineCompareVersion = '2.0.0' + testInJavaVersions = [8, 11, 17, 21] } dependencies { @@ -105,3 +150,5 @@ dependencies { } } } + +apply from: rootProject.file('gradle/maven-publish.gradle') diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..69714a96 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,21 @@ +GROUP=com.auth0 +POM_ARTIFACT_ID=auth0 +VERSION_NAME=2.12.0 + +POM_NAME=auth0-java +POM_DESCRIPTION=Java client library for the Auth0 platform +POM_PACKAGING=jar + +POM_URL=https://github.com/auth0/auth0-java +POM_SCM_URL=https://github.com/auth0/auth0-java + +POM_SCM_CONNECTION=scm:git:https://github.com/auth0/auth0-java.git +POM_SCM_DEV_CONNECTION=scm:git:https://github.com/auth0/auth0-java.git + +POM_LICENCE_NAME=The MIT License (MIT) +POM_LICENCE_URL=https://raw.githubusercontent.com/auth0/auth0-java/master/LICENSE +POM_LICENCE_DIST=repo + +POM_DEVELOPER_ID=auth0 +POM_DEVELOPER_NAME=Auth0 +POM_DEVELOPER_EMAIL=oss@auth0.com diff --git a/gradle/maven-publish.gradle b/gradle/maven-publish.gradle new file mode 100644 index 00000000..beb5f464 --- /dev/null +++ b/gradle/maven-publish.gradle @@ -0,0 +1,111 @@ +apply plugin: 'maven-publish' +apply plugin: 'signing' + +task('sourcesJar', type: Jar, dependsOn: classes) { + archiveClassifier = 'sources' + from sourceSets.main.allSource +} + +task('javadocJar', type: Jar, dependsOn: javadoc) { + archiveClassifier = 'javadoc' + from javadoc.getDestinationDir() +} +tasks.withType(Javadoc).configureEach { + javadocTool = javaToolchains.javadocToolFor { + // Use latest JDK for javadoc generation + languageVersion = JavaLanguageVersion.of(17) + } +} + +javadoc { + // Specify the Java version that the project will use + options.addStringOption('-release', "8") +} +artifacts { + archives sourcesJar, javadocJar +} + + +final releaseRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" +final snapshotRepositoryUrl = "https://oss.sonatype.org/content/repositories/snapshots/" + +publishing { + publications { + mavenJava(MavenPublication) { + + groupId = GROUP + artifactId = POM_ARTIFACT_ID + version = getVersionName() + + artifact("$buildDir/libs/${project.name}-${version}.jar") + artifact sourcesJar + artifact javadocJar + + pom { + name = POM_NAME + packaging = POM_PACKAGING + description = POM_DESCRIPTION + url = POM_URL + + licenses { + license { + name = POM_LICENCE_NAME + url = POM_LICENCE_URL + distribution = POM_LICENCE_DIST + } + } + + developers { + developer { + id = POM_DEVELOPER_ID + name = POM_DEVELOPER_NAME + email = POM_DEVELOPER_EMAIL + } + } + + scm { + url = POM_SCM_URL + connection = POM_SCM_CONNECTION + developerConnection = POM_SCM_DEV_CONNECTION + } + + pom.withXml { + def dependenciesNode = asNode().appendNode('dependencies') + + project.configurations.implementation.allDependencies.each { + def dependencyNode = dependenciesNode.appendNode('dependency') + dependencyNode.appendNode('groupId', it.group) + dependencyNode.appendNode('artifactId', it.name) + dependencyNode.appendNode('version', it.version) + } + } + } + } + } + repositories { + maven { + name = "sonatype" + url = version.endsWith('SNAPSHOT') ? snapshotRepositoryUrl : releaseRepositoryUrl + credentials { + username = System.getenv("MAVEN_USERNAME") + password = System.getenv("MAVEN_PASSWORD") + } + } + } +} + +signing { + def signingKey = System.getenv("SIGNING_KEY") + def signingPassword = System.getenv("SIGNING_PASSWORD") + useInMemoryPgpKeys(signingKey, signingPassword) + + sign publishing.publications.mavenJava +} + +javadoc { + if(JavaVersion.current().isJava9Compatible()) { + options.addBooleanOption('html5', true) + } +} + + diff --git a/gradle/versioning.gradle b/gradle/versioning.gradle new file mode 100644 index 00000000..9a8dae58 --- /dev/null +++ b/gradle/versioning.gradle @@ -0,0 +1,17 @@ +def getVersionFromFile() { + def versionFile = rootProject.file('.version') + return versionFile.text.readLines().first().trim() +} + +def isSnapshot() { + return hasProperty('isSnapshot') ? isSnapshot.toBoolean() : true +} + +def getVersionName() { + return isSnapshot() ? project.version+"-SNAPSHOT" : project.version +} + +ext { + getVersionName = this.&getVersionName + getVersionFromFile = this.&getVersionFromFile +} diff --git a/settings.gradle b/settings.gradle index ed6821be..a32c80c4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,9 +2,6 @@ pluginManagement { repositories { gradlePluginPortal() } - plugins { - id 'com.auth0.gradle.oss-library.java' version '0.18.0' - } } rootProject.name = 'auth0' From 0bb7cba9b529441b1fcbadf356216d8c0728f07c Mon Sep 17 00:00:00 2001 From: Tanya Sinha Date: Fri, 20 Sep 2024 17:40:40 +0530 Subject: [PATCH 12/14] Updated release.yml workflow (#666) --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 17648ff4..715a0bc8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,6 @@ jobs: uses: ./.github/workflows/java-release.yml with: java-version: 8.0.382-tem - is-android: false secrets: ossr-username: ${{ secrets.OSSR_USERNAME }} ossr-token: ${{ secrets.OSSR_TOKEN }} From ae24b7abfe68d347beac0c183aabed71a56ca759 Mon Sep 17 00:00:00 2001 From: Tanya Sinha Date: Mon, 23 Sep 2024 11:03:43 +0530 Subject: [PATCH 13/14] Updated gradle config (#667) --- gradle/maven-publish.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gradle/maven-publish.gradle b/gradle/maven-publish.gradle index beb5f464..bec9fc5a 100644 --- a/gradle/maven-publish.gradle +++ b/gradle/maven-publish.gradle @@ -108,4 +108,8 @@ javadoc { } } +tasks.named('publish').configure { + dependsOn tasks.named('assemble') +} + From f6df9ce28e7e81a7a97a1a51231b5bec5a6c78b2 Mon Sep 17 00:00:00 2001 From: Tanya Sinha Date: Tue, 1 Oct 2024 12:51:03 +0530 Subject: [PATCH 14/14] Added support for HRI phase 2 changes (#668) --- .../com/auth0/json/mgmt/client/Client.java | 17 ++++++ .../resourceserver/ProofOfPossession.java | 54 +++++++++++++++++++ .../mgmt/resourceserver/ResourceServer.java | 17 ++++++ .../auth0/json/mgmt/ResourceServerTest.java | 7 +++ .../auth0/json/mgmt/client/ClientTest.java | 5 ++ src/test/resources/mgmt/client.json | 3 +- src/test/resources/mgmt/resource_server.json | 4 ++ 7 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/auth0/json/mgmt/resourceserver/ProofOfPossession.java diff --git a/src/main/java/com/auth0/json/mgmt/client/Client.java b/src/main/java/com/auth0/json/mgmt/client/Client.java index 5fa11169..99ffeefa 100644 --- a/src/main/java/com/auth0/json/mgmt/client/Client.java +++ b/src/main/java/com/auth0/json/mgmt/client/Client.java @@ -100,6 +100,8 @@ public class Client { private SignedRequest signedRequest; @JsonProperty("compliance_level") private String complianceLevel; + @JsonProperty("require_proof_of_possession") + private Boolean requireProofOfPossession; /** * Getter for the name of the tenant this client belongs to. @@ -872,5 +874,20 @@ public String getComplianceLevel() { public void setComplianceLevel(String complianceLevel) { this.complianceLevel = complianceLevel; } + + /** + * @return the value of the {@code require_proof_of_possession} field + */ + public Boolean getRequireProofOfPossession() { + return requireProofOfPossession; + } + + /** + * Sets the value of the {@code require_proof_of_possession} field + * @param requireProofOfPossession the value of the {@code require_proof_of_possession} field + */ + public void setRequireProofOfPossession(Boolean requireProofOfPossession) { + this.requireProofOfPossession = requireProofOfPossession; + } } diff --git a/src/main/java/com/auth0/json/mgmt/resourceserver/ProofOfPossession.java b/src/main/java/com/auth0/json/mgmt/resourceserver/ProofOfPossession.java new file mode 100644 index 00000000..5c7be6eb --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/resourceserver/ProofOfPossession.java @@ -0,0 +1,54 @@ +package com.auth0.json.mgmt.resourceserver; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ProofOfPossession { + + @JsonProperty("mechanism") + private String mechanism; + @JsonProperty("required") + private Boolean required; + + @JsonCreator + public ProofOfPossession(@JsonProperty("mechanism") String mechanism, @JsonProperty("required") Boolean required) { + this.mechanism = mechanism; + this.required = required; + } + + /** + * Getter for the mechanism of the Proof of Possession. + * @return the mechanism of the Proof of Possession. + */ + public String getMechanism() { + return mechanism; + } + + /** + * Setter for the mechanism of the Proof of Possession. + * @param mechanism the mechanism of the Proof of Possession. + */ + public void setMechanism(String mechanism) { + this.mechanism = mechanism; + } + + /** + * Getter for the required flag of the Proof of Possession. + * @return the required flag of the Proof of Possession. + */ + public Boolean getRequired() { + return required; + } + + /** + * Setter for the required flag of the Proof of Possession. + * @param required the required flag of the Proof of Possession. + */ + public void setRequired(Boolean required) { + this.required = required; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServer.java b/src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServer.java index 6161eb3e..0c80f5c0 100644 --- a/src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServer.java +++ b/src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServer.java @@ -45,6 +45,8 @@ public class ResourceServer { private List authorizationDetails; @JsonProperty("token_encryption") private TokenEncryption tokenEncryption; + @JsonProperty("proof_of_possession") + private ProofOfPossession proofOfPossession; @JsonCreator public ResourceServer(@JsonProperty("identifier") String identifier) { @@ -228,4 +230,19 @@ public TokenEncryption getTokenEncryption() { public void setTokenEncryption(TokenEncryption tokenEncryption) { this.tokenEncryption = tokenEncryption; } + + /** + * @return the value of the {@code proof_of_possession} field. + */ + public ProofOfPossession getProofOfPossession() { + return proofOfPossession; + } + + /** + * Sets the value of the {@code proof_of_possession} field. + * @param proofOfPossession the value of the {@code proof_of_possession} field. + */ + public void setProofOfPossession(ProofOfPossession proofOfPossession) { + this.proofOfPossession = proofOfPossession; + } } diff --git a/src/test/java/com/auth0/json/mgmt/ResourceServerTest.java b/src/test/java/com/auth0/json/mgmt/ResourceServerTest.java index 66e52359..a5e6bd04 100644 --- a/src/test/java/com/auth0/json/mgmt/ResourceServerTest.java +++ b/src/test/java/com/auth0/json/mgmt/ResourceServerTest.java @@ -1,5 +1,6 @@ package com.auth0.json.mgmt; +import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; import com.auth0.json.mgmt.resourceserver.*; import org.junit.jupiter.api.Test; @@ -12,6 +13,7 @@ import static com.auth0.json.JsonMatcher.hasEntry; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.containsString; public class ResourceServerTest extends JsonTest { private final static String RESOURCE_SERVER_JSON = "src/test/resources/mgmt/resource_server.json"; @@ -42,6 +44,8 @@ public void deserialize() throws Exception { assertThat(deserialized.getTokenEncryption().getEncryptionKey().getKid(), is("my kid")); assertThat(deserialized.getTokenEncryption().getEncryptionKey().getName(), is("my JWE public key")); assertThat(deserialized.getTokenEncryption().getEncryptionKey().getThumbprintSha256(), is("thumbprint")); + assertThat(deserialized.getProofOfPossession().getMechanism(), is("mtls")); + assertThat(deserialized.getProofOfPossession().getRequired(), is(true)); } @Test @@ -77,6 +81,8 @@ public void serialize() throws Exception { encryptionKey.setPem("pem"); TokenEncryption tokenEncryption = new TokenEncryption("format", encryptionKey); entity.setTokenEncryption(tokenEncryption); + ProofOfPossession proofOfPossession = new ProofOfPossession("mtls", true); + entity.setProofOfPossession(proofOfPossession); String json = toJSON(entity); @@ -96,5 +102,6 @@ public void serialize() throws Exception { assertThat(json, hasEntry("consent_policy", "transactional-authorization-with-mfa")); assertThat(json, hasEntry("authorization_details", notNullValue())); assertThat(json, hasEntry("token_encryption", containsString("{\"format\":\"format\",\"encryption_key\":{\"name\":\"name\",\"alg\":\"alg\",\"pem\":\"pem\",\"kid\":\"kid\"}}"))); + assertThat(json, hasEntry("proof_of_possession", containsString("{\"mechanism\":\"mtls\",\"required\":true}"))); } } diff --git a/src/test/java/com/auth0/json/mgmt/client/ClientTest.java b/src/test/java/com/auth0/json/mgmt/client/ClientTest.java index 307f82b8..11f901ba 100644 --- a/src/test/java/com/auth0/json/mgmt/client/ClientTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/ClientTest.java @@ -135,6 +135,7 @@ public class ClientTest extends JsonTest { " }\n" + " ]\n" + " },\n" + + " \"require_proof_of_possession\": true,\n" + " \"compliance_level\": \"fapi1_adv_pkj_par\"\n" + "}"; @@ -179,6 +180,7 @@ public void shouldSerialize() throws Exception { client.setRefreshToken(refreshToken); client.setOrganizationUsage("require"); client.setOrganizationRequireBehavior("pre_login_prompt"); + client.setRequireProofOfPossession(true); Credential credential = new Credential("public_key", "PEM"); PrivateKeyJwt privateKeyJwt = new PrivateKeyJwt(Collections.singletonList(credential)); @@ -251,6 +253,7 @@ public void shouldSerialize() throws Exception { assertThat(serialized, JsonMatcher.hasEntry("oidc_backchannel_logout", containsString("{\"backchannel_logout_urls\":[\"http://acme.eu.auth0.com/events\"]}"))); assertThat(serialized, JsonMatcher.hasEntry("signed_request_object", containsString("{\"required\":true,\"credentials\":[{\"credential_type\":\"public_key\",\"name\":\"cred name\",\"pem\":\"pem\"}]}"))); assertThat(serialized, JsonMatcher.hasEntry("compliance_level", "fapi1_adv_pkj_par")); + assertThat(serialized, JsonMatcher.hasEntry("require_proof_of_possession", true)); } @Test @@ -326,6 +329,8 @@ public void shouldDeserialize() throws Exception { assertThat(client.getSignedRequest().getCredentials().get(0).getName(), is("My JAR credential")); assertThat(client.getSignedRequest().getCredentials().get(0).getCreatedAt(), is(Date.from(Instant.parse("2024-03-14T11:34:28.893Z")))); assertThat(client.getSignedRequest().getCredentials().get(0).getUpdatedAt(), is(Date.from(Instant.parse("2024-03-14T11:34:28.893Z")))); + + assertThat(client.getRequireProofOfPossession(), is(true)); } @Test diff --git a/src/test/resources/mgmt/client.json b/src/test/resources/mgmt/client.json index daca48ca..a3395042 100644 --- a/src/test/resources/mgmt/client.json +++ b/src/test/resources/mgmt/client.json @@ -90,5 +90,6 @@ } ] }, - "compliance_level": "fapi1_adv_pkj_par" + "compliance_level": "fapi1_adv_pkj_par", + "require_proof_of_possession": true } diff --git a/src/test/resources/mgmt/resource_server.json b/src/test/resources/mgmt/resource_server.json index a383d78f..75284b5a 100644 --- a/src/test/resources/mgmt/resource_server.json +++ b/src/test/resources/mgmt/resource_server.json @@ -36,5 +36,9 @@ "alg": "RSA-OAEP-256", "thumbprint_sha256": "thumbprint" } + }, + "proof_of_possession": { + "mechanism": "mtls", + "required": true } }