-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add sessions and refresh tokens to Users Management API #654
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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<AuthenticationMethod> updateAuthenticationMethodById(String userI | |
return request; | ||
} | ||
|
||
/** | ||
* Get refresh tokens for a user | ||
* A token with {@code read:refresh_tokens} is needed. | ||
* See <a href="https://auth0.com/docs/api/management/v2/users/get-refresh-tokens-for-user">https://auth0.com/docs/api/management/v2/users/get-refresh-tokens-for-user</a> | ||
* | ||
* @param userId the role id | ||
* @param filter an optional pagination filter | ||
* @return a Request to execute | ||
*/ | ||
public Request<RefreshTokensPage> listRefreshTokens(String userId, CheckpointPaginationFilter filter) { | ||
Asserts.assertNotNull(userId, "user id"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lets use "user ID" everywhere |
||
HttpUrl.Builder builder = baseUrl | ||
.newBuilder() | ||
.addPathSegments("api/v2/users") | ||
.addPathSegment(userId) | ||
.addPathSegment("refresh-tokens"); | ||
if (filter != null) { | ||
for (Map.Entry<String, Object> 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<RefreshTokensPage>() { | ||
}); | ||
} | ||
|
||
/** | ||
* Delete all refresh tokens for a user. | ||
* A token with scope {@code delete:refresh_tokens} is needed. | ||
* See <a href="https://auth0.com/docs/api/management/v2/users/delete-refresh-tokens-for-user">https://auth0.com/docs/api/management/v2/users/delete-refresh-tokens-for-user</a> | ||
* | ||
* @param userId the user to delete the refresh tokens for | ||
* @return a Request to execute. | ||
*/ | ||
public Request<Void> 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 <a href="https://auth0.com/docs/api/management/v2/users/get-sessions-for-user">https://auth0.com/docs/api/management/v2/users/get-sessions-for-user</a> | ||
* | ||
* @param userId the role id | ||
* @param filter an optional pagination filter | ||
* @return a Request to execute | ||
*/ | ||
public Request<SessionsPage> listSessions(String userId, CheckpointPaginationFilter filter) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use PageFilter for now instead of creating new class CheckpointPaginationFilter |
||
Asserts.assertNotNull(userId, "user id"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lets use "user ID" everywhere |
||
HttpUrl.Builder builder = baseUrl | ||
.newBuilder() | ||
.addPathSegments("api/v2/users") | ||
.addPathSegment(userId) | ||
.addPathSegment("sessions"); | ||
if (filter != null) { | ||
for (Map.Entry<String, Object> 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<SessionsPage>() { | ||
}); | ||
} | ||
|
||
/** | ||
* Delete sessions for user | ||
* A token with scope {@code delete:sessions} is needed. | ||
* See <a href="https://auth0.com/docs/api/management/v2/users/delete-sessions-for-user">https://auth0.com/docs/api/management/v2/users/delete-sessions-for-user</a> | ||
* | ||
* @param userId the user to delete the sessions for | ||
* @return a Request to execute. | ||
*/ | ||
public Request<Void> 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<String, Object> e : filter.getAsMap().entrySet()) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.auth0.client.mgmt.filter; | ||
|
||
public class CheckpointPaginationFilter extends BaseFilter { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use PageFilter for now instead of creating new class CheckpointPaginationFilter |
||
|
||
/** | ||
* 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; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<ResourceServer> resourceServers; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Device object and last_exchanged_at fields are missing. For reference - https://auth0.com/docs/api/management/v2/users/get-refresh-tokens-for-user#scopes |
||
|
||
/** | ||
* @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<ResourceServer> getResourceServers() { | ||
return resourceServers; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<RefreshToken> because the URL only supports "next" and "take" pagination. | ||
*/ | ||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
@JsonInclude(JsonInclude.Include.NON_NULL) | ||
public class RefreshTokensPage { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use inheritance and extend generic Page<> class. For reference, refer ClientsPage class |
||
@JsonProperty("total") | ||
private Integer total; | ||
|
||
@JsonProperty("next") | ||
private String next; | ||
|
||
@JsonProperty("tokens") | ||
private List<RefreshToken> 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<RefreshToken> getTokens() { | ||
return tokens; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<String> scopes; | ||
|
||
/** | ||
* @return Resource server ID | ||
*/ | ||
public String getAudience() { | ||
return audience; | ||
} | ||
|
||
/** | ||
* @return List of scopes for the refresh token | ||
*/ | ||
public List<String> getScopes() { | ||
return scopes; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<AuthenticationMethod> methods; | ||
|
||
/** | ||
* @return Contains the authentication methods a user has completed during their session | ||
*/ | ||
public List<AuthenticationMethod> getMethods() { | ||
return methods; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use PageFilter for now instead of creating new class CheckpointPaginationFilter