logon system walkthrough assistance request

Post any questions you have about using the Verj.io Studio, including client and server-side programming with Javascript or FPL, and integration with databases, web services etc.

Moderators: Jon, Steve, Ian, Dave

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

logon system walkthrough assistance request

#1

Postby kotinkarwak » Wed Nov 11, 2015 2:21 pm

Hi,
Need hand holding to understand how to implement user authentication. Using the supplied database resource hence not LDAP and the like.

Have designed a page and using the code

Code: Select all

system.securityManager.logon( [ ["Script", fields.username.value], ["Script", fields.password.value]            														] );
I can see that the supplied security code (ebaseSystemServices -> Scripts ->JS_LOGON_SERVICE_LOGIC) is being executed. I have added a log statement to confirm that the passed in data is received and that is ok.

Code: Select all

14:25:20.155 Info : ** START EXECUTION OF INTEGRATION FORM DefaultLogonService **
14:25:20.155 Info : Running Integration event for DefaultLogonService
14:25:20.155 Info : Executing Javascript script JS_LOGON_SERVICE_LOGIC
14:25:20.161 Info : AK: JS_LOGON_SERVIVE_LOGIC: PARAM1_VALUE->Kaniu PARAM2_VALUE->Ndungu
14:25:20.161 Info : ** END EXECUTION OF INTEGRATION FORM DefaultLogonService **
I think something else is yet to be configured since I can simply type in data to be username and password and the logic passes that as valid whereas that user doesn't exist.

Any help to understand this greatly appreciated.

p.s, using version 5.0.0
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#2

Postby Jon » Wed Nov 11, 2015 6:04 pm

The default implementation of the Logon Service is trying to handle a number of different possibilities and this makes it confusing. But I think it is failing to handle your requirement, so you will need to change it. The changes need to go in script JS_LOGON_SERVICE_LOGIC.

1. Add a function to check if the call is from a script invoking SecurityManager.logon():

Code: Select all

function isScriptCaller(source) {
	return (source == "Script");
}
..where "Script" matches the literal value you are passing in the logon() call.

2. Then change the logic at line 76 to..

Code: Select all

else if ( isJSPSignon(useridSource)  || isScriptCaller(useridSource) )
Note that you can test the Logon Service by opening it in the designer and clicking the run icon on the toolbar. Then complete the parameters something like this:

<req:Request xmlns:req="http://www.ebasetech.com/logon/Request">
<req:PARAM1_VALUE>test userid</req:PARAM1_VALUE>
<req:PARAM1_SOURCE>Script</req:PARAM1_SOURCE>
<req:PARAM2_VALUE>test password</req:PARAM2_VALUE>
<req:PARAM2_SOURCE>Script</req:PARAM2_SOURCE>
<req:PARAM3_VALUE>string</req:PARAM3_VALUE>
<req:PARAM3_SOURCE>string</req:PARAM3_SOURCE>
</req:Request>
0 x

Segi
Ebase User
Posts: 649
Joined: Mon Dec 09, 2013 6:37 pm

#3

Postby Segi » Wed Nov 11, 2015 6:34 pm

I use eBase to authenticate my users.

Setting this up is kind of an involved process but here is how I do it.

1. Create a business project called Login and create a simple logon form where the user enters their name and password and clicks on a Login button.

2. Create a script event for the login button click which will initiate the login by calling the system.securityManager.logon() function. The code should look like this (substitute FLDUSERNAME and FLDPASSWORD for your field names if they are different):

Code: Select all

if &#40;fields.FLDUSERNAME.value == null || fields.FLDPASSWORD.value == null&#41; &#123;
     event.owner.addMessage&#40;"The username or password is blank"&#41;;
     event.stopExecution&#40;&#41;;
&#125;

try &#123;
     system.securityManager.logon&#40;&#91;&#91;"",fields.FLDUSERNAME.value&#93;,&#91;"",fields.FLDPASSWORD.value&#93;&#93;&#41;;
&#125; catch &#40;e&#41; &#123;
     // Parse the error message 
     var errormsg=String&#40;e&#41;;
     
     event.owner.addMessage&#40;errormsg&#41;;
     
     event.stopExecution&#40;&#41;;
&#125;
3. Create a database resource that handles the database login. For example, my database resource is called USERS and has a select query like this: SELECT * FROM USERS WHERE Username=&&USERNAME AND Password=&&PASSWORD. Add this database resource to the LOGON_SERVICE_BV business view by clicking on the blue square with the inverted U shape arrow in it in the database resource->Add resource to existing business view and choose LOGON_SERVICE_BV.
4. Depending on whether you use JavaScript or FPL you need to create the script that does the actual authentication under System Services->Scripts. I call mine LOGON_SERVICE_JS for a JavaScript based script.
5. On the tree at the right hand side expand System Services->Services and double click on LOGON_SERVICE
6. Import the database resource you just created by going to the Tables tab and click on New table (looks like a white page with a star in the corner), select the resource under resource name, click on import columns from resource and choose select all then click on OK twice.
7. Go to the services' properties by clicking on the notepad icon at the top left corner->Events and add the script that you just created to handle the authentication under the System Service tab.
8. In the authentication script (LOGON_SERVICE_JS in my case) perform the authentication:

Code: Select all

try &#123;
     fields.USERID.value=fields.PARAM1_VALUE.value;
     fields.PASSWORD.value=fields.PARAM2_VALUE.value;

     tables.USERS.WHERECLAUSE.value="WHERE LOWER&#40;Username&#41;='" + fields.PARAM1_VALUE.value.toLowerCase&#40;&#41; + "' AND Password='" + fields.PARAM2_VALUE.value + "'";
     tables.USERS.fetchTable&#40;&#41;;

     if &#40; tables.USERS.rowCount > 0 &#41; &#123;
          // Required for eBase SecurityManager to know that the authentication was successfull
     	fields.USERID.value=tables.USERS.REALNAME.value;
          
          // Comment this out to add credentials here as needed which can be accessed by any application to get information about the currently logged in user by doing system.securityManager.getCredential&#40;"REALNAME"&#41;;
          //tables.CREDENTIALS.insertRow&#40;&#41;;
          //tables.CREDENTIALS.ID.value="REALNAME";
          //tables.CREDENTIALS.VALUE.value=tables.USERS.REALNAME.value;
          //tables.CREDENTIALS.updateTable&#40;&#41;;
     &#125; else &#123;
          fields.USERID.value = null;

          fields.ERRORCODE.value = "999991";
          fields.ERRORDESCRIPTION.value = "Your username or password is not correct"; 
          print&#40;"Login failed with the username " + fields.PARAM1_VALUE.value&#41;;
     &#125;
&#125; catch &#40;e&#41; &#123;
   fields.USERID.value = null;   
   fields.ERRORCODE.value = "999991";
   fields.ERRORDESCRIPTION.value = "Your username or password is not correct";
&#125;
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#4

Postby kotinkarwak » Wed Nov 11, 2015 8:38 pm

Thanks, let me spend sometime on this and will report back.

segi, you are defining your own database in this case? What are the benefits over using the provided 'internal' system? I have not reached to think about deployment as yet but would be nice to know this early so I can dedicate enough time to learn the implementation.
0 x

Segi
Ebase User
Posts: 649
Joined: Mon Dec 09, 2013 6:37 pm

#5

Postby Segi » Wed Nov 11, 2015 8:59 pm

Yes I am using my own database to authenticate users. I have my own permission system based on different database tables and incorporate this into the login script. I don't believe that you have quite as much flexibility when using the LDAP authentication.
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#6

Postby kotinkarwak » Wed Nov 11, 2015 10:45 pm

Using internal security database to test but believe Segi also calls this....

I can see the returned value from a successful login using ebasuser account as per the server log output on the right. If I now need to control the show/hide of some controls on the page how do I access this data? I have tried to import the table credential/ebaserole/customrole to the form but placing it on the page shows empty. have imported tables to project and done a fetchdata() on the table but shows empty.

http://screencast.com/t/WOY6IAqMca


P.S Hope my queries are basic enough but I tend to want to figure out the security mechanism of a platform/environment before I delve deeper into code syntax which I believe would answer some of my initial beginner queries, please bear with me.
0 x

Segi
Ebase User
Posts: 649
Joined: Mon Dec 09, 2013 6:37 pm

#7

Postby Segi » Wed Nov 11, 2015 10:58 pm

The credentials are added in the authentication script LOGON_SERVICE_JS like this:

Code: Select all

tables.CREDENTIALS.insertRow&#40;&#41;;
tables.CREDENTIALS.ID.value="REALNAME";
tables.CREDENTIALS.VALUE.value=tables.USERS.REALNAME.value;
tables.CREDENTIALS.updateTable&#40;&#41;;
then you access it in any script by doing this:

Code: Select all

if &#40;system.securityManager.getCredential&#40;"REALNAME"&#41;=="kotinkarwak"&#41; &#123;
     controls.controlname.setHidden&#40;true&#41;;
&#125;
Roles are created in LOGON_SERVICE_JS similarly:

Code: Select all

tables.CUSTOMROLES.insertRow&#40;&#41;;
tables.CUSTOMROLES.ROLEID.value="ROLENAME";
tables.CUSTOMROLES.updateTable&#40;&#41;;
then can be accessed from any script like this:

Code: Select all

if &#40;system.securityManager.hasRole&#40;"ROLENAME"&#41;==true&#41; &#123;
     // Do something here if they have this role
&#125;
You do not need to add the credentials or roles table to your form. Just access it the way I described once you add it in the authentication script.
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#8

Postby Jon » Thu Nov 12, 2015 10:20 am

As Segi says, after user has logged on, you access the security data via the security manager API:

Code: Select all

var user = system.securityManager.userName;
if &#40;system.securityManager.hasRole&#40;"ROLENAME"&#41;..
var realName = system.securityManager.getCredential&#40;"REALNAME"&#41;;
Note though that the supplied Ebase security system supports roles but does not support credentials.

General comments on which security system to use:

1. If all your users are within a single Windows domain, it's best to use Active Directory via LDAP - the main reason is that the logon process can be configured to happen silently in the background and your users don't need to sign on - always a big advantage. Active Directory groups are treated as roles within Ebase so you can use hasRole() as a basis for security. Though configuring the silent logon is quite complicated.

2. If you have some other external security system that all your users already use, then use this.

3. Otherwise you need a bespoke security system that meets your requirements in terms of roles/credentials/authentication etc, almost certainly implemented using database tables. You can use the Ebase Security system for this if you like - it's pretty basic but functional. It supports roles, but not credentials; it also supports a much more detailed authorization system which is probably of no interest to you (it's a legacy feature).

4. You also have a choice over when the user logon occurs: you can do this when the user first connects, or you can do it when necessary using some sort of logon button and then calling securityManager.logon() - you're using this second option.
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#9

Postby kotinkarwak » Thu Nov 12, 2015 2:11 pm

Thanks again for this informative responses.
I have managed to make use of ebase roles as a starting point to conditionally display/perform tasks on the page.

My envisaged application will be web based with a landing page where anonymous resources are accessed by all. A login will be initiated by user. Credential details will need to be managed and associated with the username (ebase) assigned to the given user. I see there will be a bit more involved work to, upon register of user to capture and store this in a database to form basis of credentials. Will embark on that shortly.

Segi, your code shows
tables.CREDENTIALS.insertRow()... I am assuming this is what you doing from your database but in the notes, I don't see table named credentials mentioned from a select point of view.
0 x

Segi
Ebase User
Posts: 649
Joined: Mon Dec 09, 2013 6:37 pm

#10

Postby Segi » Thu Nov 12, 2015 5:23 pm

The table Credentials is built into eBase and allows you to define your own credentials that can be used and accessed in any of your applications. It is not a database table that I created. If you follow the example that I gave you it will work.

I use my own table called USERS that stores all of the user related information.
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#11

Postby kotinkarwak » Thu Nov 12, 2015 7:24 pm

Where does the data for credentials come from? Are these columns in the users table ( assuming, only applies to self created users table since I can't see anywhere where other info like email, full name is entered for the users we create).
0 x

Segi
Ebase User
Posts: 649
Joined: Mon Dec 09, 2013 6:37 pm

#12

Postby Segi » Thu Nov 12, 2015 7:27 pm

The credentials would come (in this case) from your own users table.

I have my own users table with the columns name,emailaddress,username,password (stored in an encrypted format),department etc.

The script LOGON_SERVICE_JS would handle the SQL query that grabs that data based on the username and password from the users table
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#13

Postby kotinkarwak » Fri Nov 13, 2015 11:32 am

http://screencast.com/t/SgVgo9DOCj6

Please find details on use of MySQL database and where I am encountering error.

addendum to video, removed the WHERE keyword in the the database resource definition (01:35).
0 x

Segi
Ebase User
Posts: 649
Joined: Mon Dec 09, 2013 6:37 pm

#14

Postby Segi » Sat Nov 14, 2015 6:00 am

Hi kotinkarwak,

I think you can safely comment out the 2 lines for fields.USERID.value=fields.PARAM1.value and fields.PASSWORD.value=fields.PARAM2.value;

Thanks for the comprehensive screencast. I think I know what the problem is. I am going to assume that you have at least a basic understanding of SQL.

In most of my database resources, I usually use Native SQL because I find it to be a lot more flexible although it does require a little bit more work than assisted SQL the reward is that with a good understanding of SQL you can create in more complex and powerful SQL statements.

Now having said that, if you click on native SQL in your USERS database resource for a moment, you will see that 4 tabs appear for the SELECT,UPDATE,INSERT and DELETE SQL statements where you would write the 4 statements that correspond to each (SELECT,UPDATE,INSERT and DELETE).

The SELECT statement in my native SQL database resource looks like this:

Code: Select all

SELECT * FROM Users &&WHERECLAUSE
In this case, I build the where clause of the SELECT statement myself. However, you are using Assisted SQL so that doesn't really apply and wont work.

Personally, I recommend native or assisted SQL but this can be fixed in one of 2 ways depending on which one you choose for this database resource.

If you want to continue using assisted SQL change the line:

tables.USERS.WHERECLAUSE.value=.... <im>

to these 2 lines: (And by the way, in my case, I convert the username to lowercase so that the username doesn't have to be case sensitive but that's not required. It's up to you. If you want the username to be case sensitive change LOWER(tables.USERS.USERNAME.value) to tables.USERS.USERNAME.value and change fields.PARAM1_VALUE.value.toLowerCase() to fields.PARAM1_VALUE.value)

LOWER(tables.USERS.USERNAME.value)=fields.PARAM1_VALUE.value.toLowerCase();

tables.USERS.PASSWORD.value=fields.PARAM2_VALUE;

If you do decide to use native SQL for this database resource, the WHERE clause that you already have should work fine.

Please let me know if this works. If not, please add more print statements to trace the execution like you already did to figure out where its messing up

Also,

In LOGIN_REQUEST, under the events tab you reference both LOGON_SERVICE_JS and LOGON_SERVICE_LOGIC (which is the FPL login script). You do not need both and this will most like cause issues. Please remove LOGON_SERVICE_LOGIC from the events tab.

Segi
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#15

Postby kotinkarwak » Sat Nov 14, 2015 12:54 pm

Segi,
Thanks again.
Will get there eventually. The Assisted SQL method works, still want to fiqure out the Native one...

I have added the database resource as suggested but when I run it, no progress is achieved. Please confirm your window would be like mine, my database table is named accountmanagement.

http://screencast.com/t/6V6qdNfJX

I am still doing the trace but it fails at same position, the two lines (LOGON_SERVICE_JS) now are.


Code: Select all

     print&#40;"Message1"&#41;;
     tables.SECURITY_USER.WHERECLAUSE.value="WHERE Username='"  + fields.PARAM1_VALUE.value + "' AND Password='" + fields.PARAM2_VALUE.value + "'";    
     tables.SECURITY_USER.fetchTable&#40;&#41;;
     print&#40;"Message2"&#41;;
It prints "Message1" and echoes out the debug line in the console since I have selected the database resource to be logged, but it only shows line .

Code: Select all

Sat Nov 14 12&#58;54&#58;48&#58; DEBUG select * from accountmanagement
I would have expected the where information to appear.[/i]
0 x

Segi
Ebase User
Posts: 649
Joined: Mon Dec 09, 2013 6:37 pm

#16

Postby Segi » Sat Nov 14, 2015 5:12 pm

Ok so on the database resource, you are missing the reference to the WHERECLAUSE resource field.

I'm the resource field at the bottom, click on the green plus to add a field, enter WHERECLAUSE as the name, unchecked persistent (2nd to last check box) and check dynamic sql and then unchecked required and hit save.

When you click on the icon to the right of the save icon again to validate your resource it should say ok. If not this needs to be addressed.

Then try it again
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#17

Postby kotinkarwak » Sat Nov 14, 2015 6:33 pm

Thanks Segi,
Got there in the end.
My code is all a jumble of logs but without that tracing of what was where I would have been lost. managed to implement this in v4.5 and v5.

Phew!!!!! A marathon but the information you and jon shared was invaluable. learnt ebasetech ways.

Will surely come back to this to look at the security angle of it i.e. how do I secure the MySQL database i.e. the current table showing the column password as normal text and the like.

In my culture I now owe you a walking stick!
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#18

Postby Jon » Tue Nov 17, 2015 11:08 am

Kotin,

Here's some general info on using Database Resources. Each Database Resource can operate in only one of two modes:

Table mode: multiple records are returned and updated, data is stored in an Ebase table
Non-table mode: a single record is returned/updated/inserted/deleted, data is stored in Ebase form fields

This subject confuses lots of people. The choice between these two modes is configured in the Options panel in the Database Resource editor. In your case, to look up a single user from a database and check the password, you want to use non-table mode. You also want to use non-table mode to update a single record e.g. to change the password. It isn't technically wrong to use a table for this purpose, it's just confusing.

With Table mode, you create a table in a form, connect it to the resource and then import the columns - in the background this creates mappings between the resource fields and the table columns - click the resource mappings icon on the form toolbar (in V4) to see these. When you issue fetchTable() or updateTable() data is transferred between the form and the resource via these mappings. In table mode you issue script commands against a table and the system works out what SQL to issue on the resource e.g.

Code: Select all

//read any number of records
tables.USERS_TABLE.fetchTable&#40;&#41;;   
//update any changed, inserted or deleted records 
tables.USERS_TABLE.updateTable&#40;&#41;;  
With Non-table mode, you import form fields from the resource by clicking the Import fields icon on the top of the Fields Panel. This creates form fields and also creates the mappings between the form fields and resource fields which work in the same way as for tables. In non-table mode you issue script commands directly to the resource e.g.

Code: Select all

//read a single record
resources.USERS.fetch&#40;&#41;;      
//update a single record
resources.USERS.update&#40;&#41;;   
For more info on this, I recommend the Database and Tables tutorials (Help > Help Index > Tutorials (2nd and 3rd tutorials).

Regards
Jon
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#19

Postby kotinkarwak » Thu Nov 19, 2015 11:04 am

steady she goes!
A query on security between the application server (ebase) and database system (MySQL). Have cut a short video explaining this.

http://screencast.com/t/ehrEwi4Yxw2

The SQL in this case is derived from the database resource defined as follows

-Native SQL
-select

Code: Select all

select * 
from ebase_samples.accountmanagement_test 
&&WHERECLAUSE
-Update
-

Code: Select all

update ebase_samples.accountmanagement_test
&&WHERECLAUSE
0 x
ebasetech v5

Skype: mateso08
Location: Kenya

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#20

Postby Jon » Thu Nov 19, 2015 11:10 am

Check the mappings - between the table and the Database Resource.
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#21

Postby kotinkarwak » Thu Nov 19, 2015 11:43 am

Jon wrote:Check the mappings - between the table and the Database Resource.
Jon, Didn't understand. The mapping should be fine since the updates are taking place as needed. I am querying the underlying nature of the communication since the data is available as plain text while the intent is to have it secure.
0 x
ebasetech v5

Skype: mateso08
Location: Kenya

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#22

Postby Jon » Thu Nov 19, 2015 4:58 pm

Not sure we're talking about the same thing here. In general, if you have a SQL statement like..

Code: Select all

select * from ebase_samples.accountmanagement_test &&WHERECLAUSE 
..and you set WHERECLAUSE in your form to a value, but it doesn't appear in the executed SQL statement, then 9 times out of 10 the mappings are missing.

I'm not sure how much of this stuff you already know, so feel free to ignore this:
  • • A Database Resource contains fields (at the bottom).
    • In the form, the Database Resource fields are then mapped to form fields or table columns. To view and edit these mappings you click on the Resource Mappings icon: in Version 4 this is on the form toolbar, in Version 5 it's in the Resources Panel.
    • When you issue a script statement like fetch() or fetchTable(), data is transferred from the form to the resource and then the SQL statement is constructed.
    • So if the SQL statement is wrong, the mappings are probably missing
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#23

Postby kotinkarwak » Thu Nov 19, 2015 6:22 pm

Please see this short vid http://screencast.com/t/ehrEwi4Yxw2
The setup is all fine but query is on how not to have this information read say in the logs since it is a security risk.
0 x
ebasetech v5

Skype: mateso08
Location: Kenya

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#24

Postby Jon » Fri Nov 20, 2015 9:09 am

Kotin,

To answer your question: the most obvious way to remove the passwords from the log is just to remove the debug option from the Database Resource - you would not normally go into production with debug enabled. The logs are physical files on the server, in tomcat/logs, and these are visible to anyone who can sign on to the server e.g. via remote desktop etc. The designer logs are visible only to you - nobody else will see this data.

At the moment you are using the database to do the encryption, but there is also another way - you can use Ebase to do this. For example you can encrypt a password with:

Code: Select all

var pwd = EncryptionServices.encrypt&#40;fields.Password.value&#41;;
There are a number of methods that allow you to encrypt and decrypt.

So you have two options to encrypt data: overall I would say that getting the database to do it is more secure i.e. if your database is hacked, it's more difficult to extract passwords.

Regards
Jon
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#25

Postby kotinkarwak » Sat Nov 21, 2015 12:28 am

Thanks Jon for clarification.
0 x
ebasetech v5

Skype: mateso08
Location: Kenya

azaleas
Ebase User
Posts: 81
Joined: Thu Jul 30, 2015 12:44 pm

#26

Postby azaleas » Tue Nov 24, 2015 1:19 pm

Segi wrote:Hi kotinkarwak,

I think you can safely comment out the 2 lines for fields.USERID.value=fields.PARAM1.value and fields.PASSWORD.value=fields.PARAM2.value;

Thanks for the comprehensive screencast. I think I know what the problem is. I am going to assume that you have at least a basic understanding of SQL.

In most of my database resources, I usually use Native SQL because I find it to be a lot more flexible although it does require a little bit more work than assisted SQL the reward is that with a good understanding of SQL you can create in more complex and powerful SQL statements.

Now having said that, if you click on native SQL in your USERS database resource for a moment, you will see that 4 tabs appear for the SELECT,UPDATE,INSERT and DELETE SQL statements where you would write the 4 statements that correspond to each (SELECT,UPDATE,INSERT and DELETE).

The SELECT statement in my native SQL database resource looks like this:

Code: Select all

SELECT * FROM Users &&WHERECLAUSE
In this case, I build the where clause of the SELECT statement myself. However, you are using Assisted SQL so that doesn't really apply and wont work.

Personally, I recommend native or assisted SQL but this can be fixed in one of 2 ways depending on which one you choose for this database resource.

If you want to continue using assisted SQL change the line:

tables.USERS.WHERECLAUSE.value=.... <im>

to these 2 lines: (And by the way, in my case, I convert the username to lowercase so that the username doesn't have to be case sensitive but that's not required. It's up to you. If you want the username to be case sensitive change LOWER(tables.USERS.USERNAME.value) to tables.USERS.USERNAME.value and change fields.PARAM1_VALUE.value.toLowerCase() to fields.PARAM1_VALUE.value)

LOWER(tables.USERS.USERNAME.value)=fields.PARAM1_VALUE.value.toLowerCase();

tables.USERS.PASSWORD.value=fields.PARAM2_VALUE;

Segi
Hi guys,
I've been trying to implement the solutions from this topic on my own project. Came up to the point mentioned in the quote. The thing is my code ends with the error message.

Code: Select all

try &#123; 
     //fields.USERID.value=fields.PARAM1_VALUE.value; 
     //fields.PASSWORD.value=fields.PARAM2_VALUE.value; 
     log &#40;"Test starts "&#41;;

		 LOWER&#40;tables.USERS.USERNAME.value&#41;=fields.PARAM1_VALUE.value.toLowerCase&#40;&#41;;
		 log &#40;"user is " + fields.PARAM1_VALUE.value&#41;; 
		 tables.USERS.PASSWORD.value=fields.PARAM2_VALUE;
		 log &#40;"password is " + fields.PARAM2_VALUE.value&#41;; 

     tables.USERS.fetchTable&#40;&#41;; 
.
.
.
My log ends on Test starts message, not getting to other logs. What would be the problem?

1) I've created the DB table called Users with columns UserID, Username and Password.
2) Created where clause via Assisted sql.
3) Have some test users and passwords in db table.

So, whenever I click Authenticate button, I get the error message 999991(When I enter username and password).

Any help would be appreciated.
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#27

Postby Jon » Tue Nov 24, 2015 3:03 pm

I'm not sure what this line will do..
LOWER(tables.USERS.USERNAME.value)=fields.PARAM1_VALUE.value.toLowerCase();
..it looks invalid to me. When you surround code with try/catch blocks, you will catch ALL errors, including any Javascript syntax programming errors. If you want the lower case userid, why not use:

Code: Select all

tables.USERS.USERNAME.value=fields.PARAM1_VALUE.value.toLowerCase&#40;&#41;;
To debug errors like these, you might add log(e) or possibly print(e) to the catch block e.g.

try
{
xx..
}
catch (e)
{
log(e);
}
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#28

Postby kotinkarwak » Tue Nov 24, 2015 3:05 pm

0 x
ebasetech v5

Skype: mateso08
Location: Kenya

azaleas
Ebase User
Posts: 81
Joined: Thu Jul 30, 2015 12:44 pm

#29

Postby azaleas » Wed Nov 25, 2015 6:28 am

Thanks guys for respond,

Jon, actually I also found that code quite confusing, but I thought I can give it a try.

Kotinkarwak, thanks for your screen. I really appreciate it. I'm using V4.5. Given that V5 is still in beta state.

Ok. I'll give it a try. I found some other posts on the forum. Basically, I'm building an app and I need a user authentication and authorization. I went through the Xi Security Management for server-side JavaScript Course, but unfortunately, it mainly talks about LDAP. I'll be using databases table to authorize users, create users and etc.

I think, we, new starters, can all benefit from our moderators and experienced users on this kind of subjects. May be some tutorial series can be created? To share the knowledge.. I know, there're tutorials on help section and some video tutorials. But they are either basiic or lack the comments section:)

Either way, it's really nice to be a part of this sharing and helping community.
0 x

azaleas
Ebase User
Posts: 81
Joined: Thu Jul 30, 2015 12:44 pm

#30

Postby azaleas » Wed Nov 25, 2015 9:25 am

Ok guys, I think I got it to work:

1) I've used Non-table DB resource.

2) Used Assistive SQL and build a where clause as:

Username=&&Username AND Password=&&Password


3) Mapped the fields in Logon Service:
a) Here I've created fields Username and Password
b) Mapped three fields(UserId, Username and Password) with respected columns on DB resource

4) Here's the code:


Code: Select all

importPackage&#40;com.ebasetech.xi.api&#41;;
importPackage&#40;com.ebasetech.xi.services&#41;;

if &#40;fields.PARAM1_SOURCE.value=="SEC_MANAGEMENT"&#41;&#123;

	try &#123;

		log &#40;"1&#41; Testing started "&#41;;
		
		fields.USERNAME.value = fields.PARAM1_VALUE.value; 

		log &#40;"2&#41; USERID value is " + fields.USERNAME.value&#41;;

		fields.PASSWORD.value = fields.PARAM2_VALUE.value;
		log &#40;"3&#41; PASSWORD value is " + fields.PASSWORD.value&#41;;

		var fetchedData = resources.USERS.fetch&#40;&#41;;
		
		if &#40; fetchedData > 0 &#41;&#123; 
          
      log &#40;"User is " + fields.USERNAME.value&#41;;
      log &#40;"Count is " + fetchedData&#41;;
      log &#40;"USERID is " + fields.USERID.value&#41;;

      /*tables.ebaseRoles.insertRow&#40;&#41;; 
      tables.ebaseRoles.ROLEID.value = "SUPER_USER"; 
      tables.ebaseRoles.updateTable&#40;&#41;; */
       
     &#125; 
     // exit    
   &#125; 
   catch &#40;e&#41;&#123; 
   fields.USERID.value = null;    
   fields.ERRORCODE.value = "999991"; 
   fields.ERRORDESCRIPTION.value = "Your username or password is not correct"; 
   &#125; 
&#125;
So, I've tested it and for wrong username and password I receive this error:

JavaException: com.ebasetech.xi.exceptions.LogonException: no user or error code returned by web service


For the username and password matching the DB I get the warning message I've created in my On button event:

Code: Select all

importPackage&#40;com.ebasetech.xi.api&#41;;
importPackage&#40;com.ebasetech.xi.services&#41;;

if &#40;fields.USERNAME.value == null || fields.PASSWORD.value == null&#41; &#123; 
     event.owner.addWarningMessage&#40;"The username or password is blank"&#41;; 
     event.stopExecution&#40;&#41;; 
&#125; 

try &#123; 
     system.securityManager.logon&#40;&#91;&#91;"SEC_MANAGEMENT",fields.USERNAME.value&#93;,&#91;"SEC_MANAGEMENT",fields.PASSWORD.value&#93;&#93;&#41;;
     event.owner.addWarningMessage&#40;"Welcome " + fields.USERNAME.value&#41;; //this is the message I get on succesful username and password match
     
&#125; catch &#40;e&#41; &#123; 
     // Parse the error message 
     var errormsg=String&#40;e&#41;; 
      
     event.owner.addWarningMessage&#40;errormsg&#41;; 
      
     event.stopExecution&#40;&#41;; 
&#125; 
So, here're the questions:

1) Am I doing it right?
2) What would be the next step? Creating rules and roles. How to do that exactly?
3) How to encrypt the passwords for user. On ADP course we saw the EncryptionServices.encrypt method. Would it be applicable or should I use something else?
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#31

Postby Jon » Wed Nov 25, 2015 12:25 pm

1. Are you doing it right?
Almost.. the Logon Service must set a value in the USERID field if the logon is successful - this is part of the the basic contract of a Logon Service. If USERID has a null value, the system will throw an exception with message "no user or error code returned by web service". The database lookup of the userid/password looks fine.

Also, you check that the database lookup has returned one record, but there is no else condition corresponding to userid/password check failed. I would suggest something like the code below (I've stripped out all the logging for clarity).

One other comment.. the catch block will only be executed if there is an error in the try block e.g. you can't get a database connection or there is an error in your code or configuration i.e. once you've got it all working, you do not expect an error here.

Code: Select all

try &#123;
      fields.USERNAME.value = fields.PARAM1_VALUE.value;
      fields.PASSWORD.value = fields.PARAM2_VALUE.value;
      var fetchedData = resources.USERS.fetch&#40;&#41;;
      if &#40; fetchedData > 0 &#41;&#123;
         // Userid/password check successful
         fields.USERID.value = fields.USERNAME.value;
         // add any roles here
     &#125;
     else &#123;
         // Userid/password check failed
         fields.USERID.value = null;
         fields.ERRORCODE.value = "999991";
         fields.ERRORDESCRIPTION.value = "Your username or password is not correct";
      &#125;

     // exit   
   &#125;
   catch &#40;e&#41; &#123;
      // Some other error has occurred
      fields.USERID.value = null;   
      fields.ERRORCODE.value = "999991";
      fields.ERRORDESCRIPTION.value = e;
   &#125;
2. How do you create/maintain users and roles? Well usually you keep these in a database and set up some forms that allow you to display/delete/edit this information. This is the usual stuff of tables, Database Resources etc. I will try and find an example form that includes this functionality.

3. Using EncryptionServices.encrypt and decrypt methods is absolutely fine.
0 x

azaleas
Ebase User
Posts: 81
Joined: Thu Jul 30, 2015 12:44 pm

#32

Postby azaleas » Wed Nov 25, 2015 1:22 pm

As always, thank you very much Jon.

1) I see your point, I'll rearrange my code accordingly.

2) I thought so too. Here's what I've done lately:

a) Created Roles column in DB
b) Added the code to insert the Custom role to CustomRoles table. Acually, I got the code help from other post. Here's the code:

Code: Select all

tables.CUSTOMROLES.insertRow&#40;&#41;;
      tables.CUSTOMROLES.ROLEID.value = fields.ROLE.value;
      tables.CUSTOMROLES.updateTable&#40;&#41;;

c) I've added some code to see if it works. I've created a test button, and used this code to show it:

Code: Select all

   
//I've created Admin rule in my DB table.
if &#40;system.securityManager.hasRole&#40;"Admin"&#41;&#41;&#123;
				controls.BUTTON2.show&#40;&#41;;
				log &#40;"Logged on is " + system.securityManager.userLoggedOn&#41;;
			&#125; 
[/b]

So, it seems like it works. But I thought, rather than inserting the role everytime to the CustomRoles table, wouldn't it be better to check the table first for existing roles?

Thanks again. I'll be waiting for the form then.

3) Ok, good to know.

And, some additional questions:

1) What is exactly XILogonExit? I've read the help text provided, but couldn't quite understand how to implement it with the project or should I even implement it?
2) How to sign off the user?
3) Can SecurityManager.isAuthorized() method be used for Custom rules? Or rather, how to restrict/ grant access to certain things? I have a thought that it should go, something like this:

Code: Select all

 if &#40;system.securityManager.hasRole&#40;"Admin"&#41;&#41;&#123;
				do sth;
			&#125;
But, I'm not sure if this the right approach? I was thinking creating shared functions for specific roles to access/deny certain stuff.
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#33

Postby Jon » Wed Nov 25, 2015 5:23 pm

1) A Logon exit is something that forces all new users through a signon process, this happens when a new user connects for the first time i.e. their session is new. XILogonExit is the name of one of the possible logon exits that are possible, though in reality it is the ONLY one that is ever used nowadays. XILogonExit is capable of collecting user-related information from a number of different sources. In your case, you would use it as an alternative to system.securityManager.logon() to force users to authenticate on arrival. It would then show a default userid/password page (which is a bit primitive), collect the userid and password and pass it to the Logon Service - where PARAM1_SOURCE then has the value 'JSP'.

Bottom line: you should implement XILogonExit if you don't want to allow unauthenticated users into your system. If you want to mix authenticated and unauthenticated users in the same system, you should use system.securityManager.logon() instead.

2) In Version 4 you can't sign off a user (or certainly not easily). In Version 5, you use system.securityManager.logoff();

3) No, you should use system.securityManager.hasRole(). The isAuthorized() method supports much more complex authorisations. You are almost certainly better off using roles. Roles are dead simple - you can have any number of roles and assign any combination of roles to a user. Then you just check with hasRole();
0 x

azaleas
Ebase User
Posts: 81
Joined: Thu Jul 30, 2015 12:44 pm

#34

Postby azaleas » Thu Nov 26, 2015 6:00 am

Thanks Jon,

1) Thanks for clarification on XiLogonExit. I'll dig into it a little bit more to see if I should use it

2) I see. How about using the technique from ADP course when we have a log off hyperlink which basically brings the user to the Log on screen? At least, this way the user would be outside of the main program menu and will have to enter the username/password again. Would it work as a sort of log off?

3) Ok, I'll be using hasRole method then. Thanks for the answer.

4 ) You wrote this code in a prev. answer:

Code: Select all

try &#123; 
      fields.USERNAME.value = fields.PARAM1_VALUE.value; 
      fields.PASSWORD.value = fields.PARAM2_VALUE.value; 
      var fetchedData = resources.USERS.fetch&#40;&#41;; 
      if &#40; fetchedData > 0 &#41;&#123; 
         // Userid/password check successful 
         fields.USERID.value = fields.USERNAME.value; 
         // add any roles here 
     &#125; 
I just want to clarify one thing. I'm using UserID in my DB table as a Primary Key, so its auto incremented integer. And its also mapped to the UserID field in Logon Services. Now, back to the code. U've assigned the value of Username to UserID. Does it mean that in Logon Services UserID field is reserved as regular Username field?
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#35

Postby Jon » Thu Nov 26, 2015 8:37 am

2. If you're happy with this, go for it.

4. Re USERID field. The Logon Service must set the USERID field in the LOGON_REQUEST resource to indicate the id of a successfully signed on user - this is a requirement. As supplied, USERID in this resource is mapped to USERID in the Logon Service. Technically, it's possible to change the name to something else but I wouldn't advise it - it just confuses everything. So the answer to your question is effectively "Yes", use of USERID is reserved.
0 x

azaleas
Ebase User
Posts: 81
Joined: Thu Jul 30, 2015 12:44 pm

#36

Postby azaleas » Thu Nov 26, 2015 11:35 am

Thanks Jon for your answers.
0 x

kotinkarwak
Ebase User
Posts: 109
Joined: Mon Sep 21, 2015 9:55 pm

#37

Postby kotinkarwak » Thu Nov 26, 2015 11:42 am

I am intending to implement a site which allows for anonymous (landing page access) and also for login access and utilizing the same approach you mentioned above utilizing system.securityManager.logon mechanism. Just getting started on setting up of roles.

UPDATE: http://screencast.com/t/tAcjlTc0s
0 x
ebasetech v5

Skype: mateso08
Location: Kenya

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#38

Postby Jon » Thu Nov 26, 2015 2:29 pm

Kotin,

You're asking a question about your encryption of passwords. Your code seems fine to me. As discussed earlier you could use either MySQL or Ebase to do the encryption - they are essentially doing exactly the same thing so very little to choose between them. At the moment you have the salt as a string literal in your code - if you wanted, you could make this more hidden e.g. get it from a database or somewhere else. This all really depends on how secure you want your site to be.

Incidentally, I noticed your code included a very complicated string comparison using java.lang.String.compareTo(). You can achieve the same much easier in Javascript just using the '==' operator e.g.

Code: Select all

var a = "abcdefg";
var b = "vwxyz";
if &#40; a == b &#41; ..
Jon
0 x

kbeg
Ebase User
Posts: 1
Joined: Thu Jan 07, 2016 12:09 pm

#39

Postby kbeg » Thu Jan 07, 2016 1:13 pm

Hello,

I've been stuck for the last few days trying to implement user authentication. Tried with tutorials but they are mostly using LDAP. So I've followed instructions on page 1 by Segi. I'm using ebase derby and created new DB. I have a form with username and password and after onClick event executes I get the error message:

com.ebasetech.ufs.runtime.events.rhinojavascript.JavascriptExecutionHandler$RhinoScriptException:
Can't find method com.ebasetech.ufs.runtime.RuntimeControl.addMessage(string)

I'm using version 5.0.1.

I would appreciate any help.
Kristina.
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#40

Postby Jon » Thu Jan 07, 2016 2:51 pm

This looks like you have a script containing something like mycontrol.addMessage(). There is no addMessage() method - this is what the system is telling you, it should be addErrorMessage() or addWarningMessage().
0 x


Who is online

Users browsing this forum: No registered users and 34 guests