Security Package

The Morfik Secutiry Package provides the required functionality to secure a Morfik website against unauthorized use. In addition, it provides a number of ready-to-use widgets and forms that make securing and subsequent management of a website extremely simple. It should be noted that this package, while providing a moderate level of security to protect against unauthorized use, does not provide protection against malicious attacks.


package-view.png
package-down.png


What's new in version 2.1.0.0

This video shows how you could use the Authentication and Access Control Package to ensure that all aspects of your application security are covered. Learn how to add the security package to your project from scratch and include pre-built security widgets for different security related tasks.


A quick Walkthrough

To use the Morfik Security Package simply add the Ararat Synapse package followed by the Security package to the project that you wish to secure by using the ‘Used Packages’ command on the project ribbon (see Figure 1 Used Packages Command), or simply drag the package files onto the application main client area. Once added a number of widgets will appear on the home ribbon when the form designer is active (see Figure 2 Widget Gallery). These widgets can be placed on application forms and provide immediate functionality without the need for coding or configuration of their properties.


1.png
Figure 1: Used Packages Command

The quickest way to utilize this package is to place the Login Bar widget in the header of the main form of your application, as it exposes most of the key user interface elements related to security and user authentication in one simple widget.


2.png
Figure 2: Widget Gallery


The Login Bar widget provides for user login, new user registration, logout, displaying the current user name, changing the password and in the case of administration, a special link to the security admin pages.


3.png
Figure 3: Login Bar Widget


This is all that is needed to add user authentication to your application. At this point users can self- register and subsequently log in to the site; however, to define access rights for different users you need to add roles and define rules in your application. All aspects of access control are managed in the administration page of this package (which is automatically added to your application).

To access the security administration page, run your application and then login as “admin”. The default password for the Admin user is “admin”. Once logged in click on the Manage Users link to access the security admin pages. The Manage Users link is only visible when a user with administrative rights is logged in.


Note: For security reasons it is highly recommended that you change the default admin password to something else as soon as the package is added to a new project.


To define an access rule click on the Access Rules tab.


4.png
Figure 4: Admin Access Rules Tab


In this page you will see access rules that have been defined for your application. To add a new rule simply click on the Add New Access Rule link at the bottom of the page and a dialog box (see Figure 5 Access Rule Dialog) will appear that prompts for various details of the rule.


5.png
Figure 5: Access Rule Dialog


The Access Rule Dialog has three parts: who the rule applies to; what resources in your application are covered by this rule (new feature include Page resources); and finally whether access is to be granted or denied. Once a rule is defined it immediately takes effect.

Before we continue with the practical aspects of securing your application, it might be useful to discuss some of the basic theoretical concepts in web application security.


Multi-Language Support

The Morfik Security Package now supports the following languages: English, French, Spanish, German, Chinese and Russian. Support for a particular language is triggered by including a lng parameter in the web site URL. For example, to display the Security Package captions and prompts in German, use http://morfik.com/?lng=de. Specifying a language code is not necessary for English.

The codes for non-English languages are show below:

LanguageCode
Frenchfr
Spanishes
Germande
Chinesezh
Russianru


Note: The lng parameter only applies to the Security Package language support. The pages themselves do not automatically change languages since such support is up to the developer.


Startup Options

Two new Boolean constants have been added to the package to control the startup behavior of the Security Package. If the constant cUseCookieForSID is set to True (the default setting), the browser will store the active session in a cookie and consequently, if the page is refreshed or opened in a different browser tab, the user login will be retained.

The second constant, cAutoLoginAtStartup, (also set to True by default) controls whether the session ID will be used to automatically log in the user the next time the web site is accessed using the same browser. For the automatic login to succeed, cUseCookieForSID must also be set to True.


Note: Since the debug browser does not support cookies, this behavior will not be available during debugging.


Web application security — a technical overview

By definition all web applications are multi-user systems with a central repository of resources and a common point of access. It is therefore necessary to provide a mechanism through which the identity of a website visitor can be determined. Once identified, it is highly desirable to be able to control and limit visitors' access to application resources. This requires a system for authenticating a user as well as assigning rights and privileges that determine a user’s level of access to application resources.

User authentication requires the user to register with the system and choose a username and password which can later be used to identify the user. When a registered user visits the site and attempts to access resources that are protected, the application needs to prompt the user to log in so that the identity of the user can be determined. Once username and password are verified and the identity of the user is established, a session record with a unique ID (SessionID) is created and is stored in a session table. All subsequent requests from the same user (that follow within the same browser session) will carry this unique ID which will provide a convenient and also a safe way to establish the user’s identity throughout the remainder of the session (until the user logs out or the session record expires).

Once a user identity is established, either through username and password or through the SessionID, the system will select a subset of access rules that are relevant to both the user and the resource being accessed. Then the rule with the highest priority is chosen to determine whether access should be allowed or denied.

User authentication and session management

User authentication always begins by a call from the browser side, passing the username and password as parameters and requesting a session record to be created. If successful this call will return a unique ID for the session that was created.


Note: In Morfik, a session ID is assigned to a global variable, SecurityID, in the browser-side framework (SecurityID is part of the Morfik browser framework and is independent of this package). Once set the value stored in this global variable is automatically added to all subsequent calls to the server by the framework. This includes all calls for downloading forms, graphical resources or XML data from application data sources (this value is always appended as a URI parameter). On the server side the session ID for a given request can be accessed using HttpServer.Request.SecurityID (or SoapServer.Request.SecurityID for a Web Methods).


A session has a finite life span. If a session is idle for more than a pre-defined length of time (defaults to 6 hours) the session expires and subsequent calls will result in an invalid session error being returned, until the user logs in again. The maximum period that a session can be kept alive is currently set to 24 hours, but this value can also be changed. The two global variables, MaxSessionIdleTime and MaxSessionTime hold these values. A good place to set them (of course, only if required) is inside the On Start event of the main application.

Expired sessions are automatically garbage-collected by a background thread that constantly monitors the session table and removes any session that is expired. The administrator of the site can also expire a session manually by deleting the session record using the session tab in the admin page (see Figure 6 Deleting a session record manually).


6.png
Figure 6: Deleting a session record manually


Anonymous user

When a request is received without the session ID, the request is considered to be from an anonymous user. The User Authentication and Access Control Package allows rules to be defined for this particular class of visitors. It is important however to note that registered users will initially appear as anonymous users until they have successfully logged in. This means that a blanket rule that denies anonymous users all rights will stop all users from accessing any part of the application and hence render the website inaccessible to all.


Roles

Roles provide a simple way to define a set of access rights which can then be easily assigned to a user. To define a new role you need to go to the Roles tab in the admin page. Type the name for the new role in the New Role Name edit box and then click on the Add Role button (See Figure 7 Adding new roles).


7.png
Figure 7: Adding new roles


To assign a user to a role, simply go to the User tab in the admin page, locate the user record and then click on the Roles link (see Figure 8 Assigning users to roles), then tick the role(s) that are to be assigned and finally click on the update button.


8.png
Figure 8: Assigning users to roles


Access rules

Defining access rules is the most critical operation in securing an application. Through access rules you tell the system: ‘who can/cannot access what’. The ‘who’ corresponds to the user scope, the ‘what’ corresponds to the resource scope and the ‘can/cannot’ corresponds to the permission part of a rule. Please refer to A quick walkthrough to learn how to define a rule.

User scope - There are four ways that a user or a group of users can be defined within a rule:


9.png
Figure 9: Rule user scope


• All Users—includes all visitors, both anonymous and those who have logged in. • Anonymous Users—includes all users who are not logged in or not registered. • Role—this option requires a role to be specified. It will then include those users who are logged in and are assigned to the specified role. • User—this option requires a username to be specified (no wildcard available). It will then target that specific user for the application of this rule.


It’s seldom that you need to define an access rule for a specific user. Access rules are almost always defined for roles. It might be useful to also think of Anonymous users as a special role that all unregistered/unsigned visitors are automatically assigned to.

Resource Scope -Application resource types that are covered by a rule are Pages, Forms, Reports, Tables, Queries, Web Methods, File Uploads, Published URLs, Resources and Files as well as custom resources. Every resource is identified by its design time name. In the case of resources such as images and other similar files that are placed in the ProjectResources folder, the relative path to the project resource folder is used for the purposes of rule identification.


10.png
Figure 10: Rule resource scope


Wildcards (*, ?) can be particularly useful in specifying a resource name as they make it possible to define a single rule for a large number of resources.

Permission - Once user and resource scopes are defined, we need to specify whether this rule will allow or deny access to the requested resource. In the case of tables and queries there are additional options that allow for a finer control over what changes can be made by a user. There are four specific permissions: Read, Create, Delete and Update (see Figure 12 Permission options for Tables and Queries).


11.png
Figure 11: Standard Permission Options


12.png
Figure 12: Permission options for Tables and Queries


Rule precedence

An important aspect of rules is the precedence associated with each rule. Rule precedence determines which rule is used when there is more than one rule that can be used for a given request.

For example, for protecting sensitive content a rule is defined to deny access to all and then a rule with higher precedence is defined to allow access for a much smaller group such as site administrators. It is critically important for the role with narrower scope (one defined for the administrators) to have a higher precedence than the rule with the broader scope (applicable to all). Otherwise when an administrator attempts to access the sensitive area of the website, the system would apply the rule with the broader scope and therefore deny access (even though there is another rule that grants access to the administrator).

The rules in the Admin page are ordered by their precedence; the higher the rule in the list, the higher the precedence. Clicking on the up or down arrow will change a rule’s precedence (see Figure 13 Changing rule precedence).


13.png
Figure 13: Changing rule precedence

Securing an XApp

It is important to know that adding the security package by itself does not secure your application. Rules must be defined in order to ensure your application content is protected, otherwise all content within your application will be accessible to any visitor. (The only part of your application that does not require further protection is the content of the security package itself. The content of the security package is already protected through built-in rules. The tables used inside the security package are not published and are therefore implicitly secure.)

Before diving in and starting to add security rules it might be a good idea to step back and adopt a general strategy for meeting the security requirements of your application. Depending on the level of sensitivity of the content within your application there are two general approaches that can be adopted:


1) Optimistic approach—access to all resources is available by default. Rules are defined to limit access.


2) Pessimistic approach—access to all resources is denied by default. Rules are defined to allow access.


The first approach is more suitable for applications that are external facing or applications that provide content that is not sensitive, such as public websites. The second approach provides much tighter security and is suitable for applications that are internal-facing or applications that have highly sensitive content such as corporate/business applications.

The first approach is easier to define rules for. The basic approach is to identify resources that need to be protected and define appropriate rules to secure them.

The second approach relies on a global rule (i.e. lowest precedence) being defined that denies access to all resources.


Note: If unaccompanied by some higher precedence rules for anonymous users, a global rule that denies access to all can make the application dysfunctional—even the site administrator would not be able to access the application! Such rules must ALWAYS be accompanied (or preferably preceded) by a set of rules that are defined for anonymous users and that allow minimum access so the application can start and get to a point where login is possible.


Providing ‘minimum access’ is where the second approach gets somewhat complicated. The minimum resources required for an application to start successfully and get to the point where a user can login vary from one application to another.

One common way to make this tractable is to make the application’s home page comprised of a single form that contains an instance of the login widget. It is not surprising that a login form as the home page is the common face of most high security web applications.

Defining a single rule that allows access to the login form for anonymous users is a good start but we still need to define rules that allow core JavaScript files as well as the main html file to be accessed by anonymous users so the application can make a start. There might also be a need for additional rules that allow for images or other resources that are used within an application's home page.

One way to identify all these resources is to run the application from within the Morfik IDE and then view the HTTP panel and make note of all resources that are accessed. Then define rules to provide access to anonymous users for all these resources (see Figure 14 Minimum resources required to start an application).


Note: The administrator is considered by the system to be an anonymous user until he/she has the opportunity to login.


14.png
Figure 14: Minimum resources required to start an application


Note: It is highly recommended that you do not add global rules that deny access in a general way when the application is live as it could bring the site down. If this ever happens, there is no easy remedy except to manually remove the rule record from the database file using some kind of database utility. As such it is advisable that you test such rules during development and make sure that the security administration section of your application is always accessible by the site administrator.

Protecting Tables and Queries

The most important area of an application to protect is the data that exists in application tables. Morfik automatically creates two Web Methods for every table and query that exists within the application: one to read and one to update data. These Web Methods provide a mechanism for the application framework running in the browser to make JSON calls in order to read or modify data. This also means that any other program can do the same if it knows the schema for the application messages.

It is imperative that application data inside tables or via queries are protected. The best way to protect is to not publish tables and queries. This will cause Morfik not to automatically create Web Methods for reading/writing data for them. Data access can be provided through manually written Web Methods that provide limited access to data along with appropriate security rules to protect against unauthorized use.

To stop a table or query being published, unselect Read and Write buttons on the home ribbon when table or query designers are active (see Figure 15 Stop WSDL publishing of Tables/Queries).


15.png
Figure 15: Stop WSDL publishing of Tables/Queries


Note: Stopping WSDL publishing of a table or query results in the table or query not being allowed to be assigned to the DataSource property of any form whose ViewMode property is equal to vmSingle or vmEditableContinuous. However, it is still possible to assign the table or query to the DataSource property of forms with vmContinuous view mode.


If a table or query has to be published then it is important to define rules to protect against unauthorized use. In most cases access to anonymous users should be limited to read access only. The following Access Rule (Figure 16 Limiting Anonymous Users' Access to Read only) limits anonymous users’ access for Table1 to read-only.


16.png
Figure 16: Limiting Anonymous Users' Access to Read only


Queries essentially follow the same pattern as tables and although rare, can be used to update the underlying tables, so all permission options equally apply to queries. It is important to note that securing a query does not secure the underlying table. The underlying tables need to be secured individually.


Note: Rules that are defined for a table or query are not applied when they are bound to a continuous or editable continuous form (or report). In these situations the form or report must be protected in order to control access to the underlying tables or query.


Protecting Pages

The next items that need protection are the application pages. Pages are crucial to creating Search Engine Optimized web sites and most will have an assigned URL to be used in Hyperlink properties. Since pages with URLs can be reached directly by entering the complete URL in a browser, they are particularly important to secure.

To protect a page, in the Access Rules dialog, as seen in figure 16, under the Type selection drop down list, scroll down to Pages. Once the type is set to Pages, all the available pages will be listed in the Name(s) drop down and any of the pages can be selected. The use of wildcards in names is also supported for pages (see the discussion below in Protecting Forms and Reports). All access to pages is considered to be read-only access.

Access rules are applied to pages only when a page is directly specified in the URL and not when accessed through a Hyperlink property from within the web application or opened using the OpenPage method.


Protecting Forms and Reports

After protecting tables, queries and pages, forms and reports are the next most important application resources requiring protection. Access rules must be defined in order to protect forms and reports within an application. It is only possible to allow or deny access to a form or a report. Access to forms and reports is considered to always be read-only access, regardless of the nature of the code that might have been added to the server side of a form or report.

When naming forms or reports it is good practice to name forms and reports with common security requirements in such a way that a single rule can cover them using a wildcard. For example all forms that are related to the administration of a site can start with the prefix Admin so that a single rule with the resource scope ‘Admin*’ can cover them all.


Note: At runtime forms (as opposed to reports) make two requests to the server during their setup: one for JavaScript code and one for the form html snippet. Both requests are covered by a rule that is defined for the form; however, if the form module is tagged as Static then the code part gets bundled with the application’s main JavaScript and consequently is not protected. A module is declared as Static using a MA (module attribute) meta tag (see Figure 17 The JavaScript code associated with forms declared as Static is not protected);


17.png
Figure 17: The JavaScript code associated with forms declared as Static is not protected


Protecting Web Methods and Modules

Web Methods are protected in a similar way to other project items that have already been covered. Non-visual Web Methods (Web Methods that are defined in standard code modules rather than through using Web Method project items) can also be protected using the same method. When defining a rule for non-visual Web Methods you need to type in their name manually as they do not appear in the list of resources available.


Protecting Project Resources

There are occasions that you might have placed a file within the project resource folder (_<ProjectName>Resources) for some use by the application and do not wish the file to be downloadable. This requires that you specifically define a rule to deny access to this file. A good habit is to define a subfolder with a name such as “system” inside the project resources folder and define a rule that denies access to all files within this subfolder. Using a wildcard such as system\* is all that is needed to secure the subfolder. You can then put any file that you wish to protect in this subfolder with the knowledge that the existing rule will cover the new file.


Protecting Published URLs

Protecting a Published URL is only relevant when the published URL is referenced from an external source (such as links from other websites). Internal hyperlinks (links inside your application) are not affected by Published URL rules. Protecting a Published URL effectively renders a Published URL private and only available for internal use within your application. When it comes to defining an access rule, Published URLs follow the same model as normal project items such as forms, reports tables and queries.


Note: Protecting Published URLs is a strong form of security as it will effectively block all requests related to the Published URL by blocking the main HTML file.


Protecting Custom Requests

To protect requests that target a custom server you need to specify the CLS designator associated with the custom server as the resource Type when defining a rule. A custom server is a server-side class that descends from THTTPServer and is registered with the system using the RegisterCustomHttpServer procedure. You can use ‘All’ as the resource type and that will include the requests to custom servers as well; however, a rule that uses the ‘All’ type could be too general and should only be used to define global rules. Using the ‘All’ type should be avoided when a specific type of resources is being targeted by a rule.

For example, to block all requests to the THTTPFileServer (defined in the SystemServerFile module), which is a custom server inside the framework for serving out files, the following rule should be defined:


18.png
Figure 18: Blocking requests targeting THTTPFileServer


Protecting data in transit using SSL

Whilst user authentication and access control provides protection against unauthorized use, additional measures must be taken to protect application resources after they leave the server and while in transit before arriving in the user’s browser. The most common way to protect data in transit is to use SSL (Secure Socket Layer) through the use of HTTPS protocol. When HTTPS protocol is used, data is encrypted during transit and therefore protected against eavesdropping or other similar attacks.

The HTTPS protocol is considerably slower than the standard HTTP protocol. Consequently it is desirable to only use HTTPS when requesting resources that are sensitive. While this is easily implemented in traditional page-centric web applications, in Morfik (and other Ajax systems) the implementation turns out to be more complicated due to browsers’ cross-domain/cross-protocol restrictions.

These restrictions mean that a Morfik application is not able to selectively choose HTTPS protocol. In other words the use of the HTTPS protocol is an all-or-nothing affair in a Morfik application. There are two ways to go about finding a solution for this problem.

The first solution is to separate that portion of your application that requires SSL by placing the relevant project modules in a separate project which is accessed exclusively using the HTTPS protocol.

The second approach is to get around the browsers’ cross-domain restriction. One common technique is to use a cookie to store the result of a request that is made on the HTTPS protocol and then access the cookie from application’s main code (which would have downloaded using the HTTP protocol). This involves setting up a timer, sending the request using the HTTPS protocol and then polling for a cookie that signals the return of the request and also holds the response from the server. The server code that handles the request must prepare the response in such a way that upon arrival it will get written into a cookie that carries the actual response.


Protecting against malicious attacks

Securing a web application is an open-ended topic and has many aspects that are well outside the scope of this document. It is important to note that securing a Morfik website using the Morfik User Authorisation and Access Control Package does not protect against malicious attacks such as Denial- of-service attack or Dictionary attack.

The scope of security measures that must be taken to protect against malicious attacks goes well beyond application-level security. For example, running your Morfik website and its database server behind a firewall, minimizing the number of services running on the server and limiting it to those that are required for running the application and the database server, and keeping servers up-to- date with the latest patches and software releases, are amongst the many measures that are important in a broader context of security.


Password Recovery

User information is stored in the mfk_secUserAccts table. Users’ passwords are also stored in the same table in MD5 hash format. MD5 provides added security making it not possible (using conventional methods as MD5 is not an encryption method) even for the administrator to retrieve user passwords—as such, password recovery is not possible! However, when a password is forgotten, the system can generate a new password replacing the old one. Added to the mfk_secUserAccts table are two fields: Token and TokenCreateTime. When a user submits a request for password recovery, a unique token is created and stored in the database along with its creation time. The user requesting a password change is then sent a link (containing the token) to the password recovery page (Figure 19) via email. This page provides a means to set a new password given the token contained in the link is valid. The default time of life for a password recovery token is 2 hours after creation, but this can be changed by modifying the global variable TokenExpHours.


19.png
Figure 19: Password recovery page


The system will invoke the OnResetPassword event (which must be assigned programmatically in the current version of Morfik as there is no visual designer for the package object itself). The event handler for this event should be assigned to OnResetPassword which is a global variable in the mfk_secUtil module. Again a good place to make this assignment is in the application On Start event. Below is a code snippet that demonstrates how to send an email to a user who has requested his/her password to be reset.

FX Code

Uses mfk_secUtil, SystemInternet;
 
Procedure HandleResetPassword(Username, FirstName, LastName, Email : String; Var Cancel : Boolean; Var NewPwd : String);
Var
    MailText : TStringList; ErrorMsg : String;
Begin
    MailText := TStringList.Create; 
    Try
        MailText.Add('Dear ' + FirstName + ','); MailText.Add('');
        MailText.Add('Your account password has been reset to:'); MailText.Add('');
        MailText.Add('	Username: ' + UserName); MailText.Add('	Password: ' + NewPwd); MailText.Add('');
        MailText.Add('It is strongly advised that you change your password when you next login!');
        MailText.Add(''); MailText.Add('Thank you,'); MailText.Add(''); MailText.Add('Support');
        SendEmail('my.smtp.com', EMail, 'me@mycompany.com', 'Password Reset Confirmation',
        MailText.Text, 'MySMTPUserName','MySMTPPwd',ErrorMsg); Cancel := Not ErrorMsg.IsEmpty;
    Finally
        MailText.Free; 
    End;
End;
 
Procedure Project52XApp.XAppStart(Sender: TObject); 
Begin
    OnResetPassword := @HandleResetPassword; 
End;



Since this system relies on email notification, this package now includes global variables for a number of email settings including Subject and Content details, as well as SMTP server settings. These can all be found in mfk_secUtil and, as mentioned before, are easily set in the On Start event of your application.

Cookies

The revised version of the security package includes two cookie implementations: a persistent ‘remember me’ type cookie (mfk_secUsername) and a non-persistent session-based cookie (mfk_secSessionID). mfk_secUsername is a cookie used to automatically remember the last username that successfully logs in, and mfk_secSessionID is used to store the current sessionID once logged in.


20.png
Figure 20: The ‘Remember my username’ checkbox uses mfk_secUsername cookie


The second cookie is beneficial to developers in that it provides a way to transfer state information between application instances. Since the sessionID is stored in a cookie, it is easily accessible by any instance of your application running in the same browser session; thus, it is ideal for restoring current sessions and automatic login between applications.

The following WebFormReady code has been modified to check for the cookie’s existence. If found, it attempts to login using the sessionID via the LoginManager:

FX Code

Procedure mfk_secIndex.WebFormReady(Var Ready: Boolean);
Begin
  LoginManager.RegisterEventHandler('Login', GetMethodPointer(Self,@HandleLogin));
  LoginManager.RegisterEventHandler('Logout',GetMethodPointer(Self,@HandleLogout));
 
  If XApp.cookies['mfk_secSessionID'] <> '' Then
  LoginManager.LoginBySessionID(xApp.Cookies['mfk_secSessionID'], nil);
End;



By default, the cookie domain is not set; however, if you’d like to change this, cCookieDomainName may be changed on browser side (mfk_secUtil). For example, a cookie domain name of morfik.com will store cookies that are available to XApps at forum.morfik.com and issuetracker.morfik.com.

Protecting your application programmatically

There are occasions where you might want to protect your application by writing code rather than relying on rules. The need for this usually arises when you have a predetermined role within your application that, as the developer, you want to hard-code into your application and one which you do not want the site administrator to be able to change. A good example of this is the Admin role in the security package. All the Web Methods (non-visual) defined in the security package are protected programmatically rather than through rules.

The way to programmatically protect a resource is to check if the request is from a user that is assigned to the role that has been granted the right to access the resource. The following code demonstrates how this could be done:

FX Code

Uses mfk_secUtil;
 
Procedure Index.WebFormBeforeExecute(Sender: TWebDocument; Var PContinue: Boolean); 
Begin
    With SecurityProviderClass.Create(HTTPServer) Do
    Try
        If Not IsCurrentUserInRole('TargetRole') Then
        Raise Exception.Create('Access Denied!'); 
    Finally
        Free; 
    End;
End;



‘TargetRole’ is the role that the user is expected to be assigned to in order to gain access to the requested resource. For forms and reports this code should be placed in the OnBeforeExecute event-handler and for Web Methods it could be placed as the first statement inside the Execute method.


Note: HTTPServer is a field of the Form object that points to the current request server. The same field exists for tables, queries and reports. For Web Methods, however, this field is called SoapServer.

Login Manager

The LoginManager is a global object introduced by the security package. It resides in the browser side of your application and is responsible for interactions related to login activities that take place between the browser side and the server side of the security package. This object holds information about the current user who is logged in and has a number of useful methods. These include:

Properties:

• SessionID—The current session ID created in response to the user login request • FirstName—Current user’s first name • LastName—Current user’s last name • Username—The username used to log in • Email—Current user’s email address • UserID—Current user’s account record ID • UserRoles—List of roles that the current user is assigned to. Methods: • UserLoggedIn—Returns true or false depending on whether a user is currently logged in or not • CloseSession—Closes the current session by logging the current user out and removing the session record from the session table • Login—Calls a Web Method to authenticate a user by sending a username/password combination and requesting a new session to start • LoginActionPending—Returns true if a login request is currently in progress • RefreshAccoutDetails—Refreshes the account details for the current user • IsUserInRole—Checks if the current user is assigned to a given role • RegisterEventHandler—Registers an event handler for ‘login’ or ‘logout’ events. Once registered the event handler will be called whenever a user is logged in or logged out.

This LoginManager is implemented in the mfk_secClient module.


Receiving global login/logout notifications

There are often circumstances where you might want to show or hide certain parts of your application user interface depending on whether a user is currently logged in, or the role of the current user. In these situations the best way is to register to receive notification independent of the context in which the actual login/logout occurs. Otherwise, you have to make sure that from every place that the user can login/logout you will call the appropriate functions to update the user interface or perform other similar actions.


To receive notification about user login/logout activities independent of the context in which the event occurs, you need to register an event handler with the LoginManager. This can be done using the RegisterEventHandler method as shown below:

FX Code

Uses mfk_secClient;
 
Procedure mfk_secIndex.HandleLogin; Begin
    ShowMessage(‘User just logged in);
End;
 
 
Procedure mfk_secIndex.HandleLogout; Begin
    ShowMessage(‘User just logged out);
End;
 
Procedure Index.WebFormReady(Var Ready: Boolean); 
Begin
    LoginManager.RegisterEventHandler('Login', GetMethodPointer(Self,@HandleLogin)); 
    LoginManager.RegisterEventHandler('Logout',GetMethodPointer(Self,@HandleLogout));
End;


Custom security provider

With the Morfik User Authentication and Access Control Package it is possible to customize the actual implementation of user authentication and/or the storage of the user information. This is made possible through the TSecurityProvider class. The TSecurityProvider class defines an abstract interface between the implementation of the security functions and the rest of the package.

The built-in security provider that comes with the package uses the Firebird database for storing user information and implements user authentication within the TFBSecurityProvider class. This class is a direct descendant of the TSecurityProvider class.

To implement customized security, a class must be derived that descends from the TSecurityProvider class (similar to TFBSecurityProvider) and provides storage and the actual implementation of all abstract methods that are defined in TSecurityProvider class.

To put into effect the custom security class, the global variable SecurityProviderClass in the mfk_secUtil module must point to the new class.


Impact of security checking on application performance

Depending on the type of application, the number and nature of rules and the extent that HTTPS protocol is used in an application, performance may be impacted by the introduction of extra security layers. This is mostly due to the additional processing performed on the server side for every request and the browser’s reduced ability to use cached content (requests for identical resources carry different security IDs when a new session starts and hence are treated as different content by the browser).

To minimize the impact:

1 Keep the total number of rules to a minimum.

2 Use rules that are specific in their resource scope (minimize the number of rules that use ‘All’

for resource type). 3 Prompt for login only when protected resources are accessed. Do not force users to login at the start of your application. 4 Minimise the use of HTTPS protocol.


Widgets

Login Bar Widget — mfk_secLoginBar

The Login Bar widget provides a convenient way to expose all the necessary user interface elements required by an application to allow user login, user logout, user registration, security administration, changing password, password recovery and displaying user name after the user has logged in.


21.png
Figure 21: Login Bar Widget


Remarks: This widget is particularly useful when placed in the header of an application’s main form providing a central location for accessing security related functionality within an application. It can be used by itself or in conjunction with other security widgets without the need for synchronization of state between different widgets.

The font properties of TextLabel controls used inside this widget can be edited by using the ‘Edit Parts’ command which is located in the Layout section on the Home ribbon when the form designer is active. The Left and Top properties of the TextLabel controls cannot be changed as the widgets uses the Flow layout for the arrangement of controls inside its main container.

The Login Bar widget contains the Login Name and Login Status widgets.

Published Properties: None.

Published Events:

OnLogin—This event is invoked after a login attempt is made and the login result is returned to the browser. This event is triggered no matter where the login attempt is made from.

OnLogout—This event is invoked after the user is logged out. This event is triggered no matter where the logout attempt is made from.


Login Name Widget — mfk_secLoginName

The Login Name widget displays the current username using a simple TextLabel control.


22.png
Figure 22: Login Name Widget


Remarks: This widget is pre-configured to monitor user login/logout activities and to display the current username after a successful log in or display “anonymous” when the user logs out or when the application has just started. You could place multiple instance of this widget throughout your application without the need to manually synchronize their states.

Published Properties: None.

Published Events:

OnLogin—This event is invoked after a login attempt is made and the login result is returned to the browser. This event is triggered no matter where the login attempt is made from.

OnLogout—This event is invoked after the user is logged out. This event is triggered no matter where the logout attempt is made from.


Login Status Widget — mfk_secLoginStatus

The Login Status widget provides a link for invoking the login dialog box. After a successful login the same link displays a “sign out” link which can be clicked to invoke the logout command.


23.png
Figure 23: Login Status Widget


Remarks: This widget is pre-configured to monitor user login/logout activities and to display “Sign In“, when no user is logged in, or to display “Sign out” after a user has successfully logged in. You could place multiple instances of this widget throughout your application without the need to manually synchronize their states.

Published Properties: None.

Published Events:

OnLogin—This event is invoked after a login attempt is made and the login result is returned to the browser. This event is triggered no matter where the login attempt is made from.

OnLogout—This event is invoked after the user is logged out. This event is triggered no matter where the logout attempt is made from.


Login Widget — mfk_secLogin

The Login widget provides a pre-configured set of user interface elements that prompt the user to enter username and password, and then it calls the mfk_secLogin Web Method on the server side to perform user authentication.


24.png
Figure 24: Login Widget


Remarks: It is common to hide/show this widget upon successful login/logout. This can be done by intercepting the widget’s OnLogin and OnLogout Events and then setting the widget’s visible property to true or false. The widget’s events are not, however, triggered when the login or logout occurs via other widgets or programmatically. When this widget is used in an application main header or side panel, it is recommended to register for global notification of login/logout events so that this widget can hide or show irrespective of where the login or logout occurs within the application. Please see Receiving global login/logout notifications’.

Published Properties: None.

Published Events:

OnBeforeLogin—This event is triggered after the user has pressed the login button and before the login request is made to the server. This event provides an opportunity to do custom validation of username and password.

OnAfterLogin—This event is triggered after the login request is made and the login result is returned.


Change Password Widget — mfk_secChangePassword

The Change Password widget provides a pre-configured set of user interface elements that allow the user to change his/her password by entering and confirming a new password. It then calls the mfk_secChangePassword Web Method to affect the change.


25.png
Figure 25: Change Password Widget


Remarks: The security package also provides a popup dialog form, mfk_secChangePwdDialog, for changing a password. The change password dialog uses the Change Password widget and is used by the Login Bar widget. To activate simply call the global function RunChangePasswordDialog in the mfk_secChangePwdDialog form module.

Published Properties: None.

Published Events:

OnBeforeChangePassword—This event is triggered just after the user presses the Submit button and before the request to change password is sent to the server. This event provides an opportunity to do custom validation of the new password.

OnAfterChangePassword—This event is triggered after the result for the change password request is returned to the browser.

OnCancel—This event is triggered when the user presses the cancel button.


Password Recovery Widget — mfk_secPasswordRecovery

The Password Recovery widget provides a pre-configured set of user interface elements that allow the user to reset his/her password.


26.png
Figure 26: Password Recovery Widget


Remarks: This widget, contrary to what its name might suggest, cannot recover a password! Once forgotten, a password cannot be recovered as the system only keeps a hashed version of the actual password. The original password is not known to the system and therefore impossible to recover. This widget simply calls the mfk_secResetPassword Web Method to reset the password.

When a password is reset the system triggers the OnResetPassword event on the server side. This event must be used to send an email to the user informing him/her of the new password.

The new password will be sent in clear text (human readable) and as such should be viewed as temporary. The user should be encouraged to change his/her password immediately after resetting.

This widget is used in the mfk_secLoginDialog popup form which combines the Login and Password Recovery widgets to provide a common user login dialog that can be invoked from any context by simply calling the RunLoginDialog global function.

Published Properties: None.

Published Events:

OnBeforePasswordRecovery—This event is triggered just after the user presses the Submit button and before the request to reset password is sent to the server. This event provides an opportunity to do custom validation of the username supplied.

OnAfterPasswordRecovery—This event is triggered after the result for the reset password request is returned to the browser.


Create User Widget — mfk_secCreateUser

The Create User widget provides a pre-configured set of user interface elements that allow a new user to self-register. It also provides a way (Captcha) of verifying that it is a human user that is attempting to register rather than malicious software trying to tamper with your website.


27.png
Figure 27: Create User Widget


Remarks: The Create User widget validates the data entered by the user before executing the Web Method that registers the user with the back-end system. If there is invalid data entered the widget would display an error squiggle below the control in which the invalid data is entered. A short explanation is displayed when the user moves the cursor on the control with error squiggle. Use the OnBeforeCreateUser event to perform custom validation.

The security package also provides a popup dialog form, mfk_secRegisterDialog, for user registration. The dialog form uses the Create User widget and is used by the Login Bar widget. To activate simply call the global function RunRegisterNewUserDialog in the mfk_secRegisterDialog form module.

Published Properties: None.

Published Events:

OnBeforeCreateUser—This event is triggered just after the user presses the Submit button and before the request to create a new user is sent to the server. This event provides an opportunity to do custom validation of various fields of the Create User widget.

OnAfterCreateUser—This event is triggered after the result for the Create User request is returned to the browser.

OnCancel—This event is triggered when the user presses the cancel button.

Technical Documentation

For information on the Security Package internals, please refer to the technical documentation.

See Also


Back to top