comparison src/de/mpiwg/itgroup/annotationManager/restlet/AnnotatorResourceImpl.java @ 10:0bdfe01e30b5

checking auth token works now.
author casties
date Tue, 20 Mar 2012 15:55:51 +0100
parents 11baadcdd2c8
children 2f8c72ae4c43
comparison
equal deleted inserted replaced
9:e9fd2e1e0979 10:0bdfe01e30b5
3 */ 3 */
4 package de.mpiwg.itgroup.annotationManager.restlet; 4 package de.mpiwg.itgroup.annotationManager.restlet;
5 5
6 import java.io.UnsupportedEncodingException; 6 import java.io.UnsupportedEncodingException;
7 import java.net.URLDecoder; 7 import java.net.URLDecoder;
8 import java.security.MessageDigest;
9 import java.security.NoSuchAlgorithmException;
8 import java.util.ArrayList; 10 import java.util.ArrayList;
9 import java.util.List; 11 import java.util.List;
10 import java.util.regex.Matcher; 12 import java.util.regex.Matcher;
11 import java.util.regex.Pattern; 13 import java.util.regex.Pattern;
12 14
15 import org.apache.log4j.Logger;
16 import org.joda.time.DateTime;
17 import org.joda.time.format.DateTimeFormatter;
18 import org.joda.time.format.ISODateTimeFormat;
13 import org.json.JSONArray; 19 import org.json.JSONArray;
14 import org.json.JSONException; 20 import org.json.JSONException;
15 import org.json.JSONObject; 21 import org.json.JSONObject;
16 import org.restlet.data.Form; 22 import org.restlet.data.Form;
17 import org.restlet.representation.Representation; 23 import org.restlet.representation.Representation;
27 * @author dwinter, casties 33 * @author dwinter, casties
28 * 34 *
29 */ 35 */
30 public abstract class AnnotatorResourceImpl extends ServerResource { 36 public abstract class AnnotatorResourceImpl extends ServerResource {
31 37
38 protected Logger logger = Logger.getRootLogger();
39
32 protected String getAllowedMethodsForHeader() { 40 protected String getAllowedMethodsForHeader() {
33 return "OPTIONS,GET,POST"; 41 return "OPTIONS,GET,POST";
34 } 42 }
35 43
36 /** 44 /**
38 * 46 *
39 * @param entity 47 * @param entity
40 */ 48 */
41 @Options 49 @Options
42 public void doOptions(Representation entity) { 50 public void doOptions(Representation entity) {
43 Form responseHeaders = (Form) getResponse().getAttributes().get( 51 Form responseHeaders = (Form) getResponse().getAttributes().get("org.restlet.http.headers");
44 "org.restlet.http.headers");
45 if (responseHeaders == null) { 52 if (responseHeaders == null) {
46 responseHeaders = new Form(); 53 responseHeaders = new Form();
47 getResponse().getAttributes().put("org.restlet.http.headers", 54 getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders);
48 responseHeaders); 55 }
49 } 56 responseHeaders.add("Access-Control-Allow-Methods", getAllowedMethodsForHeader());
50 responseHeaders.add("Access-Control-Allow-Methods",
51 getAllowedMethodsForHeader());
52 // echo back Origin and Request-Headers 57 // echo back Origin and Request-Headers
53 Form requestHeaders = (Form) getRequest().getAttributes().get( 58 Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
54 "org.restlet.http.headers");
55 String origin = requestHeaders.getFirstValue("Origin", true); 59 String origin = requestHeaders.getFirstValue("Origin", true);
56 if (origin == null) { 60 if (origin == null) {
57 responseHeaders.add("Access-Control-Allow-Origin", "*"); 61 responseHeaders.add("Access-Control-Allow-Origin", "*");
58 } else { 62 } else {
59 responseHeaders.add("Access-Control-Allow-Origin", origin); 63 responseHeaders.add("Access-Control-Allow-Origin", origin);
60 } 64 }
61 String allowHeaders = requestHeaders.getFirstValue( 65 String allowHeaders = requestHeaders.getFirstValue("Access-Control-Request-Headers", true);
62 "Access-Control-Request-Headers", true);
63 if (allowHeaders != null) { 66 if (allowHeaders != null) {
64 responseHeaders.add("Access-Control-Allow-Headers", allowHeaders); 67 responseHeaders.add("Access-Control-Allow-Headers", allowHeaders);
65 } 68 }
66 responseHeaders.add("Access-Control-Allow-Credentials", "true"); 69 responseHeaders.add("Access-Control-Allow-Credentials", "true");
67 responseHeaders.add("Access-Control-Max-Age", "60"); 70 responseHeaders.add("Access-Control-Max-Age", "60");
68 } 71 }
69 72
70 /** 73 /**
71 * Erzeugt aus einer Annotation, das fuer den Annotator notwendige 74 * returns if authentication information from headers is valid.
72 * JSON-Format 75 *
76 * @param entity
77 * @return
78 */
79 public boolean isAuthenticated(Representation entity) {
80 // get authToken
81 Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
82 String consumerKey = requestHeaders.getFirstValue("x-annotator-consumer-key", true);
83 if (consumerKey == null) {
84 return false;
85 }
86 RestServer restServer = (RestServer) getApplication();
87 String consumerSecret = restServer.getConsumerSecret(consumerKey);
88 logger.debug("requested consumer key=" + consumerKey + " secret=" + consumerSecret);
89 if (consumerSecret == null) {
90 return false;
91 }
92 String userId = requestHeaders.getFirstValue("x-annotator-user-id", true);
93 String issueTime = requestHeaders.getFirstValue("x-annotator-auth-token-issue-time", true);
94 if (userId == null || issueTime == null) {
95 return false;
96 }
97 // compute hashed token based on the values we know
98 // computed_token = hashlib.sha256(consumer.secret + user_id + issue_time).hexdigest()
99 String computedToken;
100 try {
101 MessageDigest md = MessageDigest.getInstance("SHA-256");
102 String computedString = consumerSecret + userId + issueTime;
103 md.update(computedString.getBytes("UTF-8"));
104 byte[] dg = md.digest();
105 StringBuffer sb = new StringBuffer();
106 for (byte b : dg) {
107 sb.append(String.format("%02x", b));
108 }
109 computedToken = sb.toString();
110 } catch (NoSuchAlgorithmException e) {
111 e.printStackTrace();
112 return false;
113 } catch (UnsupportedEncodingException e) {
114 e.printStackTrace();
115 return false;
116 }
117 // compare to the token we got
118 String authToken = requestHeaders.getFirstValue("x-annotator-auth-token", true);
119 logger.debug(String.format("got: authToken=%s consumerSecret=%s userId=%s issueTime=%s", authToken, consumerSecret, userId,
120 issueTime));
121 if (!computedToken.equals(authToken)) {
122 return false;
123 }
124 // check token lifetime
125 // validity = iso8601.parse_date(issue_time)
126 // expiry = validity + datetime.timedelta(seconds=consumer.ttl)
127 int tokenTtl = 86400;
128 DateTime tokenValidity = null;
129 DateTime tokenExpiry = null;
130 try {
131 DateTimeFormatter parser = ISODateTimeFormat.dateTime();
132 tokenValidity = parser.parseDateTime(issueTime);
133 String tokenTtlString = requestHeaders.getFirstValue("x-annotator-auth-token-ttl", true);
134 tokenTtl = Integer.parseInt(tokenTtlString);
135 tokenExpiry = tokenValidity.plusSeconds(tokenTtl);
136 } catch (NumberFormatException e) {
137 e.printStackTrace();
138 }
139 if (tokenValidity == null || tokenValidity.isAfterNow() || tokenExpiry.isBeforeNow()) {
140 return false;
141 }
142 // must be ok then
143 return true;
144 }
145
146 /**
147 * Erzeugt aus einer Annotation, das fuer den Annotator notwendige JSON-Format
73 * 148 *
74 * @param annot 149 * @param annot
75 * @return 150 * @return
76 */ 151 */
77 protected JSONObject annot2AnnotatorJSON(Convert.Annotation annot) { 152 protected JSONObject annot2AnnotatorJSON(Convert.Annotation annot) {
85 160
86 RestServer restServer = (RestServer) getApplication(); 161 RestServer restServer = (RestServer) getApplication();
87 162
88 String userID = annot.creator; 163 String userID = annot.creator;
89 if (userID.startsWith(NS.MPIWG_PERSONS)) { 164 if (userID.startsWith(NS.MPIWG_PERSONS)) {
90 userID = userID.replace(NS.MPIWG_PERSONS, ""); // entferne 165 userID = userID.replace(NS.MPIWG_PERSONS, ""); // entferne NAMESPACE
91 // NAMESPACE
92 } 166 }
93 String userName = restServer.getUserNameFromLdap(userID); 167 String userName = restServer.getUserNameFromLdap(userID);
94 userObject.put("name", userName); 168 userObject.put("name", userName);
95 169
96 jo.put("user", userObject); 170 jo.put("user", userObject);
118 192
119 JSONArray ja = new JSONArray(); 193 JSONArray ja = new JSONArray();
120 194
121 Pattern rg = Pattern 195 Pattern rg = Pattern
122 .compile("#xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)/range-to\\(end-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)\\)"); 196 .compile("#xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)/range-to\\(end-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)\\)");
123 Pattern rg1 = Pattern 197 Pattern rg1 = Pattern.compile("#xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)");
124 .compile("#xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)");
125 198
126 try { 199 try {
127 for (String xpointer : xpointers) { 200 for (String xpointer : xpointers) {
128 String decoded = URLDecoder.decode(xpointer, "utf-8"); 201 String decoded = URLDecoder.decode(xpointer, "utf-8");
129 Matcher m = rg.matcher(decoded); 202 Matcher m = rg.matcher(decoded);