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"
10 #define OILS_AUTH_CACHE_PRFX "oils_auth_"
12 #define MODULENAME "open-ils.auth"
14 #define OILS_AUTH_OPAC "opac"
15 #define OILS_AUTH_STAFF "staff"
16 #define OILS_AUTH_TEMP "temp"
17 #define OILS_AUTH_PERSISTENT "persistent"
19 // Default time for extending a persistent session: ten minutes
20 #define DEFAULT_RESET_INTERVAL 10 * 60
22 int osrfAppInitialize();
23 int osrfAppChildInit();
25 static long _oilsAuthOPACTimeout = 0;
26 static long _oilsAuthStaffTimeout = 0;
27 static long _oilsAuthOverrideTimeout = 0;
31 @brief Initialize the application by registering functions for method calls.
32 @return Zero in all cases.
34 int osrfAppInitialize() {
36 osrfLogInfo(OSRF_LOG_MARK, "Initializing Auth Server...");
38 /* load and parse the IDL */
39 if (!oilsInitIDL(NULL)) return 1; /* return non-zero to indicate error */
41 osrfAppRegisterMethod(
43 "open-ils.auth.authenticate.init",
45 "Start the authentication process and returns the intermediate authentication seed"
46 " PARAMS( username )", 1, 0 );
48 osrfAppRegisterMethod(
50 "open-ils.auth.authenticate.complete",
52 "Completes the authentication process. Returns an object like so: "
53 "{authtoken : <token>, authtime:<time>}, where authtoken is the login "
54 "token and authtime is the number of seconds the session will be active"
55 "PARAMS(username, md5sum( seed + md5sum( password ) ), type, org_id ) "
56 "type can be one of 'opac','staff', or 'temp' and it defaults to 'staff' "
57 "org_id is the location at which the login should be considered "
58 "active for login timeout purposes", 1, 0 );
60 osrfAppRegisterMethod(
62 "open-ils.auth.session.retrieve",
63 "oilsAuthSessionRetrieve",
64 "Pass in the auth token and this retrieves the user object. The auth "
65 "timeout is reset when this call is made "
66 "Returns the user object (password blanked) for the given login session "
67 "PARAMS( authToken )", 1, 0 );
69 osrfAppRegisterMethod(
71 "open-ils.auth.session.delete",
72 "oilsAuthSessionDelete",
73 "Destroys the given login session "
74 "PARAMS( authToken )", 1, 0 );
76 osrfAppRegisterMethod(
78 "open-ils.auth.session.reset_timeout",
79 "oilsAuthResetTimeout",
80 "Resets the login timeout for the given session "
81 "Returns an ILS Event with payload = session_timeout of session "
82 "if found, otherwise returns the NO_SESSION event"
83 "PARAMS( authToken )", 1, 0 );
89 @brief Dummy placeholder for initializing a server drone.
91 There is nothing to do, so do nothing.
93 int osrfAppChildInit() {
98 @brief Implement the "init" method.
99 @param ctx The method context.
100 @return Zero if successful, or -1 if not.
105 Return to client: Intermediate authentication seed.
107 Combine the username with a timestamp and process ID, and take an md5 hash of the result.
108 Store the hash in memcache, with a key based on the username. Then return the hash to
111 However: if the username includes one or more embedded blank spaces, return a dummy
112 hash without storing anything in memcache. The dummy will never match a stored hash, so
113 any attempt to authenticate with it will fail.
115 int oilsAuthInit( osrfMethodContext* ctx ) {
116 OSRF_METHOD_VERIFY_CONTEXT(ctx);
118 char* username = jsonObjectToSimpleString( jsonObjectGetIndex(ctx->params, 0) );
123 if( strchr( username, ' ' ) ) {
125 // Embedded spaces are not allowed in a username. Use "x" as a dummy
126 // seed. It will never be a valid seed because 'x' is not a hex digit.
127 resp = jsonNewObject( "x" );
131 // Build a key and a seed; store them in memcache.
132 char* key = va_list_to_string( "%s%s", OILS_AUTH_CACHE_PRFX, username );
133 char* seed = md5sum( "%d.%ld.%s", (int) time(NULL), (long) getpid(), username );
134 osrfCachePutString( key, seed, 30 );
136 osrfLogDebug( OSRF_LOG_MARK, "oilsAuthInit(): has seed %s and key %s", seed, key );
138 // Build a returnable object containing the seed.
139 resp = jsonNewObject( seed );
145 // Return the seed to the client.
146 osrfAppRespondComplete( ctx, resp );
148 jsonObjectFree(resp);
153 return -1; // Error: no username parameter
157 Verifies that the user has permission to login with the
158 given type. If the permission fails, an oilsEvent is returned
160 @return -1 if the permission check failed, 0 if the permission
163 static int oilsAuthCheckLoginPerm(
164 osrfMethodContext* ctx, const jsonObject* userObj, const char* type ) {
166 if(!(userObj && type)) return -1;
167 oilsEvent* perm = NULL;
169 if(!strcasecmp(type, OILS_AUTH_OPAC)) {
170 char* permissions[] = { "OPAC_LOGIN" };
171 perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
173 } else if(!strcasecmp(type, OILS_AUTH_STAFF)) {
174 char* permissions[] = { "STAFF_LOGIN" };
175 perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
177 } else if(!strcasecmp(type, OILS_AUTH_TEMP)) {
178 char* permissions[] = { "STAFF_LOGIN" };
179 perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
183 osrfAppRespondComplete( ctx, oilsEventToJSON(perm) );
192 Returns 1 if the password provided matches the user's real password
197 @brief Verify the password received from the client.
198 @param ctx The method context.
199 @param userObj An object from the database, representing the user.
200 @param password An obfuscated password received from the client.
201 @return 1 if the password is valid; 0 if it isn't; or -1 upon error.
203 (None of the so-called "passwords" used here are in plaintext. All have been passed
204 through at least one layer of hashing to obfuscate them.)
206 Take the password from the user object. Append it to the username seed from memcache,
207 as stored previously by a call to the init method. Take an md5 hash of the result.
208 Then compare this hash to the password received from the client.
210 In order for the two to match, other than by dumb luck, the client had to construct
211 the password it passed in the same way. That means it neded to know not only the
212 original password (either hashed or plaintext), but also the seed. The latter requirement
213 means that the client process needs either to be the same process that called the init
214 method or to receive the seed from the process that did so.
216 static int oilsAuthVerifyPassword( const osrfMethodContext* ctx,
217 const jsonObject* userObj, const char* uname, const char* password ) {
219 // Get the username seed, as stored previously in memcache by the init method
220 char* seed = osrfCacheGetString( "%s%s", OILS_AUTH_CACHE_PRFX, uname );
222 return osrfAppRequestRespondException( ctx->session,
223 ctx->request, "No authentication seed found. "
224 "open-ils.auth.authenticate.init must be called first");
227 // Get the hashed password from the user object
228 char* realPassword = oilsFMGetString( userObj, "passwd" );
230 osrfLogInternal(OSRF_LOG_MARK, "oilsAuth retrieved real password: [%s]", realPassword);
231 osrfLogDebug(OSRF_LOG_MARK, "oilsAuth retrieved seed from cache: %s", seed );
233 // Concatenate them and take an MD5 hash of the result
234 char* maskedPw = md5sum( "%s%s", seed, realPassword );
240 // This happens only if md5sum() runs out of memory
242 return -1; // md5sum() ran out of memory
245 osrfLogDebug(OSRF_LOG_MARK, "oilsAuth generated masked password %s. "
246 "Testing against provided password %s", maskedPw, password );
249 if( !strcmp( maskedPw, password ) )
258 Calculates the login timeout
259 1. If orgloc is 1 or greater and has a timeout specified as an
260 org unit setting, it is used
261 2. If orgloc is not valid, we check the org unit auth timeout
262 setting for the home org unit of the user logging in
263 3. If that setting is not defined, we use the configured defaults
265 static long oilsAuthGetTimeout( const jsonObject* userObj, const char* type, int orgloc ) {
267 if(!_oilsAuthOPACTimeout) { /* Load the default timeouts */
269 jsonObject* value_obj;
271 value_obj = osrf_settings_host_value_object(
272 "/apps/open-ils.auth/app_settings/default_timeout/opac" );
273 _oilsAuthOPACTimeout = (long) jsonObjectGetNumber(value_obj);
274 jsonObjectFree(value_obj);
276 value_obj = osrf_settings_host_value_object(
277 "/apps/open-ils.auth/app_settings/default_timeout/staff" );
278 _oilsAuthStaffTimeout = (long) jsonObjectGetNumber(value_obj);
279 jsonObjectFree(value_obj);
281 value_obj = osrf_settings_host_value_object(
282 "/apps/open-ils.auth/app_settings/default_timeout/temp" );
283 _oilsAuthOverrideTimeout = (long) jsonObjectGetNumber(value_obj);
284 jsonObjectFree(value_obj);
287 osrfLogInfo(OSRF_LOG_MARK,
288 "Set default auth timeouts: opac => %ld : staff => %ld : temp => %ld",
289 _oilsAuthOPACTimeout, _oilsAuthStaffTimeout, _oilsAuthOverrideTimeout );
292 char* setting = NULL;
294 int home_ou = (int) jsonObjectGetNumber( oilsFMGetObject( userObj, "home_ou" ));
298 if(!strcmp(type, OILS_AUTH_OPAC))
299 setting = OILS_ORG_SETTING_OPAC_TIMEOUT;
300 else if(!strcmp(type, OILS_AUTH_STAFF))
301 setting = OILS_ORG_SETTING_STAFF_TIMEOUT;
302 else if(!strcmp(type, OILS_AUTH_TEMP))
303 setting = OILS_ORG_SETTING_TEMP_TIMEOUT;
305 char* timeout = oilsUtilsFetchOrgSetting( orgloc, setting );
308 if( orgloc != home_ou ) {
309 osrfLogDebug(OSRF_LOG_MARK, "Auth timeout not defined for org %d, "
310 "trying home_ou %d", orgloc, home_ou );
311 timeout = oilsUtilsFetchOrgSetting( home_ou, setting );
314 if( !strcmp(type, OILS_AUTH_STAFF ))
315 return _oilsAuthStaffTimeout;
316 else if( !strcmp( type, OILS_AUTH_TEMP ))
317 return _oilsAuthOverrideTimeout;
319 return _oilsAuthOPACTimeout;
323 long t = (long) atof(timeout);
329 Adds the authentication token to the user cache. The timeout for the
330 auth token is based on the type of login as well as (if type=='opac')
332 Returns the event that should be returned to the user.
335 static oilsEvent* oilsAuthHandleLoginOK( jsonObject* userObj, const char* uname,
336 const char* type, int orgloc, const char* workstation ) {
341 char* wsorg = jsonObjectToSimpleString(oilsFMGetObject(userObj, "ws_ou"));
342 if(wsorg) { /* if there is a workstation, use it for the timeout */
343 osrfLogDebug( OSRF_LOG_MARK,
344 "Auth session trying workstation id %d for auth timeout", atoi(wsorg));
345 timeout = oilsAuthGetTimeout( userObj, type, atoi(wsorg) );
348 osrfLogDebug( OSRF_LOG_MARK,
349 "Auth session trying org from param [%d] for auth timeout", orgloc );
350 timeout = oilsAuthGetTimeout( userObj, type, orgloc );
352 osrfLogDebug(OSRF_LOG_MARK, "Auth session timeout for %s: %ld", uname, timeout );
354 char* string = va_list_to_string(
355 "%d.%ld.%s", (long) getpid(), time(NULL), uname );
356 char* authToken = md5sum(string);
357 char* authKey = va_list_to_string(
358 "%s%s", OILS_AUTH_CACHE_PRFX, authToken );
360 const char* ws = (workstation) ? workstation : "";
361 osrfLogActivity(OSRF_LOG_MARK,
362 "successful login: username=%s, authtoken=%s, workstation=%s", uname, authToken, ws );
364 oilsFMSetString( userObj, "passwd", "" );
365 jsonObject* cacheObj = jsonParseFmt( "{\"authtime\": %ld}", timeout );
366 jsonObjectSetKey( cacheObj, "userobj", jsonObjectClone(userObj));
368 osrfCachePutObject( authKey, cacheObj, (time_t) timeout );
369 jsonObjectFree(cacheObj);
370 osrfLogInternal(OSRF_LOG_MARK, "oilsAuthHandleLoginOK(): Placed user object into cache");
371 jsonObject* payload = jsonParseFmt(
372 "{ \"authtoken\": \"%s\", \"authtime\": %ld }", authToken, timeout );
374 response = oilsNewEvent2( OSRF_LOG_MARK, OILS_EVENT_SUCCESS, payload );
375 free(string); free(authToken); free(authKey);
376 jsonObjectFree(payload);
381 static oilsEvent* oilsAuthVerifyWorkstation(
382 const osrfMethodContext* ctx, jsonObject* userObj, const char* ws ) {
383 osrfLogInfo(OSRF_LOG_MARK, "Attaching workstation to user at login: %s", ws);
384 jsonObject* workstation = oilsUtilsFetchWorkstationByName(ws);
385 if(!workstation || workstation->type == JSON_NULL) {
386 jsonObjectFree(workstation);
387 return oilsNewEvent(OSRF_LOG_MARK, "WORKSTATION_NOT_FOUND");
389 long wsid = oilsFMGetObjectId(workstation);
390 LONG_TO_STRING(wsid);
391 char* orgid = oilsFMGetString(workstation, "owning_lib");
392 oilsFMSetString(userObj, "wsid", LONGSTR);
393 oilsFMSetString(userObj, "ws_ou", orgid);
395 jsonObjectFree(workstation);
402 @brief Implement the "complete" method.
403 @param ctx The method context.
404 @return -1 upon error; zero if successful, and if a STATUS message has been sent to the
405 client to indicate completion; a positive integer if successful but no such STATUS
406 message has been sent.
409 - a hash with some combination of the following elements:
412 - "password" (hashed with the cached seed; not plaintext)
417 The password is required. Either a username or a barcode must also be present.
419 Return to client: Intermediate authentication seed.
421 Validate the password, using the username if available, or the barcode if not. The
422 user must be active, and not barred from logging on. The barcode, if used for
423 authentication, must be active as well. The workstation, if specified, must be valid.
425 Upon deciding whether to allow the logon, return a corresponding event to the client.
427 int oilsAuthComplete( osrfMethodContext* ctx ) {
428 OSRF_METHOD_VERIFY_CONTEXT(ctx);
430 const jsonObject* args = jsonObjectGetIndex(ctx->params, 0);
432 const char* uname = jsonObjectGetString(jsonObjectGetKeyConst(args, "username"));
433 const char* password = jsonObjectGetString(jsonObjectGetKeyConst(args, "password"));
434 const char* type = jsonObjectGetString(jsonObjectGetKeyConst(args, "type"));
435 int orgloc = (int) jsonObjectGetNumber(jsonObjectGetKeyConst(args, "org"));
436 const char* workstation = jsonObjectGetString(jsonObjectGetKeyConst(args, "workstation"));
437 const char* barcode = jsonObjectGetString(jsonObjectGetKeyConst(args, "barcode"));
439 const char* ws = (workstation) ? workstation : "";
442 type = OILS_AUTH_STAFF;
444 if( !( (uname || barcode) && password) ) {
445 return osrfAppRequestRespondException( ctx->session, ctx->request,
446 "username/barcode and password required for method: %s", ctx->method->name );
449 oilsEvent* response = NULL;
450 jsonObject* userObj = NULL;
451 int card_active = 1; // boolean; assume active until proven otherwise
453 // Fetch a row from the actor.usr table, by username if available,
454 // or by barcode if not.
456 userObj = oilsUtilsFetchUserByUsername( uname );
457 if( userObj && JSON_NULL == userObj->type ) {
458 jsonObjectFree( userObj );
459 userObj = NULL; // username not found
463 // Read from actor.card by barcode
465 osrfLogInfo( OSRF_LOG_MARK, "Fetching user by barcode %s", barcode );
467 jsonObject* params = jsonParseFmt("{\"barcode\":\"%s\"}", barcode);
468 jsonObject* card = oilsUtilsQuickReq(
469 "open-ils.cstore", "open-ils.cstore.direct.actor.card.search", params );
470 jsonObjectFree( params );
472 if( card && card->type != JSON_NULL ) {
473 // Determine whether the card is active
474 char* card_active_str = oilsFMGetString( card, "active" );
475 card_active = oilsUtilsIsDBTrue( card_active_str );
476 free( card_active_str );
478 // Look up the user who owns the card
479 char* userid = oilsFMGetString( card, "usr" );
480 jsonObjectFree( card );
481 params = jsonParseFmt( "[%s]", userid );
483 userObj = oilsUtilsQuickReq(
484 "open-ils.cstore", "open-ils.cstore.direct.actor.user.retrieve", params );
485 jsonObjectFree( params );
486 if( userObj && JSON_NULL == userObj->type ) {
487 // user not found (shouldn't happen, due to foreign key)
488 jsonObjectFree( userObj );
495 response = oilsNewEvent( OSRF_LOG_MARK, OILS_EVENT_AUTH_FAILED );
496 osrfLogInfo(OSRF_LOG_MARK, "failed login: username=%s, barcode=%s, workstation=%s",
497 uname, (barcode ? barcode : "(none)"), ws );
498 osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
499 oilsEventFree(response);
500 return 0; // No such user
503 // Such a user exists. Now see if he or she has the right credentials.
506 passOK = oilsAuthVerifyPassword( ctx, userObj, uname, password );
508 passOK = oilsAuthVerifyPassword( ctx, userObj, barcode, password );
511 jsonObjectFree(userObj);
515 // See if the account is active
516 char* active = oilsFMGetString(userObj, "active");
517 if( !oilsUtilsIsDBTrue(active) ) {
519 response = oilsNewEvent( OSRF_LOG_MARK, "PATRON_INACTIVE" );
521 response = oilsNewEvent( OSRF_LOG_MARK, OILS_EVENT_AUTH_FAILED );
523 osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
524 oilsEventFree(response);
525 jsonObjectFree(userObj);
531 osrfLogInfo( OSRF_LOG_MARK, "Fetching card by barcode %s", barcode );
534 osrfLogInfo( OSRF_LOG_MARK, "barcode %s is not active, returning event", barcode );
535 response = oilsNewEvent( OSRF_LOG_MARK, "PATRON_CARD_INACTIVE" );
536 osrfAppRespondComplete( ctx, oilsEventToJSON( response ) );
537 oilsEventFree( response );
538 jsonObjectFree( userObj );
543 // See if the user is even allowed to log in
544 if( oilsAuthCheckLoginPerm( ctx, userObj, type ) == -1 ) {
545 jsonObjectFree(userObj);
549 // If a workstation is defined, add the workstation info
550 if( workstation != NULL ) {
551 osrfLogDebug(OSRF_LOG_MARK, "Workstation is %s", workstation);
552 response = oilsAuthVerifyWorkstation( ctx, userObj, workstation );
554 jsonObjectFree(userObj);
555 osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
556 oilsEventFree(response);
561 // Otherwise, use the home org as the workstation org on the user
562 char* orgid = oilsFMGetString(userObj, "home_ou");
563 oilsFMSetString(userObj, "ws_ou", orgid);
567 char* freeable_uname = NULL;
569 uname = freeable_uname = oilsFMGetString( userObj, "usrname" );
573 response = oilsAuthHandleLoginOK( userObj, uname, type, orgloc, workstation );
576 response = oilsNewEvent( OSRF_LOG_MARK, OILS_EVENT_AUTH_FAILED );
577 osrfLogInfo(OSRF_LOG_MARK, "failed login: username=%s, barcode=%s, workstation=%s",
578 uname, (barcode ? barcode : "(none)"), ws );
581 jsonObjectFree(userObj);
582 osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
583 oilsEventFree(response);
586 free(freeable_uname);
593 int oilsAuthSessionDelete( osrfMethodContext* ctx ) {
594 OSRF_METHOD_VERIFY_CONTEXT(ctx);
596 const char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
597 jsonObject* resp = NULL;
600 osrfLogDebug(OSRF_LOG_MARK, "Removing auth session: %s", authToken );
601 char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
602 osrfCacheRemove(key);
603 resp = jsonNewObject(authToken); /**/
607 osrfAppRespondComplete( ctx, resp );
608 jsonObjectFree(resp);
613 Resets the auth login timeout
614 @return The event object, OILS_EVENT_SUCCESS, or OILS_EVENT_NO_SESSION
616 static oilsEvent* _oilsAuthResetTimeout( const char* authToken ) {
617 if(!authToken) return NULL;
619 oilsEvent* evt = NULL;
622 osrfLogDebug(OSRF_LOG_MARK, "Resetting auth timeout for session %s", authToken);
623 char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken );
624 jsonObject* cacheObj = osrfCacheGetObject( key );
627 osrfLogInfo(OSRF_LOG_MARK, "No user in the cache exists with key %s", key);
628 evt = oilsNewEvent(OSRF_LOG_MARK, OILS_EVENT_NO_SESSION);
631 // Determine a new timeout value
632 jsonObject* endtime_obj = jsonObjectGetKey( cacheObj, "endtime" );
634 // Extend the current endtime by a fixed amount
635 time_t endtime = (time_t) jsonObjectGetNumber( endtime_obj );
636 int reset_interval = DEFAULT_RESET_INTERVAL;
637 jsonObject* reset_interval_obj = jsonObjectGetKey( cacheObj, "reset_interval" );
638 if( reset_interval_obj ) {
639 reset_interval = (int) jsonObjectGetNumber( reset_interval_obj );
640 if( reset_interval <= 0 )
641 reset_interval = DEFAULT_RESET_INTERVAL;
644 time_t now = time( NULL );
645 time_t new_endtime = now + reset_interval;
646 if( new_endtime > endtime ) {
647 // Keep the session alive a little longer
648 jsonObjectSetNumber( endtime_obj, (double) new_endtime );
649 timeout = reset_interval;
650 osrfCachePutObject( key, cacheObj, timeout );
652 // The session isn't close to expiring, so don't reset anything.
653 // Just report the time remaining.
654 timeout = endtime - now;
657 // Reapply the existing timeout from the current time
658 timeout = (time_t) jsonObjectGetNumber( jsonObjectGetKeyConst( cacheObj, "authtime"));
659 osrfCachePutObject( key, cacheObj, timeout );
662 jsonObject* payload = jsonNewNumberObject( (double) timeout );
663 evt = oilsNewEvent2(OSRF_LOG_MARK, OILS_EVENT_SUCCESS, payload);
664 jsonObjectFree(payload);
665 jsonObjectFree(cacheObj);
672 int oilsAuthResetTimeout( osrfMethodContext* ctx ) {
673 OSRF_METHOD_VERIFY_CONTEXT(ctx);
674 const char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0));
675 oilsEvent* evt = _oilsAuthResetTimeout(authToken);
676 osrfAppRespondComplete( ctx, oilsEventToJSON(evt) );
682 int oilsAuthSessionRetrieve( osrfMethodContext* ctx ) {
683 OSRF_METHOD_VERIFY_CONTEXT(ctx);
685 const char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0));
686 jsonObject* cacheObj = NULL;
687 oilsEvent* evt = NULL;
691 // Reset the timeout to keep the session alive
692 evt = _oilsAuthResetTimeout(authToken);
694 if( evt && strcmp(evt->event, OILS_EVENT_SUCCESS) ) {
695 osrfAppRespondComplete( ctx, oilsEventToJSON( evt )); // can't reset timeout
699 // Retrieve the cached session object
700 osrfLogDebug(OSRF_LOG_MARK, "Retrieving auth session: %s", authToken);
701 char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken );
702 cacheObj = osrfCacheGetObject( key );
704 // Return a copy of the cached user object
705 osrfAppRespondComplete( ctx, jsonObjectGetKeyConst( cacheObj, "userobj"));
706 jsonObjectFree(cacheObj);
708 // Auth token is invalid or expired
709 oilsEvent* evt2 = oilsNewEvent(OSRF_LOG_MARK, OILS_EVENT_NO_SESSION);
710 osrfAppRespondComplete( ctx, oilsEventToJSON(evt2) ); /* should be event.. */
719 evt = oilsNewEvent(OSRF_LOG_MARK, OILS_EVENT_NO_SESSION);
720 osrfAppRespondComplete( ctx, oilsEventToJSON(evt) );