diff --git a/pom.xml b/pom.xml index 070da9e..a6af719 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.pingidentity.developer pingid-api-playground war - 1.0.0 + 1.0.1 pingid-api-playground http://maven.apache.org @@ -20,6 +20,16 @@ 3.0.1 provided + + jstl + jstl + 1.2 + + + taglibs + standard + 1.1.2 + com.googlecode.json-simple json-simple diff --git a/src/main/java/com/pingidentity/developer/pingid/Operation.java b/src/main/java/com/pingidentity/developer/pingid/Operation.java index 9d70dbf..b783a29 100644 --- a/src/main/java/com/pingidentity/developer/pingid/Operation.java +++ b/src/main/java/com/pingidentity/developer/pingid/Operation.java @@ -5,8 +5,10 @@ import java.net.HttpURLConnection; import java.net.URL; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.TimeZone; @@ -16,6 +18,7 @@ import org.jose4j.jws.JsonWebSignature; import org.jose4j.keys.HmacKey; import org.jose4j.lang.JoseException; +import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -23,7 +26,9 @@ public class Operation { - + + private static final String ENDPOINT_BASE = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/"; + private String name; private String endpoint; private String requestToken; @@ -47,7 +52,7 @@ public class Operation { private String clientData; private User user; - private final String apiVersion = "4.6"; + private final String apiVersion = "4.9"; public Operation() { } @@ -86,7 +91,7 @@ public Operation(String orgAlias, String token, String useBase64Key) { public void AddUser(Boolean activateUser) { this.name = "AddUser"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/adduser/do"; + this.endpoint = ENDPOINT_BASE + "adduser/do"; JSONObject reqBody = new JSONObject(); reqBody.put("activateUser", activateUser); @@ -111,7 +116,7 @@ public void AddUser(Boolean activateUser) { public void EditUser(Boolean activateUser) { this.name = "EditUser"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/edituser/do"; + this.endpoint = ENDPOINT_BASE + "edituser/do"; JSONObject reqBody = new JSONObject(); reqBody.put("activateUser", activateUser); @@ -136,7 +141,7 @@ public void EditUser(Boolean activateUser) { public void GetUserDetails() { this.name = "GetUserDetails"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/getuserdetails/do"; + this.endpoint = ENDPOINT_BASE + "getuserdetails/do"; JSONObject reqBody = new JSONObject(); reqBody.put("getSameDeviceUsers", false); @@ -152,15 +157,26 @@ public void GetUserDetails() { JSONObject userDetails = (JSONObject)response.get("userDetails"); this.user = new User(userDetails); - DeviceDetails deviceDetails = new DeviceDetails((JSONObject)userDetails.get("deviceDetails")); + DeviceDetails deviceDetails = new DeviceDetails(); + List devices = new ArrayList(); + if(userDetails != null) { + JSONArray devicesArray = (JSONArray)userDetails.get("devicesDetails"); + if(devicesArray != null) { + for(int i = 0; i < devicesArray.size(); i++) { + devices.add(new DeviceDetails((JSONObject)devicesArray.get(i))); + } + } + deviceDetails = new DeviceDetails((JSONObject)userDetails.get("deviceDetails")); + } this.user.setDeviceDetails(deviceDetails); + this.user.setDevices(devices); } @SuppressWarnings("unchecked") public void DeleteUser() { this.name = "DeleteUser"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/deleteuser/do"; + this.endpoint = ENDPOINT_BASE + "deleteuser/do"; JSONObject reqBody = new JSONObject(); reqBody.put("userName", this.user.getUserName()); @@ -177,7 +193,7 @@ public void DeleteUser() { public void SuspendUser() { this.name = "SuspendUser"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/suspenduser/do"; + this.endpoint = ENDPOINT_BASE + "suspenduser/do"; JSONObject reqBody = new JSONObject(); reqBody.put("userName", this.user.getUserName()); @@ -194,7 +210,7 @@ public void SuspendUser() { public void ActivateUser() { this.name = "ActivateUser"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/activateuser/do"; + this.endpoint = ENDPOINT_BASE + "activateuser/do"; JSONObject reqBody = new JSONObject(); reqBody.put("userName", this.user.getUserName()); @@ -211,7 +227,7 @@ public void ActivateUser() { public void ToggleUserBypass(long until) { this.name = "ToggleUserBypass"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/userbypass/do"; + this.endpoint = ENDPOINT_BASE + "userbypass/do"; JSONObject reqBody = new JSONObject(); reqBody.put("userName", this.user.getUserName()); @@ -226,15 +242,18 @@ public void ToggleUserBypass(long until) { } @SuppressWarnings("unchecked") - public void UnpairDevice() { + public void UnpairDevice(long deviceId) { this.name = "UnpairDevice"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/unpairdevice/do"; + this.endpoint = ENDPOINT_BASE + "unpairdevice/do"; JSONObject reqBody = new JSONObject(); reqBody.put("userName", this.user.getUserName()); reqBody.put("clientData", this.clientData); + if(deviceId > 0) + reqBody.put("deviceId", deviceId); + this.requestToken = buildRequestToken(reqBody); sendRequest(); @@ -246,7 +265,7 @@ public void UnpairDevice() { public void GetPairingStatus(String activationCode) { this.name = "GetPairingStatus"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/pairingstatus/do"; + this.endpoint = ENDPOINT_BASE + "pairingstatus/do"; JSONObject reqBody = new JSONObject(); reqBody.put("activationCode", activationCode); @@ -264,7 +283,7 @@ public void GetPairingStatus(String activationCode) { public void PairYubiKey(String otp) { this.name = "PairYubiKey"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/pairyubikey/do"; + this.endpoint = ENDPOINT_BASE + "pairyubikey/do"; JSONObject reqBody = new JSONObject(); reqBody.put("otp", otp); @@ -282,7 +301,7 @@ public void PairYubiKey(String otp) { public void StartOfflinePairing(OfflinePairingMethod pairingMethod) { this.name = "StartOfflinePairing"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/startofflinepairing/do"; + this.endpoint = ENDPOINT_BASE + "startofflinepairing/do"; JSONObject reqBody = new JSONObject(); @@ -311,7 +330,7 @@ public void StartOfflinePairing(OfflinePairingMethod pairingMethod) { public void FinalizeOfflinePairing(String sessionId, String otp) { this.name = "FinalizeOfflinePairing"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/finalizeofflinepairing/do"; + this.endpoint = ENDPOINT_BASE + "finalizeofflinepairing/do"; JSONObject reqBody = new JSONObject(); reqBody.put("otp", otp); @@ -329,7 +348,7 @@ public void FinalizeOfflinePairing(String sessionId, String otp) { public void GetActivationCode() { this.name = "GetActivationCode"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/getactivationcode/do"; + this.endpoint = ENDPOINT_BASE + "getactivationcode/do"; JSONObject reqBody = new JSONObject(); reqBody.put("userName", this.user.getUserName()); @@ -342,12 +361,16 @@ public void GetActivationCode() { values.clear(); this.lastActivationCode = (String)response.get("activationCode"); } + + public void AuthenticateOnline(Application application, String authType) { + AuthenticateOnline(application, authType, 0); + } @SuppressWarnings("unchecked") - public void AuthenticateOnline(Application application, String authType) { + public void AuthenticateOnline(Application application, String authType, long deviceId) { this.name = "AuthenticateOnline"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/authonline/do"; + this.endpoint = ENDPOINT_BASE + "authonline/do"; JSONObject reqBody = new JSONObject(); reqBody.put("authType", authType); @@ -355,6 +378,9 @@ public void AuthenticateOnline(Application application, String authType) { reqBody.put("userName", this.user.getUserName()); reqBody.put("clientData", this.clientData); + if(deviceId > 0) + reqBody.put("deviceId", deviceId); + JSONObject formParameters = new JSONObject(); formParameters.put("sp_name", application.getName()); if (application.getLogoUrl() != null || !application.getLogoUrl().isEmpty()) { @@ -378,7 +404,7 @@ public void AuthenticateOnline(Application application, String authType) { public void AuthenticateOffline(String sessionId, String otp) { this.name = "AuthenticateOffline"; - this.endpoint = "https://idpxnyl3m.pingidentity.com/pingid/rest/4/authoffline/do"; + this.endpoint = ENDPOINT_BASE + "authoffline/do"; JSONObject reqBody = new JSONObject(); reqBody.put("spAlias", "web"); diff --git a/src/main/java/com/pingidentity/developer/pingid/User.java b/src/main/java/com/pingidentity/developer/pingid/User.java index 7f2ad76..c6ed159 100644 --- a/src/main/java/com/pingidentity/developer/pingid/User.java +++ b/src/main/java/com/pingidentity/developer/pingid/User.java @@ -4,6 +4,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.TimeZone; @@ -20,6 +21,7 @@ public class User { private String phoneNumber; private DeviceDetails deviceDetails; + private List devices; private Date lastAuthentication; private Boolean enabled; @@ -106,6 +108,7 @@ public User(JSONObject userDetailsJSON) { public UserStatus getStatus() { return this.status; } public Date getBypassedUntil(String spAlias) { return this.bypassInfo.get(spAlias); } public Date getLastAuthentication() { return this.lastAuthentication; } + public List getDevices() { return devices; } public void setUserName(String userName) { this.userName = userName; } public void setFirstName(String firstName) { this.fName = firstName; } @@ -114,6 +117,7 @@ public User(JSONObject userDetailsJSON) { public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } public void setRole(UserRole role) { this.role = role; } public void setDeviceDetails(DeviceDetails deviceDetails) { this.deviceDetails = deviceDetails; } + public void setDevices(List devices) { this.devices = devices; } @SuppressWarnings("unused") private Date parseDate(String dateToParse) { diff --git a/src/main/java/com/pingidentity/developer/playground/pingid/APIHandlerServlet.java b/src/main/java/com/pingidentity/developer/playground/pingid/APIHandlerServlet.java index 51bd352..ee07b8e 100644 --- a/src/main/java/com/pingidentity/developer/playground/pingid/APIHandlerServlet.java +++ b/src/main/java/com/pingidentity/developer/playground/pingid/APIHandlerServlet.java @@ -14,11 +14,13 @@ import com.cedarsoftware.util.io.JsonWriter; import com.pingidentity.developer.pingid.Application; import com.pingidentity.developer.pingid.OfflinePairingMethod; -import com.pingidentity.developer.pingid.User; import com.pingidentity.developer.pingid.Operation; +import com.pingidentity.developer.pingid.User; public class APIHandlerServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestedOperation = request.getParameter("operation"); @@ -28,13 +30,17 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) Operation operation = new Operation((String)session.getAttribute("pingid_org_alias"), (String)session.getAttribute("pingid_token"), (String)session.getAttribute("pingid_use_base64_key"));; operation.setTargetUser(targetUsername); + String deviceIdObject = (String)request.getParameter("deviceId"); + long deviceId = deviceIdObject != null && !deviceIdObject.isEmpty() ? Long.parseLong(deviceIdObject) : 0; + switch (requestedOperation) { case "AuthenticateOnline": Application app = new Application(request.getParameter("applicationName")); app.setLogoUrl(request.getParameter("applicationIconUrl")); app.setSpAlias("web"); - operation.AuthenticateOnline(app, request.getParameter("authType")); + + operation.AuthenticateOnline(app, request.getParameter("authType"), deviceId); request.setAttribute("lastSessionId", operation.getLastSessionId()); break; @@ -139,7 +145,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) break; case "UnpairDevice": - operation.UnpairDevice(); + operation.UnpairDevice(deviceId); break; default: diff --git a/src/main/java/com/pingidentity/developer/playground/pingid/PropertiesFileUploadServlet.java b/src/main/java/com/pingidentity/developer/playground/pingid/PropertiesFileUploadServlet.java index 6795e26..1edf708 100644 --- a/src/main/java/com/pingidentity/developer/playground/pingid/PropertiesFileUploadServlet.java +++ b/src/main/java/com/pingidentity/developer/playground/pingid/PropertiesFileUploadServlet.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.io.InputStream; -import java.io.PrintWriter; import java.util.Properties; import javax.servlet.RequestDispatcher; @@ -16,12 +15,12 @@ import org.apache.commons.fileupload.FileItemStream; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.apache.commons.fileupload.util.Streams; -import org.apache.commons.io.IOUtils; public class PropertiesFileUploadServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (ServletFileUpload.isMultipartContent(request)) { @@ -32,7 +31,6 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) while(fii.hasNext()) { FileItemStream item = fii.next(); - String name = item.getFieldName(); InputStream is = item.openStream(); if (item.isFormField()) { diff --git a/src/main/java/com/pingidentity/developer/playground/pingid/StatusPollingServlet.java b/src/main/java/com/pingidentity/developer/playground/pingid/StatusPollingServlet.java new file mode 100644 index 0000000..ae5fa7c --- /dev/null +++ b/src/main/java/com/pingidentity/developer/playground/pingid/StatusPollingServlet.java @@ -0,0 +1,47 @@ +package com.pingidentity.developer.playground.pingid; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import com.pingidentity.developer.pingid.Operation; + +public class StatusPollingServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + HttpSession session = request.getSession(false); + String orgAlias = (String) session.getAttribute("pingid_org_alias"); + String token = (String) session.getAttribute("pingid_token"); + String base64Key = (String) session.getAttribute("pingid_use_base64_key"); + + response.setHeader("Content-Type", "text/plain"); + response.setHeader("success", "yes"); + String activationCode = request.getParameter("activationCode"); + Operation operation = new Operation(orgAlias, token, base64Key); + operation.GetPairingStatus(activationCode); + Map values = operation.getReturnValues(); + String returnValue = "NOT_CLAIMED"; + if (values != null && values.containsKey("pairingStatus")) { + returnValue = values.get("pairingStatus").toString(); + } + PrintWriter writer = response.getWriter(); + writer.write(returnValue); + writer.close(); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + doPost(req, resp); + } + +} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 1a908da..39ba29f 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -17,6 +17,12 @@ com.pingidentity.developer.playground.pingid.APIHandlerServlet + + StatusPollingServlet + StatusPollingServlet + com.pingidentity.developer.playground.pingid.StatusPollingServlet + + PropertiesFileUploadServlet /handle-upload-props @@ -27,4 +33,8 @@ /api-handler + + StatusPollingServlet + /status + \ No newline at end of file diff --git a/src/main/webapp/api-operation.jsp b/src/main/webapp/api-operation.jsp index 043946c..e25c842 100644 --- a/src/main/webapp/api-operation.jsp +++ b/src/main/webapp/api-operation.jsp @@ -1,5 +1,6 @@ <%@page contentType="text/html" pageEncoding="UTF-8"%> <%@taglib prefix="t" tagdir="/WEB-INF/tags"%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> @@ -36,5 +37,44 @@
${responseTokenHeaderJSON}
.
${responseTokenPayloadJSON}
.
${responseTokenSignatureJSON}
+ + +
+
QR Code
+
+
The activation code (a.k.a the pairing code) can be manually entered into either the mobile apps or the desktop app or it can be encoded in such a way as to produce a QR code. View the source of this page to see how to do that entirely in JavaScript. Note that this also includes a polling process to test if the user has used the QR code or entered in the pairing code manually.
+
+
+
Activation Code: ${lastActivationCode}
+
+
+
+ +
+
+
\ No newline at end of file diff --git a/src/main/webapp/assets/ping/img/success.png b/src/main/webapp/assets/ping/img/success.png new file mode 100644 index 0000000..a9ed16d Binary files /dev/null and b/src/main/webapp/assets/ping/img/success.png differ diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp index 5c3fb05..2fad4c9 100644 --- a/src/main/webapp/index.jsp +++ b/src/main/webapp/index.jsp @@ -79,7 +79,11 @@ + + + @@ -330,6 +334,9 @@ + +