/* 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; }
/** @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 */ int oilsAuthInternalCreateSession(osrfMethodContext* ctx) { OSRF_METHOD_VERIFY_CONTEXT(ctx); const jsonObject* args = jsonObjectGetIndex(ctx->params, 0); const char* user_id = jsonObjectGetString(jsonObjectGetKeyConst(args, "user_id")); const char* login_type = jsonObjectGetString(jsonObjectGetKeyConst(args, "login_type")); const char* workstation = jsonObjectGetString(jsonObjectGetKeyConst(args, "workstation")); int org_unit = jsonObjectGetNumber(jsonObjectGetKeyConst(args, "org_unit")); if ( !(user_id && login_type) ) { return osrfAppRequestRespondException( ctx->session, ctx->request, "Missing parameters for method: %s", ctx->method->name ); } oilsEvent* response = NULL; // fetch the user object jsonObject* idParam = jsonNewNumberStringObject(user_id); jsonObject* userObj = oilsUtilsCStoreReqCtx( ctx, "open-ils.cstore.direct.actor.user.retrieve", idParam); jsonObjectFree(idParam); if (!userObj) { return osrfAppRequestRespondException(ctx->session, ctx->request, "No user found with ID %s", user_id); } // If a workstation is defined, add the workstation info if (workstation) { response = oilsAuthVerifyWorkstation(ctx, userObj, workstation); if (response) { // invalid workstation. jsonObjectFree(userObj); osrfAppRespondComplete(ctx, oilsEventToJSON(response)); oilsEventFree(response); return 0; } else { // workstation OK. // The worksation org unit supersedes any org unit value // provided via the API. oilsAuthVerifyWorkstation() sets the // ws_ou value to the WS owning lib. A value is guaranteed. org_unit = atoi(oilsFMGetStringConst(userObj, "ws_ou")); } } else { // no workstation // For backwards compatibility, when no workstation is provided, use // the users's home org as its workstation org unit, regardless of // any API-level org unit value provided. const char* orgid = oilsFMGetStringConst(userObj, "home_ou"); oilsFMSetString(userObj, "ws_ou", orgid); // The context org unit defaults to the user's home library when // no workstation is used and no API-level value is provided. if (org_unit < 1) org_unit = atoi(orgid); } // determine the auth/cache timeout long timeout = oilsAuthGetTimeout(userObj, login_type, 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)); } osrfCachePutObject(authKey, cacheObj, (time_t) timeout); jsonObjectFree(cacheObj); 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); jsonObjectFree(userObj); osrfAppRespondComplete(ctx, oilsEventToJSON(response)); oilsEventFree(response); return 0; }