WS: Single Sign On
SSO webservice is the utility to allow users to have access to the entire editor offer with a single account, a user simply log-in to one of the sites of the editor eg. cms.editor.com and when he visits virtualnewspaper.editor.com or vice-versa no login is required.
Global workflow
The Flow
When the user log-in on one of the sites that site stores a cookie on the client that will be valid for every host of the editor. The cookie is named vuidjson
When he lands on a site that cookie will be read and the user will be logged in whenever the cookie is correctly parsed
if the user is not saved on the server DB a Webservice will be contacted to retrieve the user informations
The login
Whenever a user logs in a cookie named vuidjson that contains a 3DES encryption JSON URLEncoded with provided username and password will be released by the server.
| Example: the JSON {"login":"username@email.com","password":"123456789"} will be moXWrm7OEpRv9uEGO0ch%2BmoDWze1f2gtfxKtRkw8SJ0Yp3kRB5mtA1Pyq4Qk1rHvo3FHXs4DTfk%3D |
The resultant String will be the value of the vuidjson Cookie
Code Example
import java.security.*; import java.security.spec.*; import javax.crypto.spec.*; import javax.crypto.*; public class DesEncrypter { javax.crypto.Cipher ecipher; javax.crypto.Cipher dcipher; // 8-byte Salt byte[] salt = { (byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32, (byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03 }; // Iteration count int iterationCount = 19; public DesEncrypter(String passPhrase) { try { // Create the key KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); SecretKey key = SecretKeyFactory.getInstance( "PBEWithMD5AndDES").generateSecret(keySpec); ecipher = Cipher.getInstance(key.getAlgorithm()); dcipher = Cipher.getInstance(key.getAlgorithm()); // Prepare the parameter to the ciphers AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount); // Create the ciphers ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec); } catch (java.security.InvalidAlgorithmParameterException e) { } catch (java.security.spec.InvalidKeySpecException e) { } catch (javax.crypto.NoSuchPaddingException e) { } catch (java.security.NoSuchAlgorithmException e) { } catch (java.security.InvalidKeyException e) { } } public String encrypt(String str) { if (str==null) str=""; try { // Encode the string into bytes using utf-8 byte[] utf8 = str.getBytes("UTF8"); // Encrypt byte[] enc = ecipher.doFinal(utf8); // Encode bytes to base64 to get a string return new sun.misc.BASE64Encoder().encode(enc); } catch (javax.crypto.BadPaddingException e) { } catch (IllegalBlockSizeException e) { } catch (java.io.UnsupportedEncodingException e) { } catch (java.io.IOException e) { } return null; } public String decrypt(String str) { if (str==null) str=""; try { // Decode base64 to get bytes byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str); // Decrypt byte[] utf8 = dcipher.doFinal(dec); // Decode using utf-8 return new String(utf8, "UTF8"); } catch (javax.crypto.BadPaddingException e) { } catch (IllegalBlockSizeException e) { } catch (java.io.UnsupportedEncodingException e) { } catch (java.io.IOException e) { } return null; } }
String pk="thePrivateKey"; // The correct value is in the panel settings module org.json.JSONObject auth=new org.json.JSONObject(); auth.put("login","username@email.com"); auth.put("password","123456789"); javax.servlet.http.Cookie loginCookie=new javax.servlet.http.Cookie("vuidjson",java.net.URLEncoder.encode(new DesEncrypter(pk).encrypt(auth.toString()),"UTF-8")); loginCookie.setPath("/"); loginCookie.setDomain(request.getServerName().substring(request.getServerName().indexOf("."))); loginCookie.setMaxAge(60*60*24*365); response.addCookie(loginCookie);
thePrivateKey can be found in the administration panel settings module
The user Land handling
On each page of each site a control should be done to verify the existance of the 'vuidjson' cookie. If it is found it is required to read its value, decrypt, and use the stored username and password to login the user. If the user is not found on the server it must be retrieved by a webservice exposed by the server that released the vuidjson cookie.
Code Example
for(Cookie co:request.getCookies()){ if(co.getName().equals("vuidjson")){ org.json.JSONObject auth=new org.json.JSONObject(new utilita.DesEncrypter("thePrivateKey").decrypt(java.net.URLDecoder.decode(co.getValue(),"UTF-8"))); ResultSet rs = st.executeQuery("select * from users where email = '"+auth.getString("email")+"' and password=md5('"+auth.getString("password")+"')"); if (rs.next()) { // Login the user } else { // Use the login webservice to retrieve the user } } }
The login webservice
the URL is: 'virtualnewspaper.editor.com/sso/getUserByEmail.jsp'
Response example:
{
customerId: 2715636,
address: "viale ariosto 328",
email: "username@email.com",
status: 1,
name: "John",
gender: "_",
surname: "Doe",
orders: [
{
detailOrder: [
{
totalCredits: 12,
detailOrderId: 1193577,
price: 0,
editionsConsulted: "",
productCode: "",
expireDate: "2015-05-12",
idProduct: 141,
activationDate: "2014-05-13",
productName: "one year subscription",
currency: "EUR"
}
],
confirmed: 1,
date: "2014-05-13",
orderId: 1173568
},
{
detailOrder: [
{
totalCredits: 1,
detailOrderId: 1193576,
price: 0,
editionsConsulted: "130801edition;",
productCode: "DIGITQRTSING",
expireDate: "2015-05-12",
idProduct: 40,
activationDate: "2014-05-13",
productName: "Single Copy",
currency: "EUR"
}
],
confirmed: 1,
date: "2014-05-13",
orderId: 1173567
}
],
town: "Firenze",
password: "08cf56a1e2c7d2da70c03b861e6dd506",
mobile: ""
}
To retrieve the user informations a call to this service will provide the user informations
private static String readAll(java.io.Reader rd) throws java.io.IOException { StringBuilder sb = new StringBuilder(); int cp; while ((cp = rd.read()) != -1) { sb.append((char) cp); } return sb.toString(); } public static org.json.JSONObject readJsonFromUrl(String url) throws java.io.IOException, org.json.JSONException { org.json.JSONObject json = null; try { java.io.InputStream is = new java.net.URL(url).openStream(); java.io.InputStreamReader isr=new java.io.InputStreamReader(is, "UTF-8"); java.io.BufferedReader rd = new java.io.BufferedReader(isr); String jsonText = readAll(rd); json = new org.json.JSONObject(jsonText); is.close(); rd.close(); isr.close(); } catch(Exception e) { } return json; }
String email = "username@email.com"; String pk = "thePrivateKey" String authCode = md5(email+pk); String url = "virtualnewspaper.editor.com/sso/getUserByEmail.jsp?email="+email+"&authCode="+authCode org.json.JSONObject json = utilita.Utilities.readJsonFromUrl(url); if (json.getInt("status")==1) { // Store (or update) and login the user }
The same webservice must be provided in order to allow VirtualNewspaper to retrieve users informations. The URL must be communicated to Virtualcom support for the platform configuration
