LP#1468422 Internal auth service WIP
authorBill Erickson <berickxx@gmail.com>
Fri, 20 Nov 2015 21:35:41 +0000 (16:35 -0500)
committerBill Erickson <berickxx@gmail.com>
Fri, 20 Nov 2015 21:35:41 +0000 (16:35 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/c-apps/Makefile.am
Open-ILS/src/c-apps/oils_auth_internal.c

index 77d48e5..3014ad1 100644 (file)
@@ -33,7 +33,7 @@ test_qstore_CFLAGS = $(AM_CFLAGS)
 test_qstore_LDFLAGS = $(AM_LDFLAGS) -loils_idl -loils_utils
 test_qstore_DEPENDENCIES = liboils_idl.la liboils_utils.la
 
-lib_LTLIBRARIES = liboils_idl.la liboils_utils.la oils_cstore.la oils_qstore.la oils_rstore.la oils_pcrud.la oils_auth.la
+lib_LTLIBRARIES = liboils_idl.la liboils_utils.la oils_cstore.la oils_qstore.la oils_rstore.la oils_pcrud.la oils_auth.la oils_auth_internal.la
 
 liboils_idl_la_SOURCES = oils_idl-core.c
 liboils_idl_la_LDFLAGS = -version-info 2:0:0
@@ -61,4 +61,9 @@ oils_auth_la_SOURCES = oils_auth.c
 oils_auth_la_LDFLAGS = -module -loils_utils -version-info 2:0:0
 oils_auth_la_DEPENDENCIES = liboils_utils.la
 
+oils_auth_internal_la_SOURCES = oils_auth_internal.c
+oils_auth_internal_la_LDFLAGS = -module -loils_utils -version-info 2:0:0
+oils_auth_internal_la_DEPENDENCIES = liboils_utils.la
+
+
 
index c00df20..65922f2 100644 (file)
@@ -10,7 +10,7 @@
 #define OILS_AUTH_CACHE_PRFX "oils_auth_"
 #define OILS_AUTH_COUNT_SFFX "_count"
 
-#define MODULENAME "open-ils.auth-internal"
+#define MODULENAME "open-ils.auth_internal"
 
 #define OILS_AUTH_OPAC "opac"
 #define OILS_AUTH_STAFF "staff"
@@ -27,972 +27,293 @@ static long _oilsAuthOPACTimeout = 0;
 static long _oilsAuthStaffTimeout = 0;
 static long _oilsAuthOverrideTimeout = 0;
 static long _oilsAuthPersistTimeout = 0;
-static long _oilsAuthSeedTimeout = 0;
-static long _oilsAuthBlockTimeout = 0;
-static long _oilsAuthBlockCount = 0;
-
 
 /**
-       @brief Initialize the application by registering functions for method calls.
-       @return Zero in all cases.
+    @brief Initialize the application by registering functions for method calls.
+    @return Zero on success, 1 on error.
 */
 int osrfAppInitialize() {
 
-       osrfLogInfo(OSRF_LOG_MARK, "Initializing Auth Internal Server...");
-
-       /* load and parse the IDL */
-       if (!oilsInitIDL(NULL)) return 1; /* return non-zero to indicate error */
-
-       osrfAppRegisterMethod(
-               MODULENAME,
-               "open-ils.auth-internal.session.create",
-               "oilsAutInternalCreateSession",
-        "Adds a user to the authentication cache to indicate the user is authenticated"
-               " PARAMS( username )", 1, 0 );
-
-       osrfAppRegisterMethod(
-               MODULENAME,
-               "open-ils.auth.authenticate.complete",
-               "oilsAuthComplete",
-               "Completes the authentication process.  Returns an object like so: "
-               "{authtoken : <token>, authtime:<time>}, where authtoken is the login "
-               "token and authtime is the number of seconds the session will be active"
-               "PARAMS(username, md5sum( seed + md5sum( password ) ), type, org_id ) "
-               "type can be one of 'opac','staff', or 'temp' and it defaults to 'staff' "
-               "org_id is the location at which the login should be considered "
-               "active for login timeout purposes", 1, 0 );
-
-       osrfAppRegisterMethod(
-               MODULENAME,
-               "open-ils.auth.authenticate.verify",
-               "oilsAuthComplete",
-               "Verifies the user provided a valid username and password."
-               "Params and are the same as open-ils.auth.authenticate.complete."
-               "Returns SUCCESS event on success, failure event on failure", 1, 0);
-
-
-       osrfAppRegisterMethod(
-               MODULENAME,
-               "open-ils.auth.session.retrieve",
-               "oilsAuthSessionRetrieve",
-               "Pass in the auth token and this retrieves the user object.  The auth "
-               "timeout is reset when this call is made "
-               "Returns the user object (password blanked) for the given login session "
-               "PARAMS( authToken )", 1, 0 );
-
-       osrfAppRegisterMethod(
-               MODULENAME,
-               "open-ils.auth.session.delete",
-               "oilsAuthSessionDelete",
-               "Destroys the given login session "
-               "PARAMS( authToken )",  1, 0 );
-
-       osrfAppRegisterMethod(
-               MODULENAME,
-               "open-ils.auth.session.reset_timeout",
-               "oilsAuthResetTimeout",
-               "Resets the login timeout for the given session "
-               "Returns an ILS Event with payload = session_timeout of session "
-               "if found, otherwise returns the NO_SESSION event"
-               "PARAMS( authToken )", 1, 0 );
-
-       if(!_oilsAuthSeedTimeout) { /* Load the default timeouts */
-
-               jsonObject* value_obj;
-
-               value_obj = osrf_settings_host_value_object(
-                       "/apps/open-ils.auth/app_settings/auth_limits/seed" );
-               _oilsAuthSeedTimeout = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
-               jsonObjectFree(value_obj);
-               if( -1 == _oilsAuthSeedTimeout ) {
-                       osrfLogWarning( OSRF_LOG_MARK, "Invalid timeout for Auth Seeds - Using 30 seconds" );
-                       _oilsAuthSeedTimeout = 30;
-               }
-
-               value_obj = osrf_settings_host_value_object(
-                       "/apps/open-ils.auth/app_settings/auth_limits/block_time" );
-               _oilsAuthBlockTimeout = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
-               jsonObjectFree(value_obj);
-               if( -1 == _oilsAuthBlockTimeout ) {
-                       osrfLogWarning( OSRF_LOG_MARK, "Invalid timeout for Blocking Timeout - Using 3x Seed" );
-                       _oilsAuthBlockTimeout = _oilsAuthSeedTimeout * 3;
-               }
-
-               value_obj = osrf_settings_host_value_object(
-                       "/apps/open-ils.auth/app_settings/auth_limits/block_count" );
-               _oilsAuthBlockCount = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
-               jsonObjectFree(value_obj);
-               if( -1 == _oilsAuthBlockCount ) {
-                       osrfLogWarning( OSRF_LOG_MARK, "Invalid count for Blocking - Using 10" );
-                       _oilsAuthBlockCount = 10;
-               }
-
-               osrfLogInfo(OSRF_LOG_MARK, "Set auth limits: "
-                       "seed => %ld : block_timeout => %ld : block_count => %ld",
-                       _oilsAuthSeedTimeout, _oilsAuthBlockTimeout, _oilsAuthBlockCount );
-       }
-
-       return 0;
+    osrfLogInfo(OSRF_LOG_MARK, "Initializing Auth Internal Server...");
+
+    /* load and parse the IDL */
+    /* return non-zero to indicate error */
+    if (!oilsInitIDL(NULL)) return 1; 
+
+    osrfAppRegisterMethod(
+        MODULENAME,
+        "open-ils.auth-internal.session.create",
+        "oilsAutInternalCreateSession",
+        "Adds a user to the authentication cache to indicate "
+        "the user is authenticated", 1, 0 
+    );
+
+    return 0;
 }
 
 /**
-       @brief Dummy placeholder for initializing a server drone.
+    @brief Dummy placeholder for initializing a server drone.
 
-       There is nothing to do, so do nothing.
+    There is nothing to do, so do nothing.
 */
 int osrfAppChildInit() {
-       return 0;
+    return 0;
 }
 
+
 /**
-       @brief Implement the "init" method.
-       @param ctx The method context.
-       @return Zero if successful, or -1 if not.
-
-       Method parameters:
-       - username
-       - nonce : optional login seed (string) provided by the caller which
-               is added to the auth init cache to differentiate between logins
-               using the same username and thus avoiding cache collisions for
-               near-simultaneous logins.
-
-       Return to client: Intermediate authentication seed.
-
-       Combine the username with a timestamp and process ID, and take an md5 hash of the result.
-       Store the hash in memcache, with a key based on the username.  Then return the hash to
-       the client.
-
-       However: if the username includes one or more embedded blank spaces, return a dummy
-       hash without storing anything in memcache.  The dummy will never match a stored hash, so
-       any attempt to authenticate with it will fail.
+    @brief Determine the login timeout.
+    @param userObj Pointer to an object describing the user.
+    @param type Pointer to one of four possible character strings identifying the login type.
+    @param orgloc Org unit to use for settings lookups (negative or zero means unspecified)
+    @return The length of the timeout, in seconds.
+
+    The default timeout value comes from the configuration file, and
+    depends on the login type.
+
+    The default may be overridden by a corresponding org unit setting.
+    The @a orgloc parameter says what org unit to use for the lookup.
+    If @a orgloc <= 0, or if the lookup for @a orgloc yields no result,
+    we look up the setting for the user's home org unit instead (except
+    that if it's the same as @a orgloc we don't bother repeating the
+    lookup).
+
+    Whether defined in the config file or in an org unit setting, a
+    timeout value may be expressed as a raw number (i.e. all digits,
+    possibly with leading and/or trailing white space) or as an interval
+    string to be translated into seconds by PostgreSQL.
 */
-int oilsAuthInit( osrfMethodContext* ctx ) {
-       OSRF_METHOD_VERIFY_CONTEXT(ctx);
-
-       char* username  = jsonObjectToSimpleString( jsonObjectGetIndex(ctx->params, 0) );
-       const char* nonce = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 1));
-       if (!nonce) nonce = "";
-
-       if( username ) {
+static long oilsAuthGetTimeout(
+    const jsonObject* userObj, const char* type, int orgloc) {
 
-               jsonObject* resp;
+    if(!_oilsAuthOPACTimeout) { /* Load the default timeouts */
 
-               if( strchr( username, ' ' ) ) {
+        jsonObject* value_obj;
 
-                       // Embedded spaces are not allowed in a username.  Use "x" as a dummy
-                       // seed.  It will never be a valid seed because 'x' is not a hex digit.
-                       resp = jsonNewObject( "x" );
-
-               } else {
+        value_obj = osrf_settings_host_value_object(
+            "/apps/open-ils.auth/app_settings/default_timeout/opac" );
+        _oilsAuthOPACTimeout = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
+        jsonObjectFree(value_obj);
+        if( -1 == _oilsAuthOPACTimeout ) {
+            osrfLogWarning( OSRF_LOG_MARK, "Invalid default timeout for OPAC logins" );
+            _oilsAuthOPACTimeout = 0;
+        }
 
-                       // Build a key and a seed; store them in memcache.
-                       char* key  = va_list_to_string( "%s%s%s", OILS_AUTH_CACHE_PRFX, username, nonce );
-                       char* countkey = va_list_to_string( "%s%s%s", OILS_AUTH_CACHE_PRFX, username, OILS_AUTH_COUNT_SFFX );
-                       char* seed = md5sum( "%d.%ld.%s.%s", (int) time(NULL), (long) getpid(), username, nonce );
-                       jsonObject* countobject = osrfCacheGetObject( countkey );
-                       if(!countobject) {
-                               countobject = jsonNewNumberObject( (double) 0 );
-                       }
-                       osrfCachePutString( key, seed, _oilsAuthSeedTimeout );
-                       osrfCachePutObject( countkey, countobject, _oilsAuthBlockTimeout );
+        value_obj = osrf_settings_host_value_object(
+            "/apps/open-ils.auth/app_settings/default_timeout/staff" );
+        _oilsAuthStaffTimeout = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
+        jsonObjectFree(value_obj);
+        if( -1 == _oilsAuthStaffTimeout ) {
+            osrfLogWarning( OSRF_LOG_MARK, "Invalid default timeout for staff logins" );
+            _oilsAuthStaffTimeout = 0;
+        }
 
-                       osrfLogDebug( OSRF_LOG_MARK, "oilsAuthInit(): has seed %s and key %s", seed, key );
+        value_obj = osrf_settings_host_value_object(
+            "/apps/open-ils.auth/app_settings/default_timeout/temp" );
+        _oilsAuthOverrideTimeout = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
+        jsonObjectFree(value_obj);
+        if( -1 == _oilsAuthOverrideTimeout ) {
+            osrfLogWarning( OSRF_LOG_MARK, "Invalid default timeout for temp logins" );
+            _oilsAuthOverrideTimeout = 0;
+        }
 
-                       // Build a returnable object containing the seed.
-                       resp = jsonNewObject( seed );
+        value_obj = osrf_settings_host_value_object(
+            "/apps/open-ils.auth/app_settings/default_timeout/persist" );
+        _oilsAuthPersistTimeout = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
+        jsonObjectFree(value_obj);
+        if( -1 == _oilsAuthPersistTimeout ) {
+            osrfLogWarning( OSRF_LOG_MARK, "Invalid default timeout for persist logins" );
+            _oilsAuthPersistTimeout = 0;
+        }
 
-                       free( seed );
-                       free( key );
-                       free( countkey );
-                       jsonObjectFree( countobject );
-               }
+        osrfLogInfo(OSRF_LOG_MARK, "Set default auth timeouts: "
+            "opac => %ld : staff => %ld : temp => %ld : persist => %ld",
+            _oilsAuthOPACTimeout, _oilsAuthStaffTimeout,
+            _oilsAuthOverrideTimeout, _oilsAuthPersistTimeout );
+    }
 
-               // Return the seed to the client.
-               osrfAppRespondComplete( ctx, resp );
+    int home_ou = (int) jsonObjectGetNumber( oilsFMGetObject( userObj, "home_ou" ));
+    if(orgloc < 1)
+        orgloc = home_ou;
+
+    char* setting = NULL;
+    long default_timeout = 0;
+
+    if( !strcmp( type, OILS_AUTH_OPAC )) {
+        setting = OILS_ORG_SETTING_OPAC_TIMEOUT;
+        default_timeout = _oilsAuthOPACTimeout;
+    } else if( !strcmp( type, OILS_AUTH_STAFF )) {
+        setting = OILS_ORG_SETTING_STAFF_TIMEOUT;
+        default_timeout = _oilsAuthStaffTimeout;
+    } else if( !strcmp( type, OILS_AUTH_TEMP )) {
+        setting = OILS_ORG_SETTING_TEMP_TIMEOUT;
+        default_timeout = _oilsAuthOverrideTimeout;
+    } else if( !strcmp( type, OILS_AUTH_PERSIST )) {
+        setting = OILS_ORG_SETTING_PERSIST_TIMEOUT;
+        default_timeout = _oilsAuthPersistTimeout;
+    }
 
-               jsonObjectFree(resp);
-               free(username);
-               return 0;
-       }
+    // Get the org unit setting, if there is one.
+    char* timeout = oilsUtilsFetchOrgSetting( orgloc, setting );
+    if(!timeout) {
+        if( orgloc != home_ou ) {
+            osrfLogDebug(OSRF_LOG_MARK, "Auth timeout not defined for org %d, "
+                "trying home_ou %d", orgloc, home_ou );
+            timeout = oilsUtilsFetchOrgSetting( home_ou, setting );
+        }
+    }
 
-       return -1;  // Error: no username parameter
-}
+    if(!timeout)
+        return default_timeout;   // No override from org unit setting
+
+    // Translate the org unit setting to a number
+    long t;
+    if( !*timeout ) {
+        osrfLogWarning( OSRF_LOG_MARK,
+            "Timeout org unit setting is an empty string for %s login; using default",
+            timeout, type );
+        t = default_timeout;
+    } else {
+        // Treat timeout string as an interval, and convert it to seconds
+        t = oilsUtilsIntervalToSeconds( timeout );
+        if( -1 == t ) {
+            // Unable to convert; possibly an invalid interval string
+            osrfLogError( OSRF_LOG_MARK,
+                "Unable to convert timeout interval \"%s\" for %s login; using default",
+                timeout, type );
+            t = default_timeout;
+        }
+    }
 
-/**
-       Verifies that the user has permission to login with the
-       given type.  If the permission fails, an oilsEvent is returned
-       to the caller.
-       @return -1 if the permission check failed, 0 if the permission
-       is granted
-*/
-static int oilsAuthCheckLoginPerm(
-               osrfMethodContext* ctx, const jsonObject* userObj, const char* type ) {
-
-       if(!(userObj && type)) return -1;
-       oilsEvent* perm = NULL;
-
-       if(!strcasecmp(type, OILS_AUTH_OPAC)) {
-               char* permissions[] = { "OPAC_LOGIN" };
-               perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
-
-       } else if(!strcasecmp(type, OILS_AUTH_STAFF)) {
-               char* permissions[] = { "STAFF_LOGIN" };
-               perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
-
-       } else if(!strcasecmp(type, OILS_AUTH_TEMP)) {
-               char* permissions[] = { "STAFF_LOGIN" };
-               perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
-       } else if(!strcasecmp(type, OILS_AUTH_PERSIST)) {
-               char* permissions[] = { "PERSISTENT_LOGIN" };
-               perm = oilsUtilsCheckPerms( oilsFMGetObjectId( userObj ), -1, permissions, 1 );
-       }
-
-       if(perm) {
-               osrfAppRespondComplete( ctx, oilsEventToJSON(perm) );
-               oilsEventFree(perm);
-               return -1;
-       }
-
-       return 0;
+    free(timeout);
+    return t;
 }
 
 /**
-       Returns 1 if the password provided matches the user's real password
-       Returns 0 otherwise
-       Returns -1 on error
-*/
-/**
-       @brief Verify the password received from the client.
-       @param ctx The method context.
-       @param userObj An object from the database, representing the user.
-       @param password An obfuscated password received from the client.
-       @return 1 if the password is valid; 0 if it isn't; or -1 upon error.
-
-       (None of the so-called "passwords" used here are in plaintext.  All have been passed
-       through at least one layer of hashing to obfuscate them.)
-
-       Take the password from the user object.  Append it to the username seed from memcache,
-       as stored previously by a call to the init method.  Take an md5 hash of the result.
-       Then compare this hash to the password received from the client.
-
-       In order for the two to match, other than by dumb luck, the client had to construct
-       the password it passed in the same way.  That means it neded to know not only the
-       original password (either hashed or plaintext), but also the seed.  The latter requirement
-       means that the client process needs either to be the same process that called the init
-       method or to receive the seed from the process that did so.
-*/
-static int oilsAuthVerifyPassword( const osrfMethodContext* ctx,
-               const jsonObject* userObj, const char* uname,
-               const char* password, const char* nonce ) {
-
-       // Get the username seed, as stored previously in memcache by the init method
-       char* seed = osrfCacheGetString( "%s%s%s", OILS_AUTH_CACHE_PRFX, uname, nonce );
-       if(!seed) {
-               return osrfAppRequestRespondException( ctx->session,
-                       ctx->request, "No authentication seed found. "
-                       "open-ils.auth.authenticate.init must be called first "
-                       " (check that memcached is running and can be connected to) "
-               );
-       }
-    
-       // We won't be needing the seed again, remove it
-       osrfCacheRemove( "%s%s%s", OILS_AUTH_CACHE_PRFX, uname, nonce );
-
-       // Get the hashed password from the user object
-       char* realPassword = oilsFMGetString( userObj, "passwd" );
-
-       osrfLogInternal(OSRF_LOG_MARK, "oilsAuth retrieved real password: [%s]", realPassword);
-       osrfLogDebug(OSRF_LOG_MARK, "oilsAuth retrieved seed from cache: %s", seed );
-
-       // Concatenate them and take an MD5 hash of the result
-       char* maskedPw = md5sum( "%s%s", seed, realPassword );
-
-       free(realPassword);
-       free(seed);
-
-       if( !maskedPw ) {
-               // This happens only if md5sum() runs out of memory
-               free( maskedPw );
-               return -1;  // md5sum() ran out of memory
-       }
-
-       osrfLogDebug(OSRF_LOG_MARK,  "oilsAuth generated masked password %s. "
-                       "Testing against provided password %s", maskedPw, password );
-
-       int ret = 0;
-       if( !strcmp( maskedPw, password ) )
-               ret = 1;
-
-       free(maskedPw);
-
-       char* countkey = va_list_to_string( "%s%s%s", OILS_AUTH_CACHE_PRFX, uname, OILS_AUTH_COUNT_SFFX );
-       jsonObject* countobject = osrfCacheGetObject( countkey );
-       if(countobject) {
-               long failcount = (long) jsonObjectGetNumber( countobject );
-               if(failcount >= _oilsAuthBlockCount) {
-                       ret = 0;
-                   osrfLogInfo(OSRF_LOG_MARK, "oilsAuth found too many recent failures for '%s' : %i, forcing failure state.", uname, failcount);
-               }
-               if(ret == 0) {
-                       failcount += 1;
-               }
-               jsonObjectSetNumber( countobject, failcount );
-               osrfCachePutObject( countkey, countobject, _oilsAuthBlockTimeout );
-               jsonObjectFree(countobject);
-       }
-       free(countkey);
-
-       return ret;
-}
+ * Verify workstation exists and stuff it into the user object to be cached
+ */
+static oilsEvent* oilsAuthVerifyWorkstation(
+        const osrfMethodContext* ctx, jsonObject* userObj, const char* ws ) {
 
-/**
-       @brief Determine the login timeout.
-       @param userObj Pointer to an object describing the user.
-       @param type Pointer to one of four possible character strings identifying the login type.
-       @param orgloc Org unit to use for settings lookups (negative or zero means unspecified)
-       @return The length of the timeout, in seconds.
-
-       The default timeout value comes from the configuration file, and depends on the
-       login type.
-
-       The default may be overridden by a corresponding org unit setting.  The @a orgloc
-       parameter says what org unit to use for the lookup.  If @a orgloc <= 0, or if the
-       lookup for @a orgloc yields no result, we look up the setting for the user's home org unit
-       instead (except that if it's the same as @a orgloc we don't bother repeating the lookup).
-
-       Whether defined in the config file or in an org unit setting, a timeout value may be
-       expressed as a raw number (i.e. all digits, possibly with leading and/or trailing white
-       space) or as an interval string to be translated into seconds by PostgreSQL.
-*/
-static long oilsAuthGetTimeout( const jsonObject* userObj, const char* type, int orgloc ) {
-
-       if(!_oilsAuthOPACTimeout) { /* Load the default timeouts */
-
-               jsonObject* value_obj;
-
-               value_obj = osrf_settings_host_value_object(
-                       "/apps/open-ils.auth/app_settings/default_timeout/opac" );
-               _oilsAuthOPACTimeout = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
-               jsonObjectFree(value_obj);
-               if( -1 == _oilsAuthOPACTimeout ) {
-                       osrfLogWarning( OSRF_LOG_MARK, "Invalid default timeout for OPAC logins" );
-                       _oilsAuthOPACTimeout = 0;
-               }
-
-               value_obj = osrf_settings_host_value_object(
-                       "/apps/open-ils.auth/app_settings/default_timeout/staff" );
-               _oilsAuthStaffTimeout = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
-               jsonObjectFree(value_obj);
-               if( -1 == _oilsAuthStaffTimeout ) {
-                       osrfLogWarning( OSRF_LOG_MARK, "Invalid default timeout for staff logins" );
-                       _oilsAuthStaffTimeout = 0;
-               }
-
-               value_obj = osrf_settings_host_value_object(
-                       "/apps/open-ils.auth/app_settings/default_timeout/temp" );
-               _oilsAuthOverrideTimeout = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
-               jsonObjectFree(value_obj);
-               if( -1 == _oilsAuthOverrideTimeout ) {
-                       osrfLogWarning( OSRF_LOG_MARK, "Invalid default timeout for temp logins" );
-                       _oilsAuthOverrideTimeout = 0;
-               }
-
-               value_obj = osrf_settings_host_value_object(
-                       "/apps/open-ils.auth/app_settings/default_timeout/persist" );
-               _oilsAuthPersistTimeout = oilsUtilsIntervalToSeconds( jsonObjectGetString( value_obj ));
-               jsonObjectFree(value_obj);
-               if( -1 == _oilsAuthPersistTimeout ) {
-                       osrfLogWarning( OSRF_LOG_MARK, "Invalid default timeout for persist logins" );
-                       _oilsAuthPersistTimeout = 0;
-               }
-
-               osrfLogInfo(OSRF_LOG_MARK, "Set default auth timeouts: "
-                       "opac => %ld : staff => %ld : temp => %ld : persist => %ld",
-                       _oilsAuthOPACTimeout, _oilsAuthStaffTimeout,
-                       _oilsAuthOverrideTimeout, _oilsAuthPersistTimeout );
-       }
-
-       int home_ou = (int) jsonObjectGetNumber( oilsFMGetObject( userObj, "home_ou" ));
-       if(orgloc < 1)
-               orgloc = home_ou;
-
-       char* setting = NULL;
-       long default_timeout = 0;
-
-       if( !strcmp( type, OILS_AUTH_OPAC )) {
-               setting = OILS_ORG_SETTING_OPAC_TIMEOUT;
-               default_timeout = _oilsAuthOPACTimeout;
-       } else if( !strcmp( type, OILS_AUTH_STAFF )) {
-               setting = OILS_ORG_SETTING_STAFF_TIMEOUT;
-               default_timeout = _oilsAuthStaffTimeout;
-       } else if( !strcmp( type, OILS_AUTH_TEMP )) {
-               setting = OILS_ORG_SETTING_TEMP_TIMEOUT;
-               default_timeout = _oilsAuthOverrideTimeout;
-       } else if( !strcmp( type, OILS_AUTH_PERSIST )) {
-               setting = OILS_ORG_SETTING_PERSIST_TIMEOUT;
-               default_timeout = _oilsAuthPersistTimeout;
-       }
-
-       // Get the org unit setting, if there is one.
-       char* timeout = oilsUtilsFetchOrgSetting( orgloc, setting );
-       if(!timeout) {
-               if( orgloc != home_ou ) {
-                       osrfLogDebug(OSRF_LOG_MARK, "Auth timeout not defined for org %d, "
-                               "trying home_ou %d", orgloc, home_ou );
-                       timeout = oilsUtilsFetchOrgSetting( home_ou, setting );
-               }
-       }
-
-       if(!timeout)
-               return default_timeout;   // No override from org unit setting
-
-       // Translate the org unit setting to a number
-       long t;
-       if( !*timeout ) {
-               osrfLogWarning( OSRF_LOG_MARK,
-                       "Timeout org unit setting is an empty string for %s login; using default",
-                       timeout, type );
-               t = default_timeout;
-       } else {
-               // Treat timeout string as an interval, and convert it to seconds
-               t = oilsUtilsIntervalToSeconds( timeout );
-               if( -1 == t ) {
-                       // Unable to convert; possibly an invalid interval string
-                       osrfLogError( OSRF_LOG_MARK,
-                               "Unable to convert timeout interval \"%s\" for %s login; using default",
-                               timeout, type );
-                       t = default_timeout;
-               }
-       }
-
-       free(timeout);
-       return t;
-}
+    jsonObject* workstation = oilsUtilsFetchWorkstationByName(ws);
 
-/*
-       Adds the authentication token to the user cache.  The timeout for the
-       auth token is based on the type of login as well as (if type=='opac')
-       the org location id.
-       Returns the event that should be returned to the user.
-       Event must be freed
-*/
-static oilsEvent* oilsAuthHandleLoginOK( jsonObject* userObj, const char* uname,
-               const char* type, int orgloc, const char* workstation ) {
-
-       oilsEvent* response;
-
-       long timeout;
-       char* wsorg = jsonObjectToSimpleString(oilsFMGetObject(userObj, "ws_ou"));
-       if(wsorg) { /* if there is a workstation, use it for the timeout */
-               osrfLogDebug( OSRF_LOG_MARK,
-                               "Auth session trying workstation id %d for auth timeout", atoi(wsorg));
-               timeout = oilsAuthGetTimeout( userObj, type, atoi(wsorg) );
-               free(wsorg);
-       } else {
-               osrfLogDebug( OSRF_LOG_MARK,
-                               "Auth session trying org from param [%d] for auth timeout", orgloc );
-               timeout = oilsAuthGetTimeout( userObj, type, orgloc );
-       }
-       osrfLogDebug(OSRF_LOG_MARK, "Auth session timeout for %s: %ld", uname, timeout );
-
-       char* string = va_list_to_string(
-                       "%d.%ld.%s", (long) getpid(), time(NULL), uname );
-       char* authToken = md5sum(string);
-       char* authKey = va_list_to_string(
-                       "%s%s", OILS_AUTH_CACHE_PRFX, authToken );
-
-       const char* ws = (workstation) ? workstation : "";
-       osrfLogActivity(OSRF_LOG_MARK,
-               "successful login: username=%s, authtoken=%s, workstation=%s", uname, authToken, ws );
-
-       oilsFMSetString( userObj, "passwd", "" );
-       jsonObject* cacheObj = jsonParseFmt( "{\"authtime\": %ld}", timeout );
-       jsonObjectSetKey( cacheObj, "userobj", jsonObjectClone(userObj));
-
-       if( !strcmp( type, OILS_AUTH_PERSIST )) {
-               // Add entries for endtime and reset_interval, so that we can gracefully
-               // extend the session a bit if the user is active toward the end of the 
-               // timeout originally specified.
-               time_t endtime = time( NULL ) + timeout;
-               jsonObjectSetKey( cacheObj, "endtime", jsonNewNumberObject( (double) endtime ) );
-
-               // Reset interval is hard-coded for now, but if we ever want to make it
-               // configurable, this is the place to do it:
-               jsonObjectSetKey( cacheObj, "reset_interval",
-                       jsonNewNumberObject( (double) DEFAULT_RESET_INTERVAL ));
-       }
-
-       osrfCachePutObject( authKey, cacheObj, (time_t) timeout );
-       jsonObjectFree(cacheObj);
-       osrfLogInternal(OSRF_LOG_MARK, "oilsAuthHandleLoginOK(): Placed user object into cache");
-       jsonObject* payload = jsonParseFmt(
-               "{ \"authtoken\": \"%s\", \"authtime\": %ld }", authToken, timeout );
-
-       response = oilsNewEvent2( OSRF_LOG_MARK, OILS_EVENT_SUCCESS, payload );
-       free(string); free(authToken); free(authKey);
-       jsonObjectFree(payload);
-
-       return response;
-}
+    if(!workstation || workstation->type == JSON_NULL) {
+        jsonObjectFree(workstation);
+        return oilsNewEvent(OSRF_LOG_MARK, "WORKSTATION_NOT_FOUND");
+    }
 
-static oilsEvent* oilsAuthVerifyWorkstation(
-               const osrfMethodContext* ctx, jsonObject* userObj, const char* ws ) {
-       osrfLogInfo(OSRF_LOG_MARK, "Attaching workstation to user at login: %s", ws);
-       jsonObject* workstation = oilsUtilsFetchWorkstationByName(ws);
-       if(!workstation || workstation->type == JSON_NULL) {
-               jsonObjectFree(workstation);
-               return oilsNewEvent(OSRF_LOG_MARK, "WORKSTATION_NOT_FOUND");
-       }
-       long wsid = oilsFMGetObjectId(workstation);
-       LONG_TO_STRING(wsid);
-       char* orgid = oilsFMGetString(workstation, "owning_lib");
-       oilsFMSetString(userObj, "wsid", LONGSTR);
-       oilsFMSetString(userObj, "ws_ou", orgid);
-       free(orgid);
-       jsonObjectFree(workstation);
-       return NULL;
+    long wsid = oilsFMGetObjectId(workstation);
+    LONG_TO_STRING(wsid);
+    char* orgid = oilsFMGetString(workstation, "owning_lib");
+    oilsFMSetString(userObj, "wsid", LONGSTR);
+    oilsFMSetString(userObj, "ws_ou", orgid);
+    free(orgid);
+    jsonObjectFree(workstation);
+    return NULL;
 }
 
 
-
 /**
-       @brief Implement the "complete" method.
-       @param ctx The method context.
-       @return -1 upon error; zero if successful, and if a STATUS message has been sent to the
-       client to indicate completion; a positive integer if successful but no such STATUS
-       message has been sent.
-
-       Method parameters:
-       - a hash with some combination of the following elements:
-               - "username"
-               - "barcode"
-               - "password" (hashed with the cached seed; not plaintext)
-               - "type"
-               - "org"
-               - "workstation"
-               - "agent" (what software/interface/3rd-party is making the request)
-               - "nonce" optional login seed to differentiate logins using the same username.
-
-       The password is required.  Either a username or a barcode must also be present.
-
-       Return to client: Intermediate authentication seed.
-
-       Validate the password, using the username if available, or the barcode if not.  The
-       user must be active, and not barred from logging on.  The barcode, if used for
-       authentication, must be active as well.  The workstation, if specified, must be valid.
-
-       Upon deciding whether to allow the logon, return a corresponding event to the client.
-*/
-int oilsAuthComplete( osrfMethodContext* ctx ) {
-       OSRF_METHOD_VERIFY_CONTEXT(ctx);
-
-       const jsonObject* args  = jsonObjectGetIndex(ctx->params, 0);
+    @brief Implement the session create method
+    @param ctx The method context.
+    @return -1 upon error; zero if successful, and if a STATUS message has 
+    been sent to the client to indicate completion; a positive integer if 
+    successful but no such STATUS message has been sent.
+
+    Method parameters:
+    - a hash with some combination of the following elements:
+        - "user_id"     -- actor.usr (au) ID for the user to cache.
+        - "org_unit"    -- actor.org_unit (aou) ID representing the physical 
+                           location / context used for timeout, etc. settings.
+        - "login_type"  -- login type (opac, staff, temp, persist)
+        - "workstation" -- workstation name
 
-       const char* uname       = jsonObjectGetString(jsonObjectGetKeyConst(args, "username"));
-       const char* password    = jsonObjectGetString(jsonObjectGetKeyConst(args, "password"));
-       const char* type        = jsonObjectGetString(jsonObjectGetKeyConst(args, "type"));
-       int orgloc        = (int) jsonObjectGetNumber(jsonObjectGetKeyConst(args, "org"));
-       const char* workstation = jsonObjectGetString(jsonObjectGetKeyConst(args, "workstation"));
-       const char* barcode     = jsonObjectGetString(jsonObjectGetKeyConst(args, "barcode"));
-       const char* ewho        = jsonObjectGetString(jsonObjectGetKeyConst(args, "agent"));
-       const char* nonce       = jsonObjectGetString(jsonObjectGetKeyConst(args, "nonce"));
-
-       const char* ws = (workstation) ? workstation : "";
-       if (!nonce) nonce = "";
+*/
+int oilsAutInternalCreateSession(osrfMethodContext* ctx) {
+    OSRF_METHOD_VERIFY_CONTEXT(ctx);
 
-       /* Use __FILE__, harmless_line_number for creating
-        * OILS_EVENT_AUTH_FAILED events (instead of OSRF_LOG_MARK) to avoid
-        * giving away information about why an authentication attempt failed.
-        */
-       int harmless_line_number = __LINE__;
+    const jsonObject* args  = jsonObjectGetIndex(ctx->params, 0);
 
-       if( !type )
-                type = OILS_AUTH_STAFF;
+    const char* user_id     = jsonObjectGetString(jsonObjectGetKeyConst(args, "user_id"));
+    const char* org_unit    = jsonObjectGetString(jsonObjectGetKeyConst(args, "org_unit"));
+    const char* login_type  = jsonObjectGetString(jsonObjectGetKeyConst(args, "login_type"));
+    const char* workstation = jsonObjectGetString(jsonObjectGetKeyConst(args, "workstation"));
 
-       if( !( (uname || barcode) && password) ) {
-               return osrfAppRequestRespondException( ctx->session, ctx->request,
-                       "username/barcode and password required for method: %s", ctx->method->name );
-       }
+    if ( !(user_id && login_type && org_unit) ) {
+        return osrfAppRequestRespondException( ctx->session, ctx->request,
+            "Missing parameters for method: %s", ctx->method->name );
+    }
 
        oilsEvent* response = NULL;
-       jsonObject* userObj = NULL;
-       int card_active     = 1;      // boolean; assume active until proven otherwise
-
-       // Fetch a row from the actor.usr table, by username if available,
-       // or by barcode if not.
-       if(uname) {
-               userObj = oilsUtilsFetchUserByUsername( uname );
-               if( userObj && JSON_NULL == userObj->type ) {
-                       jsonObjectFree( userObj );
-                       userObj = NULL;         // username not found
-               }
-       }
-       else if(barcode) {
-               // Read from actor.card by barcode
-
-               osrfLogInfo( OSRF_LOG_MARK, "Fetching user by barcode %s", barcode );
-
-               jsonObject* params = jsonParseFmt("{\"barcode\":\"%s\"}", barcode);
-               jsonObject* card = oilsUtilsQuickReq(
-                       "open-ils.cstore", "open-ils.cstore.direct.actor.card.search", params );
-               jsonObjectFree( params );
-
-               if( card && card->type != JSON_NULL ) {
-                       // Determine whether the card is active
-                       char* card_active_str = oilsFMGetString( card, "active" );
-                       card_active = oilsUtilsIsDBTrue( card_active_str );
-                       free( card_active_str );
-
-                       // Look up the user who owns the card
-                       char* userid = oilsFMGetString( card, "usr" );
-                       jsonObjectFree( card );
-                       params = jsonParseFmt( "[%s]", userid );
-                       free( userid );
-                       userObj = oilsUtilsQuickReq(
-                                       "open-ils.cstore", "open-ils.cstore.direct.actor.user.retrieve", params );
-                       jsonObjectFree( params );
-                       if( userObj && JSON_NULL == userObj->type ) {
-                               // user not found (shouldn't happen, due to foreign key)
-                               jsonObjectFree( userObj );
-                               userObj = NULL;
-                       }
-               }
-       }
-
-       int     barred = 0, deleted = 0;
-       char   *barred_str, *deleted_str;
-
-       if(userObj) {
-               barred_str = oilsFMGetString( userObj, "barred" );
-               barred = oilsUtilsIsDBTrue( barred_str );
-               free( barred_str );
-
-               deleted_str = oilsFMGetString( userObj, "deleted" );
-               deleted = oilsUtilsIsDBTrue( deleted_str );
-               free( deleted_str );
-       }
-
-       if(!userObj || barred || deleted) {
-               response = oilsNewEvent( __FILE__, harmless_line_number, OILS_EVENT_AUTH_FAILED );
-               osrfLogInfo(OSRF_LOG_MARK,  "failed login: username=%s, barcode=%s, workstation=%s",
-                               uname, (barcode ? barcode : "(none)"), ws );
-               osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
-               oilsEventFree(response);
-               return 0;           // No such user
-       }
-
-       // Such a user exists and isn't barred or deleted.
-       // Now see if he or she has the right credentials.
-       int passOK = -1;
-       if(uname)
-               passOK = oilsAuthVerifyPassword( ctx, userObj, uname, password, nonce );
-       else if (barcode)
-               passOK = oilsAuthVerifyPassword( ctx, userObj, barcode, password, nonce );
-
-       if( passOK < 0 ) {
-               jsonObjectFree(userObj);
-               return passOK;
-       }
-
-       // See if the account is active
-       char* active = oilsFMGetString(userObj, "active");
-       if( !oilsUtilsIsDBTrue(active) ) {
-               if( passOK )
-                       response = oilsNewEvent( OSRF_LOG_MARK, "PATRON_INACTIVE" );
-               else
-                       response = oilsNewEvent( __FILE__, harmless_line_number, OILS_EVENT_AUTH_FAILED );
-
-               osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
-               oilsEventFree(response);
-               jsonObjectFree(userObj);
-               free(active);
-               return 0;
-       }
-       free(active);
-
-       osrfLogInfo( OSRF_LOG_MARK, "Fetching card by barcode %s", barcode );
-
-       if( !card_active ) {
-               osrfLogInfo( OSRF_LOG_MARK, "barcode %s is not active, returning event", barcode );
-               response = oilsNewEvent( OSRF_LOG_MARK, "PATRON_CARD_INACTIVE" );
-               osrfAppRespondComplete( ctx, oilsEventToJSON( response ) );
-               oilsEventFree( response );
-               jsonObjectFree( userObj );
-               return 0;
-       }
-
-
-       // See if the user is even allowed to log in
-       if( oilsAuthCheckLoginPerm( ctx, userObj, type ) == -1 ) {
-               jsonObjectFree(userObj);
-               return 0;
-       }
-
-       // If a workstation is defined, add the workstation info
-       if( workstation != NULL ) {
-               osrfLogDebug(OSRF_LOG_MARK, "Workstation is %s", workstation);
-               response = oilsAuthVerifyWorkstation( ctx, userObj, workstation );
-               if(response) {
-                       jsonObjectFree(userObj);
-                       osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
-                       oilsEventFree(response);
-                       return 0;
-               }
-
-       } else {
-               // Otherwise, use the home org as the workstation org on the user
-               char* orgid = oilsFMGetString(userObj, "home_ou");
-               oilsFMSetString(userObj, "ws_ou", orgid);
-               free(orgid);
-       }
-
-       char* freeable_uname = NULL;
-       if(!uname) {
-               uname = freeable_uname = oilsFMGetString( userObj, "usrname" );
-       }
-
-       if( passOK ) { // login successful  
-        
-               char* ewhat = "login";
-
-               if (0 == strcmp(ctx->method->name, "open-ils.auth.authenticate.verify")) {
-                       response = oilsNewEvent( OSRF_LOG_MARK, OILS_EVENT_SUCCESS );
-                       ewhat = "verify";
-
-               } else {
-                       response = oilsAuthHandleLoginOK( userObj, uname, type, orgloc, workstation );
-               }
-
-               oilsUtilsTrackUserActivity(
-                       oilsFMGetObjectId(userObj), 
-                       ewho, ewhat, 
-                       osrfAppSessionGetIngress()
-               );
-
-       } else {
-               response = oilsNewEvent( __FILE__, harmless_line_number, OILS_EVENT_AUTH_FAILED );
-               osrfLogInfo(OSRF_LOG_MARK,  "failed login: username=%s, barcode=%s, workstation=%s",
-                               uname, (barcode ? barcode : "(none)"), ws );
-       }
-
-       jsonObjectFree(userObj);
-       osrfAppRespondComplete( ctx, oilsEventToJSON(response) );
-       oilsEventFree(response);
-
-       if(freeable_uname)
-               free(freeable_uname);
-
-       return 0;
-}
-
-
 
-int oilsAuthSessionDelete( osrfMethodContext* ctx ) {
-       OSRF_METHOD_VERIFY_CONTEXT(ctx);
+    // fetch the user object
+    jsonObject* idParam = jsonNewNumberStringObject(user_id);
+    jsonObject* userObj = oilsUtilsCStoreReq(
+        "open-ils.cstore.direct.actor.user.retrieve", idParam);
+    jsonObjectFree(idParam);
 
-       const char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
-       jsonObject* resp = NULL;
-
-       if( authToken ) {
-               osrfLogDebug(OSRF_LOG_MARK, "Removing auth session: %s", authToken );
-               char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken ); /**/
-               osrfCacheRemove(key);
-               resp = jsonNewObject(authToken); /**/
-               free(key);
-       }
-
-       osrfAppRespondComplete( ctx, resp );
-       jsonObjectFree(resp);
-       return 0;
-}
+    if (!userObj) {
+        return osrfAppRequestRespondException(ctx->session, 
+            ctx->request, "No user found with ID %s", user_id);
+    }
 
-/**
- * Fetches the user object from the database and updates the user object in 
- * the cache object, which then has to be re-inserted into the cache.
- * User object is retrieved inside a transaction to avoid replication issues.
- */
-static int _oilsAuthReloadUser(jsonObject* cacheObj) {
-    int reqid, userId;
-    osrfAppSession* session;
-       osrfMessage* omsg;
-    jsonObject *param, *userObj, *newUserObj;
-
-    userObj = jsonObjectGetKey( cacheObj, "userobj" );
-    userId = oilsFMGetObjectId( userObj );
-
-    session = osrfAppSessionClientInit( "open-ils.cstore" );
-    osrfAppSessionConnect(session);
-
-    reqid = osrfAppSessionSendRequest(session, NULL, "open-ils.cstore.transaction.begin", 1);
-       omsg = osrfAppSessionRequestRecv(session, reqid, 60);
-
-    if(omsg) {
-
-        osrfMessageFree(omsg);
-        param = jsonNewNumberObject(userId);
-        reqid = osrfAppSessionSendRequest(session, param, "open-ils.cstore.direct.actor.user.retrieve", 1);
-           omsg = osrfAppSessionRequestRecv(session, reqid, 60);
-        jsonObjectFree(param);
-
-        if(omsg) {
-            newUserObj = jsonObjectClone( osrfMessageGetResult(omsg) );
-            osrfMessageFree(omsg);
-            reqid = osrfAppSessionSendRequest(session, NULL, "open-ils.cstore.transaction.rollback", 1);
-               omsg = osrfAppSessionRequestRecv(session, reqid, 60);
-            osrfMessageFree(omsg);
+    // If a workstation is defined, add the workstation info
+    if (workstation) {
+        response = oilsAuthVerifyWorkstation(ctx, userObj, workstation);
+        if (response) {
+            jsonObjectFree(userObj);
+            osrfAppRespondComplete(ctx, oilsEventToJSON(response));
+            oilsEventFree(response);
+            return 0;
         }
+
+    } else {
+        // Otherwise, use the home org as the workstation org on the user
+        char* orgid = oilsFMGetString(userObj, "home_ou");
+        oilsFMSetString(userObj, "ws_ou", orgid);
+        free(orgid);
     }
 
-    osrfAppSessionFree(session); // calls disconnect internally
+    // determine the auth/cache timeout
+    long timeout = oilsAuthGetTimeout(userObj, login_type, atoi(org_unit));
+
+    char* string = va_list_to_string("%d.%ld.%ld", 
+        (long) getpid(), time(NULL), oilsFMGetObjectId(userObj));
+    char* authToken = md5sum(string);
+    char* authKey = va_list_to_string(
+        "%s%s", OILS_AUTH_CACHE_PRFX, authToken);
+
+    oilsFMSetString(userObj, "passwd", "");
+    jsonObject* cacheObj = jsonParseFmt("{\"authtime\": %ld}", timeout);
+    jsonObjectSetKey(cacheObj, "userobj", jsonObjectClone(userObj));
+
+    if( !strcmp(login_type, OILS_AUTH_PERSIST)) {
+        // Add entries for endtime and reset_interval, so that we can gracefully
+        // extend the session a bit if the user is active toward the end of the 
+        // timeout originally specified.
+        time_t endtime = time( NULL ) + timeout;
+        jsonObjectSetKey(cacheObj, "endtime", 
+            jsonNewNumberObject( (double) endtime ));
+
+        // Reset interval is hard-coded for now, but if we ever want to make it
+        // configurable, this is the place to do it:
+        jsonObjectSetKey(cacheObj, "reset_interval",
+            jsonNewNumberObject( (double) DEFAULT_RESET_INTERVAL));
+    }
 
-    if(newUserObj) {
+    osrfCachePutObject(authKey, cacheObj, (time_t) timeout);
+    jsonObjectFree(cacheObj);
+    jsonObject* payload = jsonParseFmt(
+        "{\"authtoken\": \"%s\", \"authtime\": %ld}", authToken, timeout);
 
-        // ws_ou and wsid are ephemeral and need to be manually propagated
-        // oilsFMSetString dupe()'s internally, no need to clone the string
-        oilsFMSetString(newUserObj, "wsid", oilsFMGetStringConst(userObj, "wsid"));
-        oilsFMSetString(newUserObj, "ws_ou", oilsFMGetStringConst(userObj, "ws_ou"));
+    response = oilsNewEvent2(OSRF_LOG_MARK, OILS_EVENT_SUCCESS, payload);
+    free(string); free(authToken); free(authKey);
+    jsonObjectFree(payload);
 
-        jsonObjectRemoveKey(cacheObj, "userobj"); // this also frees the old user object
-        jsonObjectSetKey(cacheObj, "userobj", newUserObj);
-        return 1;
-    } 
+    jsonObjectFree(userObj);
+    osrfAppRespondComplete(ctx, oilsEventToJSON(response));
+    oilsEventFree(response);
 
-    osrfLogError(OSRF_LOG_MARK, "Error retrieving user %d from database", userId);
     return 0;
 }
 
-/**
-       Resets the auth login timeout
-       @return The event object, OILS_EVENT_SUCCESS, or OILS_EVENT_NO_SESSION
-*/
-static oilsEvent*  _oilsAuthResetTimeout( const char* authToken, int reloadUser ) {
-       if(!authToken) return NULL;
-
-       oilsEvent* evt = NULL;
-       time_t timeout;
-
-       osrfLogDebug(OSRF_LOG_MARK, "Resetting auth timeout for session %s", authToken);
-       char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken );
-       jsonObject* cacheObj = osrfCacheGetObject( key );
-
-       if(!cacheObj) {
-               osrfLogInfo(OSRF_LOG_MARK, "No user in the cache exists with key %s", key);
-               evt = oilsNewEvent(OSRF_LOG_MARK, OILS_EVENT_NO_SESSION);
-
-       } else {
-
-        if(reloadUser) {
-            _oilsAuthReloadUser(cacheObj);
-        }
-
-               // Determine a new timeout value
-               jsonObject* endtime_obj = jsonObjectGetKey( cacheObj, "endtime" );
-               if( endtime_obj ) {
-                       // Extend the current endtime by a fixed amount
-                       time_t endtime = (time_t) jsonObjectGetNumber( endtime_obj );
-                       int reset_interval = DEFAULT_RESET_INTERVAL;
-                       const jsonObject* reset_interval_obj = jsonObjectGetKeyConst(
-                               cacheObj, "reset_interval" );
-                       if( reset_interval_obj ) {
-                               reset_interval = (int) jsonObjectGetNumber( reset_interval_obj );
-                               if( reset_interval <= 0 )
-                                       reset_interval = DEFAULT_RESET_INTERVAL;
-                       }
-
-                       time_t now = time( NULL );
-                       time_t new_endtime = now + reset_interval;
-                       if( new_endtime > endtime ) {
-                               // Keep the session alive a little longer
-                               jsonObjectSetNumber( endtime_obj, (double) new_endtime );
-                               timeout = reset_interval;
-                               osrfCachePutObject( key, cacheObj, timeout );
-                       } else {
-                               // The session isn't close to expiring, so don't reset anything.
-                               // Just report the time remaining.
-                               timeout = endtime - now;
-                       }
-               } else {
-                       // Reapply the existing timeout from the current time
-                       timeout = (time_t) jsonObjectGetNumber( jsonObjectGetKeyConst( cacheObj, "authtime"));
-                       osrfCachePutObject( key, cacheObj, timeout );
-               }
-
-               jsonObject* payload = jsonNewNumberObject( (double) timeout );
-               evt = oilsNewEvent2(OSRF_LOG_MARK, OILS_EVENT_SUCCESS, payload);
-               jsonObjectFree(payload);
-               jsonObjectFree(cacheObj);
-       }
-
-       free(key);
-       return evt;
-}
-
-int oilsAuthResetTimeout( osrfMethodContext* ctx ) {
-       OSRF_METHOD_VERIFY_CONTEXT(ctx);
-       const char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0));
-    double reloadUser = jsonObjectGetNumber( jsonObjectGetIndex(ctx->params, 1));
-       oilsEvent* evt = _oilsAuthResetTimeout(authToken, (int) reloadUser);
-       osrfAppRespondComplete( ctx, oilsEventToJSON(evt) );
-       oilsEventFree(evt);
-       return 0;
-}
-
-
-int oilsAuthSessionRetrieve( osrfMethodContext* ctx ) {
-       OSRF_METHOD_VERIFY_CONTEXT(ctx);
-    bool returnFull = false;
-
-       const char* authToken = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0));
-
-    if(ctx->params->size > 1) {
-        // caller wants full cached object, with authtime, etc.
-        const char* rt = jsonObjectGetString(jsonObjectGetIndex(ctx->params, 1));
-        if(rt && strcmp(rt, "0") != 0) 
-            returnFull = true;
-    }
-
-       jsonObject* cacheObj = NULL;
-       oilsEvent* evt = NULL;
-
-       if( authToken ){
-
-               // Reset the timeout to keep the session alive
-               evt = _oilsAuthResetTimeout(authToken, 0);
-
-               if( evt && strcmp(evt->event, OILS_EVENT_SUCCESS) ) {
-                       osrfAppRespondComplete( ctx, oilsEventToJSON( evt ));    // can't reset timeout
-
-               } else {
-
-                       // Retrieve the cached session object
-                       osrfLogDebug(OSRF_LOG_MARK, "Retrieving auth session: %s", authToken);
-                       char* key = va_list_to_string("%s%s", OILS_AUTH_CACHE_PRFX, authToken );
-                       cacheObj = osrfCacheGetObject( key );
-                       if(cacheObj) {
-                               // Return a copy of the cached user object
-                if(returnFull)
-                                   osrfAppRespondComplete( ctx, cacheObj);
-                else
-                                   osrfAppRespondComplete( ctx, jsonObjectGetKeyConst( cacheObj, "userobj"));
-                               jsonObjectFree(cacheObj);
-                       } else {
-                               // Auth token is invalid or expired
-                               oilsEvent* evt2 = oilsNewEvent(OSRF_LOG_MARK, OILS_EVENT_NO_SESSION);
-                               osrfAppRespondComplete( ctx, oilsEventToJSON(evt2) ); /* should be event.. */
-                               oilsEventFree(evt2);
-                       }
-                       free(key);
-               }
-
-       } else {
-
-               // No session
-               evt = oilsNewEvent(OSRF_LOG_MARK, OILS_EVENT_NO_SESSION);
-               osrfAppRespondComplete( ctx, oilsEventToJSON(evt) );
-       }
-
-       if(evt)
-               oilsEventFree(evt);
-
-       return 0;
-}