]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/c-apps/oils_auth.c
4a08d408c225bc6045802cde4d1e64d40396060e
[working/Evergreen.git] / Open-ILS / src / c-apps / oils_auth.c
1 #include "opensrf/osrf_app_session.h"
2 #include "opensrf/osrf_application.h"
3 #include "opensrf/osrf_settings.h"
4 #include "opensrf/osrf_json.h"
5 #include "opensrf/log.h"
6 #include "openils/oils_utils.h"
7 #include "openils/oils_constants.h"
8 #include "openils/oils_event.h"
9
10 #define OILS_AUTH_CACHE_PRFX "oils_auth_"
11
12 #define MODULENAME "open-ils.auth"
13
14 #define OILS_AUTH_OPAC "opac"
15 #define OILS_AUTH_STAFF "staff"
16 #define OILS_AUTH_TEMP "temp"
17
18 int osrfAppInitialize();
19 int osrfAppChildInit();
20
21 static int _oilsAuthOPACTimeout = 0;
22 static int _oilsAuthStaffTimeout = 0;
23 static int _oilsAuthOverrideTimeout = 0;
24
25
26 /**
27         @brief Initialize the application by registering functions for method calls.
28         @return Zero in all cases.
29 */
30 int osrfAppInitialize() {
31
32         osrfLogInfo(OSRF_LOG_MARK, "Initializing Auth Server...");
33
34         /* load and parse the IDL */
35         if (!oilsInitIDL(NULL)) return 1; /* return non-zero to indicate error */
36
37         osrfAppRegisterMethod(
38                 MODULENAME,
39                 "open-ils.auth.authenticate.init",
40                 "oilsAuthInit",
41                 "Start the authentication process and returns the intermediate authentication seed"
42                 " PARAMS( username )", 1, 0 );
43
44         osrfAppRegisterMethod(
45                 MODULENAME,
46                 "open-ils.auth.authenticate.complete",
47                 "oilsAuthComplete",
48                 "Completes the authentication process.  Returns an object like so: "
49                 "{authtoken : <token>, authtime:<time>}, where authtoken is the login "
50                 "token and authtime is the number of seconds the session will be active"
51                 "PARAMS(username, md5sum( seed + md5sum( password ) ), type, org_id ) "
52                 "type can be one of 'opac','staff', or 'temp' and it defaults to 'staff' "
53                 "org_id is the location at which the login should be considered "
54                 "active for login timeout purposes", 1, 0 );
55
56         osrfAppRegisterMethod(
57                 MODULENAME,
58                 "open-ils.auth.session.retrieve",
59                 "oilsAuthSessionRetrieve",
60                 "Pass in the auth token and this retrieves the user object.  The auth "
61                 "timeout is reset when this call is made "
62                 "Returns the user object (password blanked) for the given login session "
63                 "PARAMS( authToken )", 1, 0 );
64
65         osrfAppRegisterMethod(
66                 MODULENAME,
67                 "open-ils.auth.session.delete",
68                 "oilsAuthSessionDelete",
69                 "Destroys the given login session "
70                 "PARAMS( authToken )",  1, 0 );
71
72         osrfAppRegisterMethod(
73                 MODULENAME,
74                 "open-ils.auth.session.reset_timeout",
75                 "oilsAuthResetTimeout",
76                 "Resets the login timeout for the given session "
77                 "Returns an ILS Event with payload = session_timeout of session "
78                 "if found, otherwise returns the NO_SESSION event"
79                 "PARAMS( authToken )", 1, 0 );
80
81         return 0;
82 }
83
84 /**
85         @brief Dummy placeholder for initializing a server drone.
86
87         There is nothing to do, so do nothing.
88 */
89 int osrfAppChildInit() {
90         return 0;
91 }
92
93 /**
94         @brief Implement the init method.
95         @param ctx The method context.
96         @return Zero if successful, or -1 if not.
97
98         Method parameters:
99         - username
100
101         Return to client: Intermediate authentication seed.
102
103         Combine the username with a timestamp and process ID, and take an md5 hash of the result.
104         Store the hash in memcache, with a key based on the username.  Then return the hash to
105         the client.
106
107         However: if the username includes one or more embedded blank spaces, return a dummy
108         hash without storing anything in memcache.  The dummy will never match a stored hash, so
109         any attempt to authenticate with it will fail.
110 */
111 int oilsAuthInit( osrfMethodContext* ctx ) {
112         OSRF_METHOD_VERIFY_CONTEXT(ctx);
113
114         char* username  = jsonObjectToSimpleString( jsonObjectGetIndex(ctx->params, 0) );
115         if( username ) {
116
117                 jsonObject* resp;
118
119                 if( strchr( username, ' ' ) ) {
120
121                         // Embedded spaces are not allowed in a username.  Use "x" as a dummy
122                         // seed.  It will never be a valid seed because 'x' is not a hex digit.
123                         resp = jsonNewObject( "x" );
124
125                 } else {
126
127                         // Build a key and a seed; store them in memcache.
128                         char* key  = va_list_to_string( "%s%s", OILS_AUTH_CACHE_PRFX, username );
129                         char* seed = md5sum( "%d.%ld.%s", (int) time(NULL), (long) getpid(), username );
130                         osrfCachePutString( key, seed, 30 );
131
132                         osrfLogDebug( OSRF_LOG_MARK, "oilsAuthInit(): has seed %s and key %s", seed, key );
133
134                         // Build a returnable object containing the seed.
135                         resp = jsonNewObject( seed );
136
137                         free( seed );
138                         free( key );
139                 }
140
141                 // Return the seed to the client.
142                 osrfAppRespondComplete( ctx, resp );
143
144                 jsonObjectFree(resp);
145                 free(username);
146                 return 0;
147         }
148
149         return -1;  // Error: no username parameter
150 }
151
152 /**
153         Verifies that the user has permission to login with the
154         given type.  If the permission fails, an oilsEvent is returned
155         to the caller.
156         @return -1 if the permission check failed, 0 if the permission
157         is granted
158 */
159 static int oilsAuthCheckLoginPerm(
160                 osrfMethodContext* ctx, const jsonObject* userObj, const char* type ) {
161
162         if(!(userObj && type)) return -1;
163         oilsEvent* perm = NULL;
164
165         if(!strcasecmp(type, OILS_AUTH_OPAC)) {
166                 char* permissions[] = { "OPAC_LOGIN" };
167                 perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
168
169         } else if(!strcasecmp(type, OILS_AUTH_STAFF)) {
170                 char* permissions[] = { "STAFF_LOGIN" };
171                 perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
172
173         } else if(!strcasecmp(type, OILS_AUTH_TEMP)) {
174                 char* permissions[] = { "STAFF_LOGIN" };
175                 perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
176         }
177
178         if(perm) {
179                 osrfAppRespondComplete( ctx, oilsEventToJSON(perm) );
180                 oilsEventFree(perm);
181                 return -1;
182         }
183
184         return 0;
185 }
186
187 /**
188         Returns 1 if the password provided matches the user's real password
189         Returns 0 otherwise
190         Returns -1 on error
191 */
192 static int oilsAuthVerifyPassword( const osrfMethodContext* ctx,
193                 const jsonObject* userObj, const char* uname, const char* password ) {
194
195         int ret = 0;
196         char* realPassword = oilsFMGetString( userObj, "passwd" ); /**/
197         char* seed = osrfCacheGetString( "%s%s", OILS_AUTH_CACHE_PRFX, uname ); /**/
198
199         if(!seed) {
200                 free(realPassword);
201                 return osrfAppRequestRespondException( ctx->session,
202                         ctx->request, "No authentication seed found. "
203                         "open-ils.auth.authenticate.init must be called first");
204         }
205
206         osrfLogInternal(OSRF_LOG_MARK, "oilsAuth retrieved real password: [%s]", realPassword);
207         osrfLogDebug(OSRF_LOG_MARK,  "oilsAuth retrieved seed from cache: %s", seed );
208         char* maskedPw = md5sum( "%s%s", seed, realPassword );
209         free(realPassword);
210         free(seed);
211
212         if(!maskedPw)
213                 return -1;
214
215         osrfLogDebug(OSRF_LOG_MARK,  "oilsAuth generated masked password %s. "
216                         "Testing against provided password %s", maskedPw, password );
217
218         if( !strcmp( maskedPw, password ) ) ret = 1;
219
220         free(maskedPw);
221
222         return ret;
223 }
224
225 /**
226         Calculates the login timeout
227         1. If orgloc is 1 or greater and has a timeout specified as an
228         org unit setting, it is used
229         2. If orgloc is not valid, we check the org unit auth timeout
230         setting for the home org unit of the user logging in
231         3. If that setting is not defined, we use the configured defaults
232 */
233 static double oilsAuthGetTimeout( const jsonObject* userObj, const char* type, double orgloc ) {
234
235         if(!_oilsAuthOPACTimeout) { /* Load the default timeouts */
236
237                 jsonObject* value_obj;
238
239                 value_obj = osrf_settings_host_value_object(
240                         "/apps/open-ils.auth/app_settings/default_timeout/opac" );
241                 _oilsAuthOPACTimeout = jsonObjectGetNumber(value_obj);
242                 jsonObjectFree(value_obj);
243
244                 value_obj = osrf_settings_host_value_object(
245                         "/apps/open-ils.auth/app_settings/default_timeout/staff" );
246                 _oilsAuthStaffTimeout = jsonObjectGetNumber(value_obj);
247                 jsonObjectFree(value_obj);
248
249                 value_obj = osrf_settings_host_value_object(
250                                 "/apps/open-ils.auth/app_settings/default_timeout/temp" );
251                 _oilsAuthOverrideTimeout = jsonObjectGetNumber(value_obj);
252                 jsonObjectFree(value_obj);
253
254
255                 osrfLogInfo(OSRF_LOG_MARK,
256                                 "Set default auth timeouts: opac => %d : staff => %d : temp => %d",
257                                 _oilsAuthOPACTimeout, _oilsAuthStaffTimeout, _oilsAuthOverrideTimeout );
258         }
259
260         char* setting = NULL;
261
262         double home_ou = jsonObjectGetNumber( oilsFMGetObject( userObj, "home_ou" ) );
263         if(orgloc < 1) orgloc = (int) home_ou;
264
265         if(!strcmp(type, OILS_AUTH_OPAC))
266                 setting = OILS_ORG_SETTING_OPAC_TIMEOUT;
267         else if(!strcmp(type, OILS_AUTH_STAFF))
268                 setting = OILS_ORG_SETTING_STAFF_TIMEOUT;
269         else if(!strcmp(type, OILS_AUTH_TEMP))
270                 setting = OILS_ORG_SETTING_TEMP_TIMEOUT;
271
272         char* timeout = oilsUtilsFetchOrgSetting( orgloc, setting );
273
274         if(!timeout) {
275                 if( orgloc != home_ou ) {
276                         osrfLogDebug(OSRF_LOG_MARK, "Auth timeout not defined for org %d, "
277                                                                 "trying home_ou %d", orgloc, home_ou );
278                         timeout = oilsUtilsFetchOrgSetting( (int) home_ou, setting );
279                 }
280                 if(!timeout) {
281                         if(!strcmp(type, OILS_AUTH_STAFF)) return _oilsAuthStaffTimeout;
282                         if(!strcmp(type, OILS_AUTH_TEMP)) return _oilsAuthOverrideTimeout;
283                         return _oilsAuthOPACTimeout;
284                 }
285         }
286
287         double t = atof(timeout);
288         free(timeout);
289         return t ;
290 }
291
292 /*
293         Adds the authentication token to the user cache.  The timeout for the
294         auth token is based on the type of login as well as (if type=='opac')
295         the org location id.
296         Returns the event that should be returned to the user.
297         Event must be freed
298 */
299 static oilsEvent* oilsAuthHandleLoginOK( jsonObject* userObj, const char* uname,
300                 const char* type, double orgloc, const char* workstation ) {
301
302         oilsEvent* response;
303
304         double timeout;
305         char* wsorg = jsonObjectToSimpleString(oilsFMGetObject(userObj, "ws_ou"));
306         if(wsorg) { /* if there is a workstation, use it for the timeout */
307                 osrfLogDebug( OSRF_LOG_MARK,
308                                 "Auth session trying workstation id %d for auth timeout", atoi(wsorg));
309                 timeout = oilsAuthGetTimeout( userObj, type, atoi(wsorg) );
310                 free(wsorg);
311         } else {
312                 osrfLogDebug( OSRF_LOG_MARK,
313                                 "Auth session trying org from param [%d] for auth timeout", orgloc );
314                 timeout = oilsAuthGetTimeout( userObj, type, orgloc );
315         }
316         osrfLogDebug(OSRF_LOG_MARK, "Auth session timeout for %s: %f", uname, timeout );
317
318         char* string = va_list_to_string(
319                         "%d.%ld.%s", (long) getpid(), time(NULL), uname );
320         char* authToken = md5sum(string);
321         char* authKey = va_list_to_string(
322                         "%s%s", OILS_AUTH_CACHE_PRFX, authToken );
323
324         const char* ws = (workstation) ? workstation : "";
325         osrfLogActivity(OSRF_LOG_MARK,
326                 "successful login: username=%s, authtoken=%s, workstation=%s", uname, authToken, ws );
327
328         oilsFMSetString( userObj, "passwd", "" );
329         jsonObject* cacheObj = jsonParseFmt("{\"authtime\": %f}", timeout);
330         jsonObjectSetKey( cacheObj, "userobj", jsonObjectClone(userObj));
331
332         osrfCachePutObject( authKey, cacheObj, timeout );
333         jsonObjectFree(cacheObj);
334         osrfLogInternal(OSRF_LOG_MARK, "oilsAuthHandleLoginOK(): Placed user object into cache");
335         jsonObject* payload = jsonParseFmt(
336                 "{ \"authtoken\": \"%s\", \"authtime\": %f }", authToken, timeout );
337
338         response = oilsNewEvent2( OSRF_LOG_MARK, OILS_EVENT_SUCCESS, payload );
339         free(string); free(authToken); free(authKey);
340         jsonObjectFree(payload);
341
342         return response;
343 }
344
345 static oilsEvent* oilsAuthVerifyWorkstation(
346                 const osrfMethodContext* ctx, jsonObject* userObj, const char* ws ) {
347         osrfLogInfo(OSRF_LOG_MARK, "Attaching workstation to user at login: %s", ws);
348         jsonObject* workstation = oilsUtilsFetchWorkstationByName(ws);
349         if(!workstation || workstation->type == JSON_NULL) {
350                 jsonObjectFree(workstation);
351                 return oilsNewEvent(OSRF_LOG_MARK, "WORKSTATION_NOT_FOUND");
352         }
353         long wsid = oilsFMGetObjectId(workstation);
354         LONG_TO_STRING(wsid);
355         char* orgid = oilsFMGetString(workstation, "owning_lib");
356         oilsFMSetString(userObj, "wsid", LONGSTR);
357         oilsFMSetString(userObj, "ws_ou", orgid);
358         free(orgid);
359         jsonObjectFree(workstation);
360         return NULL;
361 }
362
363
364
365 /* see if the card used to login is marked as barred */
366 static oilsEvent* oilsAuthCheckCard( const char* barcode ) {
367         if(!barcode) return NULL;
368         osrfLogDebug(OSRF_LOG_MARK, "Checking to see if barcode %s is active", barcode);
369
370         jsonObject* params = jsonParseFmt("{\"barcode\":\"%s\"}", barcode);
371         jsonObject* card = oilsUtilsQuickReq(
372                 "open-ils.cstore", "open-ils.cstore.direct.actor.card.search", params );
373         jsonObjectFree(params);
374
375         char* active = oilsFMGetString(card, "active");
376         jsonObjectFree(card);
377
378         oilsEvent* return_event = NULL;
379         if( ! oilsUtilsIsDBTrue(active) ) {
380                 osrfLogInfo(OSRF_LOG_MARK, "barcode %s is not active, returning event", barcode);
381                 return_event = oilsNewEvent(OSRF_LOG_MARK, "PATRON_CARD_INACTIVE");
382         }
383
384         free(active);
385         return return_event;
386 }
387
388
389
390 int oilsAuthComplete( osrfMethodContext* ctx ) {
391         OSRF_METHOD_VERIFY_CONTEXT(ctx);
392
393         const jsonObject* args  = jsonObjectGetIndex(ctx->params, 0);
394
395         const char* uname       = jsonObjectGetString(jsonObjectGetKeyConst(args, "username"));
396         const char* password    = jsonObjectGetString(jsonObjectGetKeyConst(args, "password"));
397         const char* type        = jsonObjectGetString(jsonObjectGetKeyConst(args, "type"));
398         double orgloc           = jsonObjectGetNumber(jsonObjectGetKeyConst(args, "org"));
399         const char* workstation = jsonObjectGetString(jsonObjectGetKeyConst(args, "workstation"));
400         const char* barcode     = jsonObjectGetString(jsonObjectGetKeyConst(args, "barcode"));
401
402         const char* ws = (workstation) ? workstation : "";
403
404
405         if(!type) type = OILS_AUTH_STAFF;
406
407         if( !( (uname || barcode) && password) ) {
408                 return osrfAppRequestRespondException( ctx->session, ctx->request,
409                         "username/barcode and password required for method: %s", ctx->method->name );
410         }
411
412         oilsEvent* response = NULL;
413         jsonObject* userObj = NULL;
414
415         if(uname) {
416                 userObj = oilsUtilsFetchUserByUsername( uname );
417                 if( userObj && JSON_NULL == userObj->type ) {
418                         jsonObjectFree( userObj );
419                         userObj = NULL;         // username not found
420                 }
421         }
422         else if(barcode)
423                  userObj = oilsUtilsFetchUserByBarcode( barcode );
424
425         if(!userObj) {
426                 response = oilsNewEvent( OSRF_LOG_MARK, OILS_EVENT_AUTH_FAILED );
427                 osrfLogInfo(OSRF_LOG_MARK,  "failed login: username=%s, barcode=%s, workstation=%s",
428                                 uname, (barcode ? barcode : "(none)"), ws );
429                 osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
430                 oilsEventFree(response);
431                 return 0;
432         }
433
434         /* first let's see if they have the right credentials */
435         int passOK = -1;
436         if(uname)
437                 passOK = oilsAuthVerifyPassword( ctx, userObj, uname, password );
438         else if (barcode)
439                 passOK = oilsAuthVerifyPassword( ctx, userObj, barcode, password );
440
441         if( passOK < 0 ) {
442                 jsonObjectFree(userObj);
443                 return passOK;
444         }
445
446         /* first see if their account is inactive */
447         char* active = oilsFMGetString(userObj, "active");
448         if( !oilsUtilsIsDBTrue(active) ) {
449                 if( passOK )
450                         response = oilsNewEvent( OSRF_LOG_MARK, "PATRON_INACTIVE" );
451                 else
452                         response = oilsNewEvent( OSRF_LOG_MARK, OILS_EVENT_AUTH_FAILED );
453
454                 osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
455                 oilsEventFree(response);
456                 jsonObjectFree(userObj);
457                 free(active);
458                 return 0;
459         }
460         free(active);
461
462         /* then see if the barcode they used is active */
463         if( barcode && ctx && userObj && (response = oilsAuthCheckCard( barcode )) ) {
464                 osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
465                 oilsEventFree(response);
466                 jsonObjectFree(userObj);
467                 return 0;
468         }
469
470
471         /* check to see if the user is even allowed to login */
472         if( oilsAuthCheckLoginPerm( ctx, userObj, type ) == -1 ) {
473                 jsonObjectFree(userObj);
474                 return 0;
475         }
476
477
478         /* if a workstation is defined, flesh the user with the workstation info */
479         if( workstation != NULL ) {
480                 osrfLogDebug(OSRF_LOG_MARK, "Workstation is %s", workstation);
481                 response = oilsAuthVerifyWorkstation( ctx, userObj, workstation );
482                 if(response) {
483                         jsonObjectFree(userObj);
484                         osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
485                         oilsEventFree(response);
486                         return 0;
487                 }
488
489         } else {
490                 /* otherwise, use the home org as the workstation org on the user */
491                 char* orgid = oilsFMGetString(userObj, "home_ou");
492                 oilsFMSetString(userObj, "ws_ou", orgid);
493                 free(orgid);
494         }
495
496         char* freeable_uname = NULL;
497         if(!uname) {
498                 uname = freeable_uname = oilsFMGetString( userObj, "usrname" );
499         }
500
501         if( passOK ) {
502                 response = oilsAuthHandleLoginOK( userObj, uname, type, orgloc, workstation );
503
504         } else {
505                 response = oilsNewEvent( OSRF_LOG_MARK, OILS_EVENT_AUTH_FAILED );
506                 osrfLogInfo(OSRF_LOG_MARK,  "failed login: username=%s, barcode=%s, workstation=%s",
507                                 uname, (barcode ? barcode : "(none)"), ws );
508         }
509
510         jsonObjectFree(userObj);
511         osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
512         oilsEventFree(response);
513
514         if(freeable_uname)
515                 free(freeable_uname);
516
517         return 0;
518 }
519
520
521
522 int oilsAuthSessionDelete( osrfMethodContext* ctx ) {
523         OSRF_METHOD_VERIFY_CONTEXT(ctx);
524
525         const char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
526         jsonObject* resp = NULL;
527
528         if( authToken ) {
529                 osrfLogDebug(OSRF_LOG_MARK, "Removing auth session: %s", authToken );
530                 char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
531                 osrfCacheRemove(key);
532                 resp = jsonNewObject(authToken); /**/
533                 free(key);
534         }
535
536         osrfAppRespondComplete( ctx, resp );
537         jsonObjectFree(resp);
538         return 0;
539 }
540
541 /**
542         Resets the auth login timeout
543         @return The event object, OILS_EVENT_SUCCESS, or OILS_EVENT_NO_SESSION
544 */
545 static oilsEvent*  _oilsAuthResetTimeout( const char* authToken ) {
546         if(!authToken) return NULL;
547
548         oilsEvent* evt = NULL;
549         double timeout;
550
551         osrfLogDebug(OSRF_LOG_MARK, "Resetting auth timeout for session %s", authToken);
552         char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken );
553         jsonObject* cacheObj = osrfCacheGetObject( key );
554
555         if(!cacheObj) {
556                 osrfLogInfo(OSRF_LOG_MARK, "No user in the cache exists with key %s", key);
557                 evt = oilsNewEvent(OSRF_LOG_MARK, OILS_EVENT_NO_SESSION);
558
559         } else {
560
561                 timeout = jsonObjectGetNumber( jsonObjectGetKeyConst( cacheObj, "authtime"));
562                 osrfCacheSetExpire( timeout, key );
563                 jsonObject* payload = jsonNewNumberObject(timeout);
564                 evt = oilsNewEvent2(OSRF_LOG_MARK, OILS_EVENT_SUCCESS, payload);
565                 jsonObjectFree(payload);
566                 jsonObjectFree(cacheObj);
567         }
568
569         free(key);
570         return evt;
571 }
572
573 int oilsAuthResetTimeout( osrfMethodContext* ctx ) {
574         OSRF_METHOD_VERIFY_CONTEXT(ctx);
575         const char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0));
576         oilsEvent* evt = _oilsAuthResetTimeout(authToken);
577         osrfAppRespondComplete( ctx, oilsEventToJSON(evt) );
578         oilsEventFree(evt);
579         return 0;
580 }
581
582
583 int oilsAuthSessionRetrieve( osrfMethodContext* ctx ) {
584         OSRF_METHOD_VERIFY_CONTEXT(ctx);
585
586         const char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0));
587         jsonObject* cacheObj = NULL;
588         oilsEvent* evt = NULL;
589
590         if( authToken ){
591
592                 evt = _oilsAuthResetTimeout(authToken);
593
594                 if( evt && strcmp(evt->event, OILS_EVENT_SUCCESS) ) {
595                         osrfAppRespondComplete( ctx, oilsEventToJSON(evt) );
596
597                 } else {
598
599                         osrfLogDebug(OSRF_LOG_MARK, "Retrieving auth session: %s", authToken);
600                         char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken );
601                         cacheObj = osrfCacheGetObject( key );
602                         if(cacheObj) {
603                                 osrfAppRespondComplete( ctx, jsonObjectGetKeyConst( cacheObj, "userobj"));
604                                 jsonObjectFree(cacheObj);
605                         } else {
606                                 oilsEvent* evt2 = oilsNewEvent(OSRF_LOG_MARK, OILS_EVENT_NO_SESSION);
607                                 osrfAppRespondComplete( ctx, oilsEventToJSON(evt2) ); /* should be event.. */
608                                 oilsEventFree(evt2);
609                         }
610                         free(key);
611                 }
612
613         } else {
614
615                 evt = oilsNewEvent(OSRF_LOG_MARK, OILS_EVENT_NO_SESSION);
616                 osrfAppRespondComplete( ctx, oilsEventToJSON(evt) );
617         }
618
619         if(evt)
620                 oilsEventFree(evt);
621
622         return 0;
623 }