@@ -59,6 +59,9 @@ public class OAuthReturn extends AbstractWebScript
59
59
ConnectorService connectorService ;
60
60
String accessTokenUrl ;
61
61
62
+ /**
63
+ * Web Script constructor
64
+ */
62
65
public OAuthReturn ()
63
66
{
64
67
}
@@ -69,7 +72,8 @@ public void execute(WebScriptRequest req, WebScriptResponse resp) throws IOExcep
69
72
String verifier = req .getParameter (PARAM_OAUTH_VERIFIER ),
70
73
connectorId = req .getParameter (PARAM_CONNECTOR_ID ),
71
74
endpointName = req .getParameter (PARAM_ENDPOINT_ID ),
72
- providerName = req .getParameter (PARAM_PROVIDER_ID );
75
+ providerName = req .getParameter (PARAM_PROVIDER_ID ),
76
+ reqToken = req .getParameter (HttpOAuthConnector .OAUTH_TOKEN );
73
77
74
78
if (verifier == null || verifier .length () == 0 )
75
79
{
@@ -84,7 +88,8 @@ public void execute(WebScriptRequest req, WebScriptResponse resp) throws IOExcep
84
88
throw new WebScriptException ("No provider name was specified" );
85
89
}
86
90
87
- String pn = PREFS_BASE + providerName ;
91
+ // JSON path below which data is stored, using dot notation
92
+ String jsonPath = PREFS_BASE + providerName + "." + PREF_DATA ;
88
93
89
94
Map <String , Object > scriptParams = this .getContainer ().getScriptParameters ();
90
95
scriptRemote = (ScriptRemote ) scriptParams .get ("remote" );
@@ -97,45 +102,22 @@ public void execute(WebScriptRequest req, WebScriptResponse resp) throws IOExcep
97
102
String authToken = "" , authTokenSecret = "" ;
98
103
99
104
// Load the current auth data
100
- Response authDataResp = alfrescoConnector . get ( USER_TOKEN_URL + "?filter=" + pn + "." + PREF_DATA );
105
+ Response authDataResp = getAccessTokenData ( alfrescoConnector , jsonPath );
101
106
if (authDataResp .getStatus ().getCode () == Status .STATUS_OK )
102
107
{
103
108
String authData = authDataResp .getResponse ();
104
- JSONObject authObj = null ;
105
109
Map <String , String > authParams = null ;
106
110
try
107
111
{
108
112
if (authData .length () > 0 )
109
113
{
110
- authObj = new JSONObject (authData );
111
- for (String k : pn .split ("\\ ." ))
112
- {
113
- if (authObj != null )
114
- {
115
- try
116
- {
117
- authObj = authObj .getJSONObject (k );
118
- }
119
- catch (JSONException e )
120
- {
121
- authObj = null ;
122
- }
123
- }
124
- }
125
- if (authObj != null && authObj .length () > 0 )
114
+ String data = jsonStringByPath (authData , jsonPath );
115
+ if (data != null && data .length () > 0 )
126
116
{
127
- String data = authObj .optString ("data" , "" );
128
- if (data .length () > 0 )
129
- {
130
- Map <String , String > dataMap = this .unpackData (data );
131
- // Unpack the existing parameters
132
- authToken = dataMap .get (HttpOAuthConnector .OAUTH_TOKEN );
133
- authTokenSecret = dataMap .get (HttpOAuthConnector .OAUTH_TOKEN_SECRET );
134
- }
135
- else
136
- {
137
- throw new WebScriptException (Status .STATUS_NOT_FOUND , "No OAuth data could be found for provider " + providerName );
138
- }
117
+ Map <String , String > dataMap = this .unpackData (data );
118
+ // Unpack the existing parameters
119
+ authToken = dataMap .get (HttpOAuthConnector .OAUTH_TOKEN );
120
+ authTokenSecret = dataMap .get (HttpOAuthConnector .OAUTH_TOKEN_SECRET );
139
121
}
140
122
else
141
123
{
@@ -150,6 +132,10 @@ public void execute(WebScriptRequest req, WebScriptResponse resp) throws IOExcep
150
132
{
151
133
throw new WebScriptException (Status .STATUS_NOT_FOUND , "Request token secret could not be found" );
152
134
}
135
+ if (reqToken != null && !reqToken .equals (authToken ))
136
+ {
137
+ throw new WebScriptException (Status .STATUS_BAD_REQUEST , "Stored request token and returned token do not match" );
138
+ }
153
139
154
140
authParams = requestAccessToken (endpointName , authToken , authTokenSecret , verifier , req , oauthConnector );
155
141
}
@@ -162,11 +148,6 @@ public void execute(WebScriptRequest req, WebScriptResponse resp) throws IOExcep
162
148
{
163
149
throw new WebScriptException ("Could not decode OAuth data JSON response" , e );
164
150
}
165
- /*
166
- catch (ConnectorServiceException e)
167
- {
168
- throw new WebScriptException("Could not locate OAuth connector", e);
169
- }*/
170
151
171
152
if (authParams .size () == 0 )
172
153
{
@@ -182,13 +163,10 @@ public void execute(WebScriptRequest req, WebScriptResponse resp) throws IOExcep
182
163
}
183
164
184
165
// Persist the data
185
- Response writeAccessTokenResponse = this .storeAccessTokenData (authParams , pn );
166
+ Response writeAccessTokenResponse = this .storeAccessTokenData (alfrescoConnector , jsonPath , authParams );
186
167
if (writeAccessTokenResponse .getStatus ().getCode () == Status .STATUS_OK )
187
168
{
188
- String redirectPage = req .getParameter (PARAM_REDIRECT_PAGE ).indexOf ('/' ) == 0 ? req .getParameter (PARAM_REDIRECT_PAGE ) : "/" + req .getParameter (PARAM_REDIRECT_PAGE ),
189
- redirectLocation = req .getServerPath () + req .getContextPath () + (redirectPage != null ? redirectPage : "" );
190
- resp .addHeader (WebScriptResponse .HEADER_LOCATION , redirectLocation );
191
- resp .setStatus (Status .STATUS_MOVED_TEMPORARILY );
169
+ executeRedirect (req , resp );
192
170
}
193
171
else
194
172
{
@@ -198,8 +176,15 @@ public void execute(WebScriptRequest req, WebScriptResponse resp) throws IOExcep
198
176
}
199
177
else
200
178
{
201
- // TODO if resp is 401 then redirect to original page
202
- throw new WebScriptException (authDataResp .getStatus ().getCode (), "A problem occurred while loading the OAuth token data (code " + authDataResp .getStatus ().getCode () + ")" );
179
+ // If resp is 401 then redirect to original page
180
+ if (authDataResp .getStatus ().getCode () == 401 )
181
+ {
182
+ executeRedirect (req , resp );
183
+ }
184
+ else
185
+ {
186
+ throw new WebScriptException (authDataResp .getStatus ().getCode (), "A problem occurred while loading the OAuth token data (code " + authDataResp .getStatus ().getCode () + ")" );
187
+ }
203
188
}
204
189
}
205
190
@@ -225,35 +210,69 @@ private Map<String, String> unpackData(String body)
225
210
return m ;
226
211
}
227
212
228
- private Map <String , String > requestAccessToken (
229
- String endpointName , String authToken ,
230
- String authTokenSecret , String verifier ,
231
- WebScriptRequest req ,
232
- ScriptRemoteConnector oauthConnector ) throws HttpException , IOException
213
+ /**
214
+ * Pack OAuth parameters into a form suitable for putting into a single string
215
+ *
216
+ * @param params
217
+ * @return
218
+ */
219
+ private String packData (Map <String , String > params )
233
220
{
234
- Map <String , String > authParams ;
235
- // Add the verifier
236
- //Connector oauthConnector = connectorService.getConnector(connectorName);
237
- HttpClient client = new HttpClient ();
238
-
239
- // TODO Parameterise the access token path
240
- String postUri = req .getServerPath () + req .getContextPath () + URL_PROXY_SERVLET + "/" + endpointName + getAccessTokenUrl (oauthConnector );
241
- HttpMethod method = new PostMethod (postUri );
242
- method .addRequestHeader (HttpOAuthConnector .HEADER_OAUTH_DATA , HttpOAuthConnector .OAUTH_TOKEN + "=\" " + authToken + "\" ," +
243
- HttpOAuthConnector .OAUTH_TOKEN_SECRET + "=\" " + authTokenSecret + "\" ," + PARAM_OAUTH_VERIFIER + "=\" " + verifier + "\" " );
244
- int statusCode = client .executeMethod (method );
245
- if (statusCode == Status .STATUS_OK )
221
+ StringBuffer newdata = new StringBuffer ();
222
+ // add each key,val pair to the string
223
+ for (Map .Entry <String , String > p : params .entrySet ())
246
224
{
247
- // do something with the input stream, which contains the new parameters in the body
248
- byte [] responseBody = method .getResponseBody ();
249
- String tokenResp = new String (responseBody , Charset .forName ("UTF-8" ));
250
- authParams = this .unpackData (tokenResp );
251
- return authParams ;
225
+ newdata .append (newdata .length () > 0 ? "&" : "" );
226
+ newdata .append (p .getKey () + "=" + p .getValue ());
252
227
}
253
- else
228
+ return newdata .toString ();
229
+ }
230
+
231
+ /**
232
+ * Look up a string value in some JSON mark-up, using a path expressed in dot notation
233
+ *
234
+ * @param jsonSrc
235
+ * @param path
236
+ * @return
237
+ * @throws JSONException
238
+ */
239
+ private String jsonStringByPath (String jsonSrc , String path ) throws JSONException
240
+ {
241
+ String str = null ,
242
+ objPath = path .substring (0 , path .lastIndexOf ('.' )),
243
+ strKey = path .substring (path .lastIndexOf ('.' ) + 1 );
244
+ JSONObject authObj = new JSONObject (jsonSrc );
245
+ for (String k : objPath .split ("\\ ." ))
254
246
{
255
- throw new WebScriptException (statusCode , "A problem occurred while requesting the access token" );
247
+ if (authObj != null )
248
+ {
249
+ try
250
+ {
251
+ authObj = authObj .getJSONObject (k );
252
+ }
253
+ catch (JSONException e )
254
+ {
255
+ authObj = null ;
256
+ }
257
+ }
256
258
}
259
+ if (authObj != null && authObj .length () > 0 )
260
+ {
261
+ str = authObj .optString (strKey , "" );
262
+ }
263
+ return str ;
264
+ }
265
+
266
+ /**
267
+ * Load OAuth data from the repository
268
+ *
269
+ * @param connector
270
+ * @param path
271
+ * @return
272
+ */
273
+ private Response getAccessTokenData (ScriptRemoteConnector connector , String path )
274
+ {
275
+ return connector .get (USER_TOKEN_URL + "?filter=" + path );
257
276
}
258
277
259
278
/**
@@ -263,29 +282,28 @@ private Map<String, String> requestAccessToken(
263
282
* @param base
264
283
* @return
265
284
*/
266
- private Response storeAccessTokenData (Map <String , String > authParams , String base )
285
+ private Response storeAccessTokenData (ScriptRemoteConnector connector , String path , Map <String , String > authParams )
267
286
{
268
- ScriptRemoteConnector connector = scriptRemote .connect ();
269
- String [] baseParts = base .split ("\\ ." );
287
+ String basePath = path .substring (0 , path .lastIndexOf ('.' )),
288
+ strKey = path .substring (path .lastIndexOf ('.' ) + 1 );
289
+ String [] baseParts = basePath .split ("\\ ." );
270
290
try
271
291
{
272
- StringBuffer newdata = new StringBuffer ();
292
+ // start main object
273
293
JSONWriter currJSON = new JSONStringer ().object ();
274
- for (String k : baseParts )
275
- {
276
- currJSON .key (k ).object ();
277
- }
278
- // add each auth parameter to currJSON
279
- for (Map .Entry <String , String > p : authParams .entrySet ())
294
+ // start all outer objects
295
+ for (int i = 0 ; i < baseParts .length ; i ++)
280
296
{
281
- newdata .append (newdata .length () > 0 ? "&" : "" );
282
- newdata .append (p .getKey () + "=" + p .getValue ());
297
+ currJSON .key (baseParts [i ]).object ();
283
298
}
284
- currJSON .key (PREF_DATA ).value (newdata .toString ());
299
+ // add string value
300
+ currJSON .key (strKey ).value (packData (authParams ));
301
+ // end each outer object
285
302
for (int i = 0 ; i < baseParts .length ; i ++)
286
303
{
287
304
currJSON .endObject ();
288
305
}
306
+ // end main object
289
307
currJSON .endObject ();
290
308
String postBody = currJSON .toString ();
291
309
@@ -296,6 +314,63 @@ private Response storeAccessTokenData(Map<String, String> authParams, String bas
296
314
throw new WebScriptException ("Could not encode OAuth data in JSON format" , e );
297
315
}
298
316
}
317
+
318
+ /**
319
+ * Obtain a permanent access token from the OAuth service, utilising the OAuth connector to
320
+ * perform the necessary signing of requests.
321
+ *
322
+ * @param endpointName
323
+ * @param authToken
324
+ * @param authTokenSecret
325
+ * @param verifier
326
+ * @param req
327
+ * @param oauthConnector
328
+ * @return
329
+ * @throws HttpException
330
+ * @throws IOException
331
+ */
332
+ private Map <String , String > requestAccessToken (
333
+ String endpointName , String authToken ,
334
+ String authTokenSecret , String verifier ,
335
+ WebScriptRequest req ,
336
+ ScriptRemoteConnector oauthConnector ) throws HttpException , IOException
337
+ {
338
+ Map <String , String > authParams ;
339
+ HttpClient client = new HttpClient ();
340
+
341
+ String postUri = req .getServerPath () + req .getContextPath () + URL_PROXY_SERVLET + "/" + endpointName + getAccessTokenUrl (oauthConnector );
342
+ HttpMethod method = new PostMethod (postUri );
343
+ method .addRequestHeader (HttpOAuthConnector .HEADER_OAUTH_DATA , HttpOAuthConnector .OAUTH_TOKEN + "=\" " + authToken + "\" ," +
344
+ HttpOAuthConnector .OAUTH_TOKEN_SECRET + "=\" " + authTokenSecret + "\" ," + PARAM_OAUTH_VERIFIER + "=\" " + verifier + "\" " );
345
+ int statusCode = client .executeMethod (method );
346
+ if (statusCode == Status .STATUS_OK )
347
+ {
348
+ // do something with the input stream, which contains the new parameters in the body
349
+ byte [] responseBody = method .getResponseBody ();
350
+ String tokenResp = new String (responseBody , Charset .forName ("UTF-8" ));
351
+ authParams = this .unpackData (tokenResp );
352
+ return authParams ;
353
+ }
354
+ else
355
+ {
356
+ throw new WebScriptException (statusCode , "A problem occurred while requesting the access token" );
357
+ }
358
+ }
359
+
360
+ /**
361
+ * Redirect the user to the location that was specified in the request parameter, or
362
+ * to the webapp context root if this was not found
363
+ *
364
+ * @param req
365
+ * @param resp
366
+ */
367
+ private void executeRedirect (WebScriptRequest req , WebScriptResponse resp )
368
+ {
369
+ String redirectPage = req .getParameter (PARAM_REDIRECT_PAGE ).indexOf ('/' ) == 0 ? req .getParameter (PARAM_REDIRECT_PAGE ) : "/" + req .getParameter (PARAM_REDIRECT_PAGE ),
370
+ redirectLocation = req .getServerPath () + req .getContextPath () + (redirectPage != null ? redirectPage : "" );
371
+ resp .addHeader (WebScriptResponse .HEADER_LOCATION , redirectLocation );
372
+ resp .setStatus (Status .STATUS_MOVED_TEMPORARILY );
373
+ }
299
374
300
375
public ScriptRemote getScriptRemote ()
301
376
{
0 commit comments