• PRODUCT

    PRODUCT

  • PRICING
    PRICING

  • HELP
    HELP

  • BLOG
    BLOG

  • APPSTORE
    APPSTORE

  • COMPANY
    COMPANY

  • LEGAL
    LEGAL

  • LOGIN
    LOGIN

  • Izyware Session Management


  • This article describes the Izyware Session Management system


  • Introduction

    Any multiuser system needs to be able to authenticate, authorize and control the access to its features and resources.

    While currently cookie based authenticatation is the predominant method of implementation, it relies heavily on the domain based security rules implemented by modern browsers. This model would cause challenges when implementing apps in hybrid environments.

    Credential Lifecycle Management UI

    The full life cycle for signing up (create), authenticating (read), updating username/password (update) has been implemented in a self contained package. It is worth mentioning that token persistence has been intentionally decoupled from this package to allow for flexible use in a variety of scenarios (cross-domain, toolbar, embedded, etc.).

    push(["overlay", {

    "parts" : "ext",

    "what" : "ui/w/shell/login/full",

    "initval" : {

    "node" : modtask.node

    },

    "success" : [

    ["query", false, "val", modtask, "user"],

    function(push) {

    modtask.modsess.setUser(

    modtask.user,

    function() {

    push([

    ["push", "onuserstate", modtask]

    ]);

    }

    );

    }

    ]

    }, modtask] );

    modtask.modsess os the interface that should provide sessions persistence via setUser/getUser interface. Below are a few examples.

    Session Agnostic Frames

    The frame will query for the modsess:

    doChain(

    ['frame_getsessman', modtask],

    function() {

    modtask.sessman.getUser(

    function(user) {

    }

    The frame does not really care how the session is managed. The advantage of this approach is that the UI can be reused in the following scenarios:

    Regular Website

    case 'frame_getsessman':

    params['sessman'] = modtask.ldmod('ui/w/shell/sessman/ckbased').sp({

    node: modtask.getNode()

    });

    callback(transition);

    return true;

    break;

    Toolbar
    In a browser toolbar implementaion mode, the cookie based persistence would not be appropriate and instead the global api is used to persist the user object:

    case 'frame_getsessman':

    params['sessman'] = {

    getUser: function(okpush) {

    modtask.getGlobal('user', function(val) {

    if (!val) val = false;

    okpush(val);

    });

    }

    }

    callback(transition);

    return true;

    break;
    Case Study: Embedded Widgets -- Login Wall

    The embedded login wall which is useful for scenarios where the application functionality needs to be made available only to authenticated users (i.e. most of the appid/register/embedded) use the cookie based sesssion manager.

    modtask.sessionCheck = function(push) {

    push({

    parts: 'ext',

    what: 'ui/w/shell/auth/simple',

    onuserstate: [

    function(push) {

    push(['replace', modtask.statusInstructions])

    }

    ]

    })

    }

    The problem with the current implementation for auth/simple is that it does not decouple the session from its implementation and uses ckbased hardwired. A better approach would be to decouple it. Also to make it work cross domain, a new session manage type would need to be created that would rely on iframes (the iframe would store the cookie and would be on the izyware.com or another trusted thirdparty site) and window messaging for communicating state.

    Resource Access

    \ui/node/direct\ is the main component that is used to access cloud resources.

    var node = modtask.ldmod('ui/node/direct').sp({

    // Optional: What sort of access do I have? false means minimal

    accesstoken: false,

    // Where is the service located at?

    dataservice: 'https://izyware.com/',

    // Optional: If using tunnelling to access resources, pass the id

    tunnelendpointid: 'endpointid',

    // What communication stack should I use?

    groupidobject: {

    transportmodule: 'qry/transport/scrsrc'

    },

    // log queries, etc.

    verbose: true,

    // default is true

    encryptqueries : false

    });

    All the other servies, including the identity management system use:

    node.runQuery2(

    q,

    okpush,

    failpush

    );

    Authentication

    The following steps are used for generating an authentication token:

    Step 1
    A username/password is all that is needed to obtain an authentication token. For example, ui/w/shell/login uses the following to login a new user:

    modtask.ldmod('ui/node/api/user').sp({

    node: node

    }).authenticate({

    user : 'username',

    password : 'password'

    },

    function(user) {

    // pass user.accesstoken to your node object

    },

    function(outcome) {

    }

    );

    If successful, this will return a user object which will have the information about the user (role, etc.) and also the authentication token.

    Step 2

    The authentication token may be used to request privilaged services via the \accesstoken\ property of the node object.

    node.sp('accesstoken', user.accesstoken).runQuery2(

    ...

    );

    Persisting the Session

    Unless running in an extension or a mobile app, the session token needs to be persisted in order to avoid login attempts from happening everytime the the page is refresh.

    Case in point is the Shell. After the user is logged in successfully, it uses he \rel:session\ to cookie the current web domain container:

    "success" :

    [

    ["query", false, "val", modtask, "user"],

    function(push)

    {

    modtask.ldmod("rel:session").setUser(

    modtask.user,

    function()

    {

    push(["push", "onuserstate"]);

    }

    );

    }

    ]

    WARNING BUG: for backwards compatibility, it also performs:

    modtask.ldmod("ui/node/auth").set(user.accesstoken) action.

    This will force sign all the node instances to use the user.accesstoken which will cause issues in a multi node environment. See the workarounds section for solutions.

    When the Shell is loaded due to entering the page or refresh, it will call:

    modtask.ldmod("rel:session").getUser(function(user) { })

    This will perform the following checks:

    • If a \cached\ user is defined, just return it, otherwise
    • If the \setUser\ cookie is not defined return no user, otherwise
    • Extract the accesstoken from the the cookie and load user information by:

    modtask.ldmod("ui/node/api/user").sp({ node : modtask.node }).loadsession(

    { "accesstoken" : accesstoken },

    function(user) {},

    ...

    Sharing Scenarios

    temporary accounts

    The sharer sends a user agnostic* link to sharee.

    - when landing on the link, if the session is logged in access will be granted to that session

    - if not logged in you can either

    - force login/account create

    - use temporary accounts to allow temporary access

    the sharer sends a sharee specific* link to sharee

    - because this assumes the sharee is already in the system, if logged in as the sharee it will just work, otherwise if logged in as somebody else or not as sharee it will force them to relogin as the new user.

    Links

    • package bootstrap/5/sessman

    Change Log

    V5.3

    • 530045: add api?login

    * replaces sendmail,user,' + commaEncode(params.user) + ',' + commaEncode(params.password) + ',5'; for runQuery2

    * fixes security issues reported for \

    * lower cases and white space cleanses the username before auth

    V5

    • add api?whoamifull

    * populate session user information from usermetadata

    • add usermetadata data schema
    • add api?whoami

  • Izyware Help Articles
    Izyware Help Articles