Bug 541698 - ClassCastException in JSON deserialization with custom identity provider

Change-Id: I1f2d848baf1b52ddc42dfc8addc386987fda0735
diff --git a/org.eclipse.userstorage.oauth.tests/src/org/eclipse/userstorage/oauth/AuthTokenTest.java b/org.eclipse.userstorage.oauth.tests/src/org/eclipse/userstorage/oauth/AuthTokenTest.java
index 5ca627e..4f7779a 100644
--- a/org.eclipse.userstorage.oauth.tests/src/org/eclipse/userstorage/oauth/AuthTokenTest.java
+++ b/org.eclipse.userstorage.oauth.tests/src/org/eclipse/userstorage/oauth/AuthTokenTest.java
@@ -7,6 +7,7 @@
 
 import java.io.IOException;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashSet;
 
 import org.eclipse.userstorage.internal.oauth.AuthToken;
@@ -15,6 +16,30 @@
 public class AuthTokenTest {
 
 	@Test
+	public void testParse_rfc6749() {
+		String serializedForm = "{\"access_token\":\"a8f8a49232520e7d621b1ae1235a35665e27344d\","
+				+ "\"token_type\":\"Bearer\"," + "\"scope\":\"uss_retrieve\"," + "\"expires_in\":3600}";
+		AuthToken token = new AuthToken(serializedForm, new Date(0));
+		assertEquals("a8f8a49232520e7d621b1ae1235a35665e27344d", token.getAccessToken());
+		assertEquals("Bearer", token.getTokenType());
+		assertEquals(new HashSet<String>(Collections.singleton("uss_retrieve")), token.getScopes());
+		assertNull(token.getRefreshToken());
+		assertTrue(token.isExpired());
+	}
+
+	@Test
+	public void testParse_oauthDrupal() {
+		String serializedForm = "{\"access_token\":\"a8f8a49232520e7d621b1ae1235a35665e27344d\","
+				+ "\"token_type\":\"Bearer\"," + "\"scope\":\"uss_retrieve\"," + "\"expires_in\":\"3600\"}";
+		AuthToken token = new AuthToken(serializedForm, new Date(0));
+		assertEquals("a8f8a49232520e7d621b1ae1235a35665e27344d", token.getAccessToken());
+		assertEquals("Bearer", token.getTokenType());
+		assertEquals(new HashSet<String>(Collections.singleton("uss_retrieve")), token.getScopes());
+		assertNull(token.getRefreshToken());
+		assertTrue(token.isExpired());
+	}
+
+	@Test
 	public void testDeserialization() {
 		String serializedForm = "{\"access_token\":\"a8f8a49232520e7d621b1ae1235a35665e27344d\","
 				+ "\"token_type\":\"Bearer\"," + "\"scope\":\"uss_retrieve\","
diff --git a/org.eclipse.userstorage.oauth/src/org/eclipse/userstorage/internal/oauth/AuthToken.java b/org.eclipse.userstorage.oauth/src/org/eclipse/userstorage/internal/oauth/AuthToken.java
index 114cc32..83c319f 100644
--- a/org.eclipse.userstorage.oauth/src/org/eclipse/userstorage/internal/oauth/AuthToken.java
+++ b/org.eclipse.userstorage.oauth/src/org/eclipse/userstorage/internal/oauth/AuthToken.java
@@ -88,7 +88,10 @@
     }
     if (details.containsKey(EXPIRES_IN))
     {
-      long expiry = Long.parseLong(details.remove(EXPIRES_IN)); // seconds
+      // RFC 6749 §5.1 says expires_in is a JSON number, but the oauth2_server
+      // drupal module returns it encoded as a JSON string
+      Object expiresIn = details.remove(EXPIRES_IN);
+      long expiry = expiresIn instanceof String ? Long.parseLong((String)expiresIn) : ((Number)expiresIn).longValue(); // seconds
       expiryDate = new Date(responseDate.getTime() + expiry * 1000);
       details.put(EXPIRES, DateUtils.formatDate(expiryDate));
     }