It's likely that some, or many, of the concepts in
Secwin may be new to you. This section provides a helpful primer to some
of the terminology used, so that the subsequent documentation makes more
sense.
Secrets
By necessity security involves the use of secrets.
Without secrets stolen databases would be easy to read, or alter.
Secwin makes use of multiple secrets, set on the
global extension template, to offer maximum flexibility and
security. If multiple apps (think multi-app systems, or desktop app
and web app) are using the same security tables, then they will all
need to use the same secrets.
If your suite consists of multiple app files, compiling as DLL's and
Exe's, then these apps will need to be set to use the same secrets. In
this situation the use of a global, unthreaded, variable likely offers
the most flexibility. These global variable need to be primed before
the application starts accessing the tables.
The
Program Secret is a secret that the developer of
the program (you) sets. This secret will be used in all the Secwin
data tables. If this secret is changed, or forgotten, then the data in
the Secwin tables will be lost. This secret is usually compiled into
the program and is therefore something the program "knows". It does
not need to be stored externally.
Fundamentally the goal of the Program Secret is to protect the
protected data from being read or altered by other programs. It should
not be shared outside of the program developers, and is not needed by
customers or support staff.
The
Table Secret is a secret that the developer of
the program (you) sets. This secret will be used in all the Secwin
data tables. If this secret is changed, or forgotten, then the data in
the Secwin tables will be lost. This secret is usually compiled into
the program and is therefore something the program "knows". It does
not need to be stored externally.
The Table Secret is also used as the Owner (or Password) for ISAM
(TPS) file. This secret needs to be known for read access to the TPS
file via TopScan etc. This secret should ideally not be shared, but
can be shared with appropriate customers or support staff who need to
use TopScan to verify table information. Note that even with this
secret data should not be edited via TopScan as without the program
secret that data will be considered invalid.
The table secret should not be the same as the program secret.
The
Customer Secret is the other end of the
equation. This secret is optional. The customer secret locks the
protected data from access by other customers of the program
(including the developers). To be completely secure the customer
secret should not be stored in a place where anyone else can access
it. The most secure form is a value that the user has to enter when
the program starts.
Of course for most users the use of a custom Customer Secret is
unnecessary - the program being protected simply does not warrant the
extra inconvenience offered by the extra security. Nevertheless a
custom Customer Secret, stored in a separate location to the data
tables, is a useful security step.
IMPORTANT: Changing
Secrets is very difficult and time consuming. So selecting
a unique Program secret and unique Table secret early is very
important. Customer Secrets, if used, need to be set when the program
is first installed for a customer.
Note that in this context these secrets apply to the Secwin Tables,
not to generic data in the application. For more information on
securing data in the application itself use
MyTable.
The secrets can be set on the Secrets tab of the
Global
Extension Template.
Hint: Desktop programs expose the
actual EXE file to possible attackers, Setting the program secret to
an expression, rather than a fixed string, makes it harder to find in
the Exe file. So something like
'sec' & 10 * 4 & 'ret'
is more secure than just
'secret'
This is less of an issue in Web programs, or pseudo web applications
like H5, AnyScreen or TS Plus.
Tables
It's important to understand the editing the
Secwin data tables through a program that does not know, or use, the
program secret is not possible. The use of tools like TopScan, or SQL
Enterprise Manager therefor have limited use when it comes to these
tables. Even data which is stored in plain text (like the user login
or user name) is protected via a hash. Changing these values will
prevent these records from being used in your program.
Encrypted fields are stored as base-64 encoded, so they can more
easily be exported to text etc.
Binding specific security tables to an install is a nuanced topic, and
discussed in the
Security Table
Distribution section. When the time comes to start distribution
this is a section you will want to read through carefully.
Guids
Secwin tables do not make use of auto-incremented
numbers. Rather each row is identified by a Guid field
[1].
This is nothing more, or less, than a 16-character random string which
is easily generated (internally) by the
StringTheory
MakeGuid method.
Many of the various class methods use Guid (String 16) fields to
identify rows in the tables. So each User has a Guid, each Group has a
Guid, and so on. There's nothing magical about this - it is just less
complicated, and less prone to problems, than auto-numbering. As a
bonus it makes data importing, exporting, and merging much easier.
Note 1
Do not confuse this with the MsSQL
GUID data
type - which is also a string(16) but which is often displayed as a 37
character hex-encoded string (with 3 hyphens).
Examples
In all the examples the user password is set to
the username followed by a 1.
So Demo / Demo1
and so on.
A SysAdmin User, Demo, Demo1 has been added so use that for your first
login.
Access Control, Licensing or Both?
One question that comes up a lot is whether you
can implement just access control, or just licensing, or do you have
to do both?
The answer is that you don't have to do both, you can do the two
separately - however to do them separately you end up doing both
anyway.
In other words, consider the case where access control is not
required. You could implement "just licensing", but since access
control is settable at runtime, it makes sense to implement at least
the rudiments of access control, and then allow the user to simply not
make use of it.
Equally with licensing - if you simply don't set any licensing
requirements in your app, and don't populate the SecwinLicense window
for the user to see, then you have "not implemented licensing". That
said, even if you don't actual enforce any license restrictions, it's
not a bad thing to gather customer information for informational and
marketing reasons. So adding licensing, even in free applications,
makes a lot of sense.
A user, is, as the name suggests, a person who uses the program. A
user has a Login and a Password. In addition Email and Phone fields
allow for second factor and password reset communications.
A user can belong to one or more groups, and can also be assigned their
own rights that can override their group rights.
User Levels
There are six possible levels for a user.
- No Level (sw:NoLevel)
- Guest (sw:Guest)
Same as an operator but logs in without a password.
- Operator (sw:Operator)
Can be assigned to groups. Has limited access as set by a
Supervisor or Administrator.
- Supervisor (sw:Supervisor)
Has unlimited access to the program.
Can assign rights to Operators and Groups.
Can not create, delete or edit, users or groups.
- Administrator (sw:Administrator)
Has complete access to the system, and can add, edit and remove
groups and users from the system. They also control the runtime
Secwin settings for the company they are in.
- SysAdmin (sw:SysAdmin)
Same as an Administrator, except has control over all the
companies in the system. The first user in the database has to be
a SysAdmin level user, and this user cannot be deleted if other
users exist.
Aside: The levels are equates, with more powerful levels having a
higher numeric value in the equate.
Hint: Use
SecwinCurrentUser.GetLevel()
to get the current user's level.
Default Rights
Users of type SysAdmin, Administrator and
Supervisor have access to all the program functions of their type.
Users of Type No Access cannot access the application at all. For
these users the Default Rights setting does not apply.
For Operator and Guest users you can set their default access rights.
This is the right that will be assumed, if the right is not explicitly
set on the group, or user level.
The possible options are All, Group or None.
If set to All then the user will have access to the whole program
except for places where they have personally (or all the groups they
are in have specifically) been set to No Access. This is the most
permissive option and should only be used for users who have "almost
Supervisor" levels of access.
If set to Group then the user will inherit their access from their
Group(s), including the default access given to the group(s).
If set to None then only access rights explicitly assigned to the
user, or to one of the groups the user is in, will be available to the
user.
Unlocking a User
If a user gets their password wrong too often they
may be temporarily or permanently
"locked" in the system. In the temporary case they will be
automatically
unlocked after some period of time.
In the permanent case (or indeed in the temporary case) a use can be
unlocked by a administrator by editing the user record, and clicking
on the Unlock User button.
Deleting Users
Because users appear in logs and so on, user
records are not deleted. If you "delete" a user then they appear in
the users list as deleted, and they can no longer log in.
A user can be undeleted by an administrator by editing the user
record, and clicking on the Undelete User button.
User Self Signup
In most desktop applications a user has to be
added to the program, before they can log in. However in many web
applications it is desirable for users to be able to add themselves to
the system - usually with some limited set of functionality being
offered. As products like H5, AnyScreen and TS Plus blur the lines
between desktop and web, this functionality needs to be available for
desktop programs as well.
As with most Secwin features, this functionality is available in both
Desktop and Web applications.
This feature is only available when using Program Login or Windows
Login types. It is not available for programs using Active Directory
authentication.
This feature is only available if either SMS or Email functionality is
available in the program. (The initial password is sent to them using
one of these options).
When a user clicks on the Register button on the login window, then
they will be asked for a Login, their name, an Email address and Phone
number. Once they have completed the form a new password is emailed
(or sms'd to them) so they can login.
User Login Type
Using the Security Policies, it's possible to set
the login type that the program will use. There are a number of
options, including Program logins, and Active Directory logins.
In Active Directory systems it may be desirable to add additional
users - ones not in the Active Directory database, but which need
access to the program. It may also be desirable to have a SysAdmin
user, who can log in without using Active Directory to avoid
The Login Paradox.
Users can be set to have a specific login type (ie Program Login) even
if the program is set to use a different login type. This is done on
the Update User form, on the Other tab.
[1]
Note 1:
If upgrading from a version of Secwin 7, before 7.16, your Other tab
may not have a Login Type setting. If that is the case then you can
either re-import the procedure from one of the examples, or add the
option manually. To add manually;
Desktop
- Add a variable called LoginType of type LONG to the Attributes
GROUP in the Local Data Pad of the SecwinUpdateUsers procedure.
- Add a radio option to the Other Tab for the new LoginType
variable. The Option should have settings for Default(0) and
Program Login (1).
the code will look like this;
OPTION('Login
Type'),AT(10,52,321,51),USE(LoginType),BOXED
RADIO('Default'),AT(20,69),USE(?LOGINTYPE:Default),VALUE('0')
RADIO('Program
Login'),AT(20,83),USE(?Login:Program),VALUE('1')
END
Web
- Add a variable called LoginType of type LONG to the Attributes
GROUP in the Local Data Pad of the SecwinUpdateUsersWeb
procedure.
- Add a RADIO option to the form, on the Other tab, using this
variable.
- Add two radio options, 'Default' (sw:DefaultSetting) and
'Program Login' (sw:ProgramLogin) to the field.
Attributes
One of the goals with Secwin 7 is to make the
user table completely extensible. Different programmers have
different information that needs to be stored in the table. Having
the table in the dictionary helps in this regard, but adding fields
there (and matching hash fields to prevent tampering), and
converting the old tables to new tables can be a lot of work.
To reduce this workload the Attributes BLOB has been added to the
table. This blob contains a structured JSON document, and is freely
extensible with virtually no effort. Indeed to add an attribute to a
user simply;
- Go to the SecwinUpdateUsers or SecwinUpdateUsersWeb procedure
- Add a field into the Local Data, inside the Attributes Group
- Add this field on to the form.
That's it. The rest of the form is done for you. You can then access
the attribute for the currently logged in user using the
SecwinCurrentUser
object, using the
GetAttribute
method. For example;
whatever =
SecwinCurrentUser.GetAttribute('whatever')
If you wish to set an attribute at runtime, then you will need a
SecwinUserRecordClass object.
Once that is created, and initialized, then you can call the
SetAttribute
method. For example;
secUser SecwinUserRecordClass
code
secUser.Init(SecwinUsers,'programsecret','tablesecret','customersecret')
If secUser.LoadUserByGuid(SecwinCurrentUser.GetGuid()) =
sw:ok
secUser.SetAttribute('whatever',somevalue)
secUser.SaveUser()
End
Incidentally the user will inherit attributes from the System
Settings as well, so you can access these via the same
GetAttribute
method. For more on extending SystemSetting attributes see
Extending
the Settings.
For more information on updating an attribute after a successful
login see
Updating
an Attribute after a Successful Login.
Workgroups
Workgroups are a feature from Secwin 1 (through
Secwin 6). It is a LONG value that can be assigned to a user. For
backward compatibility reasons workgroups are preserved in Secwin 7,
although new application may want to take a different approach.
Workgroups can be used in a browse
Runtime Settings
Security is always a balance between security and convenience. The
higher the security level, the more inconvenient it is. Each customer
will have different needs and will find this balance in a different
place.
A key aspect is the ability to configure Secwin at runtime so that
each of your customers can apply the features and policies that they
prefer, and thus balance their security needs against the
inconvenience they are prepared to tolerate.
To configure these settings a user has to be
User
Level of Administrator, or SysAdmin.
General
SMS Available: Tick this
option on if your program has the ability to send SMS's. If this
option is on then SMS can be used as a second factor option, or as a
way for user's to reset their own passwords.
Email Available: : Tick this option on if the
program has the ability to send Emails. If this option is on then
Email can be used as a second factor option, or as a way for user's
to reset their own passwords.
Login Policies
Login Type: Select the Login
method that the program should use.
- No Login
If this is chosen then no user login screen will be
presented to the user. The user will automatically be logged in
as an SysAdmin.
- Program Login
The user will log in with a username and password. These will be
stored locally in a database.
- Active Directory Login (Get username and password)
The user will enter a login and password, this will then be
validated against an Active Directory server. Once inside the
program groups and rights are assigned as normal, and this
information is stored in a local database.
Generally speaking, the existence of at least two SysAdmin users
is a good idea. If the ability for one of them to login is lost,
then the other can be used to restore the first one to working
order. When using Active Directory authentication the use of one
local user (See User Login Type)
is recommended in case the Active Directory credentials are
changed unexpectedly.
- Active Directory Login (User Name from Windows)
The Windows User Name will be checked against the Active
Directory server. No password to the program is required.
Once inside the program groups and rights are assigned as
normal, and this information is stored in a local database.
- Windows Login
The Windows User Name will be used, no password is required.
Once inside the program groups and rights are assigned as
normal, and this information is stored in a local database.
Default User Name From Windows: Prime the User
Name field with the Windows user name.
Allow Remember Login: Allow the program to
remember the user who is logging in, and store that for future
logins.
Tokens Expire After (days): The number of days that auto-login-tokens
are good for. If set to 0 then the tokens do not expire.
Allow Guest Login: Allow the user to login using
a Guest account.
Lockout Policies
This policy can automatically lock a user
account if brute-force logins are detected.
You can set how long the lockout is for, and how many incorrect
passwords will trigger it. When a valid login occurs then the
lockout counter is reset to 0.
If a user is locked, then they can be unlocked by an
administrator in the program. The administrator does this on the
update user screen in the program, by clicking on the Unlock User
button.
Lockout Type:
- None: Users are not locked out, regardless of password fails.
- Temporary: Lockouts are temporary and expire after a certain
amount of time.
- Permanent: Lockouts are permanent. A user must be unlocked by
an Administrator before they can log in again.
If Incorrect Password: The number of incorrect
passwords allowed (in the time specified) before the user will be
locked out.
Times in: The time period being monitored. If,
for example, this is set to 12 hours then the failed counter will
reset after 12 hours. If this is left blank then there is no limit
to the time between fails.
Password Policies
Passwords are always Case Sensitive.
Password policies are often set by the customer against their
specific set of rules. Interestingly these policies often weaken
passwords rather than strengthen them. Nevertheless they may be
required for various reasons.
Minimum Password Length: : Longer passwords are
better. However requiring passwords that are too long can
hinder rather than help security. [1] There is no limit to the
password length in Secwin (although allowing this to be set to
greater than 256 characters will require the entry field on the
Login Window to be made bigger.)
Password Expiry Days: Force the user to change
their password after some fixed number of days. Use of this option
will weaken security. [2]
Do not allow common passwords: Tick this on to
prevent users from using a password that is commonly used. A list of
the hundred thousand (100 000) most common passwords is shipped with
Secwin as
CommonPasswords.Txt. This
file should be included in the same folder as the EXE. This is a
very good option to have on.
Password must contain one or more digits
Password must contain one or more uppercase characters
Password must contain one or more lowercase characters
Password must contain one or more special characters
All of the above are self-explanatory, but do nothing to improve
security [
1,
2].
Use them only if local (bad) policies require them.
Do not allow users to recycle passwords: If this is
on then users will not be able to reuse a recently used password. In
places where mandatory password expiry is set this prevents a small
number of passwords from simply being rotated. (This is a good
policy if you are expiring passwords.)
User Password Self-Reset Method: If Email or SMS
are available then you can allow users to reset their own passwords
(without knowing the current password.)
Setting this option to
Not Allowed means that an
Administrator will be required to reset the password for the user,
on the Update User screen.
Be aware that both SMS and Email can be compromised though so
allowing users to reset their own passwords (without knowing the
existing password) can be a security risk. Requiring an
Administrator to reset the password is more secure, but brings
another human into the loop and communication of the new password to
the user still has to happen securely. Either way it is recommended
that the user change their password, after logging in, the first
time the password is used.
Note 1
https://www.enzoic.com/surprising-new-password-guidelines-nist/
https://pages.nist.gov/800-63-3/
https://www.microsoft.com/en-us/research/wp-content/uploads/2016/06/Microsoft_Password_Guidance-1.pdf
Note 2
https://www.microsoft.com/en-us/research/publication/do-strong-web-passwords-accomplish-anything/
Second Factor Policies
Access to any system can be achieved using one,
or more, of three different items.
- Something you know: This is the
most common. The password is a "secret" in your head. It's
effective as long as this secret remains secret. This approach
works best when the user is making use of a password manager
(which assists with passwords never being reused for two
different programs or services.)
- Something you are: This is
biometrically linked to you, for example a fingerprint, voice
print or face recognition. The quality of these systems vary
somewhat but generally they provide good security.
- Something you have: : This makes
use of a phone, or email, or other device which you control.
This approach remains effective as long as you have control of
the device.
Secwin supports logins that make use of two-factor authentication,
in other words it allows you to login with a password, and/or
email/sms. This approach though can be tedious to use every time so
several policies control how this behaves.
Note that use of this feature implies that your program supports the
sending of Emails or SMSs. If you do not have this facility in your
program, then you cannot make use of Second Factor Authentication.
Second Factor Authentication
- Not Available: This is set if you don't want
to allow second factor authentication, or Email and SMS are not
available in your program
- User Optional: the user can determine if they
want to use Second Factor or not
- Required (Either SMS or Email): Second Factor
logins (at least some of the time) are required to use this
program. Either SMS or Email could be used for this.
- Required (Both SMS and Email): Second Factor
logins (at least some of the time) are required to use this
program. Both SMS and Email will be used for this, the user must
have access to both for the login to work.
Trigger Second Factor When
- Always: The second factor is triggered on
every login.
- On New Machine: The second factor is only
triggered when the user logs in from a new machine.
- On Password Change: The second factor is
triggered when the user uses a new password for the first time.
- Every n Days: The second factor is triggered
on a regular basis, like once a week and so on.
All the above options can be used independently. In other words
the customer may require second factors to be used on a new
machine, and also when passwords change.
Stale Time: : Second factor authentication works
by sending the user a one-time code to their email, or sms device.
This code is generated, and sent, while they are logging in. (This
can delay the login process until the code is received.) However
the code itself should become "stale" at some point - in other
words they need to use it within a time (typically a few minutes)
of generation. A good option here would be 15 minutes or so.
Active Directory
These options are only visible on the settings
form, if the Login Type is set to one of the Active Directory
options.
In this context the word Directory has nothing to do with Folders on
the disk. Rather it refers to a central user directory which allows
administrators to control computer use from a remote location.
Active Directory uses a technology called LDAP and Secwin (via
NetTalk) supports LDAP. The most common Active Directory in use is
the Windows Active Directory Directory Services.
There are two approaches to using Active Directory;
1. The user enters a login and password as usual. Instead of being
validated against a local database though they are passed to the
Active Directory Server and validated there. In addition to this the
user has to be placed in an Active Directory Group in order to gain
access to the program. This allows a remote administrator to control
access to the program - for example terminated employees can be
removed from the group centrally, instead of having to visit all the
different programs individually.
2. The program passes the Windows User Name to the Active Directory
Server. The server then checks the group to see if that user has
access to the program. The user does not (and can not) enter
the user name, and there is no password required. This approach
assumes that logging into the machine itself, as a valid user, is
sufficient authentication. This is also sometimes known as
single-sign-on. This approach can be used in conjunction with Second
Factor Policies to improve security. This approach is only supported
in Desktop programs, not Web programs.
In order to make use of an Active Directory server, some settings
are required. You will need to liaise with the customer's IT
department to get these settings.
Active Directory Server: These details allow the
program to connect to the server itself.
- Host: (required) This is the address of the
server. This could be an IP address, or a DNS (or WINS) name
that resolves to an IP address.
- Port: (required) This is the port the server
is running on. The default port for Active Directory connections
is 389 (for insecure) or 636 (for secure).
- TLS: Tick this on if the connection to the
server should occur over TLS.
- Domain: (required) This is the domain, on the
server, in which all the users, and groups exist.
NOTE: If one of the
required fields above are not set, then the program will be
unable to validate against the Active Directory server. In this
situation a user (if they have a level of Administrator or
higher) will be logged in (without checking) primarily so that
the Administrator can correct the settings.
Active Directory Admin User / Password: These are
the details for an Admin user - one that allows you to make requests
to the server to check if a user is in a group.
NOTE: If these are not set
then the user logging in (if they have a level of Administrator or
higher) will NOT be checked against a Group, even if the Active
Directory Group name is set.
NOTE: If these fields are
set, but either the user name, or password, is incorrect, then the
user logging in (if they have a level of Administrator or higher)
will NOT be checked against a Group, even if the Active Directory
Group name is set.
Active Directory Rights: This is the name of the
Active Directory Group, that the user must be a part of, in order to
gain access to the program.
To learn more about LDAP in general, and Active Directory Directory
Services in particular, see
https://www.capesoft.com/docs/NetTalk12/NetTalkLDAP.Htm.
Of special interest is the number of user logins that are possible
for an Active Directory user -
https://www.capesoft.com/docs/NetTalk12/NetTalkLDAP.Htm#UserLogin
Aside: If you need to brush up on
Active Directory Directory Services because your client wants you to
support it, but you know nothing about it then I recommend this
YouTube playlist. Start with item 5 on that
list. It's an excellent introduction to Active Directory.
User Self Signup
In most desktop applications a user has to be
added to the program, before they can log in. However in many web
applications it is desirable for users to be able to add themselves
to the system - usually with some limited set of functionality being
offered. As products like H5, AnyScreen and TS Plus blur the lines
between desktop and web, this functionality needs to be available
for desktop programs as well.
As with most Secwin features, this functionality is available in
both Desktop and Web applications.
This feature is only available when using Program Login or Windows
Login types. It is not available for programs using Active Directory
authentication.
Allow Self-Signup of new users: If this option is
on then a REGISTER button, or link, will appear on
the Login screen.
Group for Self-signed-up users: Select a group here
that the new user will automatically be placed into. the new user
will have the level of Operator. By controlling the access rights of
this group you effectively control the access rights that
self-signed-in users will have. Once signed up an Administrator can
assign the user into other groups, change their rights, and so on.
Multi Tenant
Default Record: This is ticked
on if this is the default settings record. In a single tenant
situation there should only be a single record in the settings
table, and this field should be checked.
Company: The name of the company that uses these
settings. The value in this field needs to be unique. In
multi-tenant situations the company name is used to distinguish
between tenants. When users log in they may need to identify the
company they are logging into.
PIN: A
PIN code identifier for the company. The value in this field
needs to be unique. The use of PIN codes allows users, in a
multi-tenant setup, to easily identify the company they are logging
into (without needing the whole company name). It is most useful in
situation when displaying a list of companies, and asking the user
to select the correct one, is not desirable.
See Also :
Multi-Tenant,
Making
a Multi-Tenant Web Server Program, with different data folders /
databases
Extending the Settings
This bit is technical, feel free to skip it.
The settings are stored in a table typically called SecwinSettings.
More accurately the settings themselves are stored in a BLOB in that
table called Settings. The blob is
encrypted and hashed to protect the settings while they are on the
disk.
On the SecwinSettings Window they
exist as fields in a group called
SettingsGroup. Unfortunately you cannot manually add items
to this group, because the template will drop all your changes on
the next generate of the procedure.
For this reason an Attributes blob
also exists in the table. You can create a group, and add any fields
you like to the group. These fields can be populated on the Settings
window. The Control template for the window allows you to assign the
group to the Attributes blob in the
table.
This means you are not limited to the features that Secwin provides
- you can easily extend the system to include features specific to
your requirements.
The example app contains a group on the window called AttributesGroup,
with a simple string field called Comments.
This comments field is on the window on the Other tab. The control
template has been set to use this group for the Attributes
blob. In this example you can add whatever fields you like
to this group. Secwin itself does not use the comments field for
anything, and so it can be removed if you wish to do so.
Logins
One key feature of Secwin is that it allows you to create (or more
likely import) a login window for your application. While at first
glance this should be a trivial feature, there are a lot of login
flavors, and this can make the procedure quite complicated. Secwin is
designed to support a whole range of optional login features, and at
the same time allow your customers to choose which of those features
they would like to make use of.
Login Procedure
The start of each application is the login
window (the SecwinLogin procedure). While the cosmetics of the
window can be altered, functional changes to the window should be
applied with care.
The flow of the login window is governed by the
Runtime
Settings. If the login does not work as you wish it to then it
is likely the result of a setting that can be altered. Because many
of the settings are now set at runtime the options in the
UserLogin template have been vastly reduced.
Change Login
A ChangeLogin Code template exists to call the
SecwinLogin procedure. This code template can be added to menu
items, or buttons to change the user that is currently logged in. If
this window is called, and the login fails, or is cancelled, then
the current user remains logged in.
This code template has a template setting for options to pass to the
procedure. It is likely (recommended?) that the option sw:noToken
be used here. This means that any "saved login" will not be used for
this login. (Any existing token will still be used for the next
program login.)
Logout
A Logout Code template exists to call the
SecwinLogout procedure. This is typically called from a button or
menu item on the Frame procedure.
Important: The Logout function
deletes the Remember Login Token. So if a user (who is remembered)
wants to not-be-remembered-anymore then they can do so by clicking
the Logout button.
Tip: If this button is added to the frame, then it's recommended
that on the frame, the User Screen Security, Access Control Tab, No
ACCESS Column at Runtime checkbox is turned ON. Failure to do this
means the program will close immediately when the logout button is
pressed. (This makes sense - if the user is logged out, and the
Frame has the Access Column for runtime settings, then the current
user (which is "no one") suddenly does not have access to the frame,
and the frame therefore closes.
User Changing Their Password
When a user is logged in they are able to change
their password by going to the SecwinChangePassword procedure. This
feature is only applicable if the Login Type is set to Program Login
(as set on the
Runtime Settings
window) . If one of the other types are used then the procedure
posts an error message, and closes.
The user will need to enter the old password, and a new password.
The new password will need to conform to the Password Policies (as
set on the
Runtime Settings window)
in order to be saved.
Current User
A global object called SecwinCurrentUser
(SecwinCurrentUserClass) is created by the global template. This
object is updated when the logged-in user changes.
You can access the properties, and methods, of this object in your
code if you need details about the user.
See Also
SecwinCurrentUser
Remembering
One of the settings that the end-user can choose
to activate is allowing a user login to be remembered.
This makes sense when the user is accessing the program from their
personal computer or device, and where the penalty for someone else
logging in as themself is limited. Of course if a different person
gets access to the device then access to the program is compromised.
In order to remember a user a Token is generated by Secwin, and this
token is stored in the database in the SecwinTokens table. This
token is also stored locally on the device
[1].
When the program is next started, the token is loaded from the
device and tested. If the token is valid then it is automatically
used, and the user is logged in.
In desktop apps the token includes machine information, which makes
the token unportable from one machine to another. On the web (in a
browser) it is not (legally / ethically / transparently) possible to
bind the token to a specific machine. Technically is is possible to
bind the token to an IP address, but since device-IP-Addresses
change so frequently, this is likely not useful (and is not done by
default.)
In both cases the contents of the token are not a secret. The token
itself does not contain the user login, or password
[2].
However the token itself is a valid login, so it should be treated
as such.
Note 1
By default, on the desktop, the token is simply stored in the INI
file
[3]. The token is bound to the
machine (and the program) so "stealing" the token has no value.
There can only be one token stored per machine per user.
On the web the token is stored as a cookie. It can be erased by the
user simply by clearing their cookies (or by clicking on Logout).
The browser usually protects cookies, as long as the connection to
the server is secure (ie using TLS). These tokens are not bound to
the device though, so should be used with care.
In both desktop and web cases, if the user expressly logs out
(SecwinLogout procedure) then the token is deleted on the server,
and the client, and thus any (client side) copies of the token
become useless.
Tokens have an expiry date - by default 30 days. This is one of the
settings set by the SysAdmin when setting the Runtime Settings.
Setting the expiry days to 0 means that the tokens do not expire.
Note 2
The user login and password are NOT stored in the token. So if a
user changes his password, or has his user login changed, this does
not invalidate the token, and remembered logins will still work.
Note 3
The name and location of the INI file is specified on the Secwin
Global extension, Options tab.
If you don't want to use an INI file then you can override the
storage method in Desktop Apps by overriding the LoadTokenFromStore,
and SaveTokenToStore methods in the SecwinLogin and SecwinLogout
procedures.
Note 4
Remembering is only in play for the Program Login, and Active
Directory with User and Password login types. Logging in using the
Windows login name bypasses the need for a user and password, and
hence bypasses the need for a remember token.
Chaining
Secwin allows a user logged into one Exe to be
automatically logged into another exe if that second EXE is RUN from
the first exe. This is known as chaining.
Support for chaining has to be turned on. It is off by default.
Historically this was done on the
UserLoginHere
template (and this setting is still supported if it is on). However
the setting should be set as a parameter when calling the
SecwinLogin procedure.
Chaining is accomplished by passing a token on the command line,
with the syntax login=sometoken. This should be invisible to your
program (unless it it is paying particular attention to the command
line).
Chaining consists of two parts - the caller, and the callee. The
caller creates a token, and passes it to the callee. The callee then
uses the token to log the user in.
Caller
The token is created with a
SecwinTokenRecordClass.
Add this to the procedure that will make the call, using the
SecwinTokenClass
extension template. This will create the object (
secToken),
and take care of initializing the object.
Once the object exists, and has been initialized, it can be used
in one of two ways;
- Generate a command line parameter, and then use this as part
of your normal RUN command. For example;
parameter =
SecToken.GetChainToken('callee.exe',SecwinCurrentUser))
RUN('demo.exe' & clip(parameter))
- OR call the RUN method of the object. For example;
SecToken.Run(SecwinCurrentUser,'callee.exe')
If you have your own parameters then pass them as an extra
parameter
SecToken.run(SecwinCurrentUser,'callee.exe','yourparameters')
You can also pass a waitflag if you want to pause program
execution
SecToken.run(SecwinCurrentUser,'callee.exe','yourparameters',true)
In both the above cases, the currently-logged-in-user information
is gotten from the
SecwinCurrentUser object.
This global object exists in your program, so it can be used here
as-is.
Note: The Caller APP must include a declaration of the SecwinToken
table.
Callee
Historically this option was set on the User
Login Here extension template. This template was added as an
extension to the procedure that called the Login procedure (like
the Main, or Frame procedure.) The setting was called
Allow Automatic Login from other Exes. For backward
compatibility, if this option is set in your program, then it will
be respected, however once this option is off it will disappear
from these options.
The option can (and should) now be set in the login procedure
itself.
Go to the SecwinLogin procedure, to the FOR SecwinLogin extension
and turn on the option there.
Note: The Callee program should have Secwin installed just as you
would for any Exe, and it's capable of being run as an Exe by
itself. The chaining facility does not alter the Secwin
functionality in any way, it simply allows the program to
automatically log a user in using a chained token.
The Login Paradox
The system is setup by Administrator, or
SysAdmin users.
In order to login, a user has to meet all the requirements of the
system.
If the system is set such that it cannot validate any Administrator
or sysAdmin user, then no-one can login to fix the system setup.
When the program is first installed, no users exist, so the user is
logged in as a sysAdmin. However if users already exist, and the
Admin user can no longer login, then how can the settings be
corrected?
For example, say the program is set up to use Active Directory
authentication. This requires that the program be set up to
communicate with the Active Directory server (server name, port
number etc). What happens if those settings are, or become, invalid.
How then to log in to correct the settings. A solution to this is to
create a SysAdmin user who uses local credentials, not Active
Directory credentials. See
User Login Type
for more on this.
Generally speaking, the existence of at least two SysAdmin users is
a good idea. If the ability for one of them to login is lost, then
the other can be used to restore the first one to working order.
When using Active Directory authentication the use of one local user
(See
User Login Type) is
recommended in case the Active Directory credentials are changed
unexpectedly.
Embedding
This section is technical, feel free to skip it.
Embedding in the login window can be difficult to do correctly,
because of the many moving parts and options that go into a login.
However this flow-chart serves as a general guide to the path the
login may take, and hence the best place to embed your own code;
Setting Security Rights
Logging into an application is and important thing
to do, but within the application the customer may want to limit
functionality for users, based on what they are allowed to do. One of
the goals of Secwin is to allow end-users to do this in an intuitive
way, but a way that allows them to understand what a user's rights
are, and how to set them.
A user has to be the level of Supervisor, Administrator or SysAdmin in
order to assign rights to individuals or groups.
Groups
Secwin allows User Groups to be created. A user
has to be at least at the
Administrator Level
in order to create groups.
Using Groups is useful because rights can be assigned to groups.
Then when a new user is added to the system it is not necessary to
set all their rights individually, you can simply assign the user
one or more groups.
If a user is a member of more than one group then they get the
access rights of all the groups. So as long as they have access to
something through at least one of their groups, they will have
access to that something. In technical terms access rights are OR
not AND.
When a group is created you can set its access rights to default to
either ALL or NONE. If set to ALL then the group has access to
everything (by default) and it can be edited to restrict specific
access. If set to NONE then specific access has to be granted to the
group.
Users
A user has to be at least at the
Administrator
Level in order to add users. (With the exception of systems
which allow users to create themselves, more on that later.)
In addition to being in a group a user can have specific rights
which override these group rights. These allows the administrator to
not just to allow specific users to do specific things outside of
their group, but it also allows the administrator to prevent a user
doing something, even if their groups are allowed to do it.
Users who are not part of any group can also have their rights set
on an individual basis.
When a user is created you can set their access rights to default to
either ALL, GROUP or NONE. If set to ALL then the user has access to
everything (by default.) This can then be edited to restrict
specific access. If set to GROUP then the default rights of their
group(s) are used. If any are set to ALL then the user's default is
ALL, if all are set to NONE then the user's default is NONE.
Compile Time
The program developer determines which windows,
and which controls, in the application need to be protected. This is
done with the User Screen Security template.
Procedures can be protected based on the User Level (the user has to
be at or higher than a specific level in order to view the
procedure). This is not changeable at runtime.
The procedure can be set so that access, to the screen as a whole,
can be set (or not set) at runtime.
Controls, or in the case of List Controls, Columns, can be set as
restrictable-at-runtime. These controls can be grouped together, or
have their rights assigned separately.
New controls can inherit their access from an existing control. So
for example if your program has a Delete button, and you have set
rights to that button (at runtime) and then later on you add a Purge
button then you can "default" the purge button to be the same as the
Delete button. (This is just a default, the Purge button can be set
specifically just like any other protected control.)
Run Time
There are two approaches to controlling the
access rights of users at run time.
-
- Go to the window that needs protecting
- Press the system-wide Hot Key (Ctrl-F8 by default)
- Edit the rights for users and groups for that screen
This approach is ideally suited to the less-technical
supervisor. They do not need to understand the bigger
application, they simply go to what they want to protect, and
protect it. It takes slightly longer to do it this way, but can
be done with minimal user training.
- Make use of the Global "Set Access Rights" window. This window
presents a lit of all the procedures which can be protected, and
allows the supervisor to set the rights for all the procedures,
and controls in one place. This approach is faster, but the user
needs an understanding of how the application is arranged, and
what procedures refer to what functions.
Bubbling
Menu Items and Buttons are often set to "Call a
Procedure". Having the button present, but going to an Access Denied
message is not very friendly.
The solution for this in Secwin 6 and earlier was to protect both
the button in the calling procedure, and the destination procedure
as well. this can duplicate work when setting up the system.
Secwin 7 introduces the concept of Bubbling - if a user does not
have access to a procedure then buttons and menu items that call
that procedure (using the template Actions setting) are
automatically hidden.
Additional Program Restrictions
Disabling, and Hiding of controls for access
control purposes does not happen in isolation. There may be other
considerations which also come into play.
One Time
For example an Invoice marked as Paid or Unpaid
may affect other actions the user can perform on a form. The code
belongs in the procedure in the SecAccess.SetWindow
method, after the Parent call. For
example
If INV:paid = False
Disable(?Export)
End
You should only further disable items in this code, not enable
items. You can Disable or Hide controls here.
Update Dynamically
Elsewhere in your code you may need to enable,
or disable controls based on some changing value. For example, in a
Browse, say you wanted to enable, or disable and update button based
on the selected row. So something like "Unpaid invoices can be
altered, Paid invoices cannot be altered."
In this situation you need to combine your test with the data test
to decide whether the control should be allowed or not. This is done
using the
GetControlAccess
method. For example;
If inv:paid = false and
secAccess.GetControlAccess(?Change) = sw:Ok
Enable(?Change)
Else
Disable(?Change)
End
The above code could be placed on the NewSelection event for the
browse, or anywhere else where the inv:paid condition may change.
Multi-Tenant
Multi-Tenant support is optional. It is more likely to occur in a web
context than a desktop context. You can design a system to be
single-tenant, and expand it to be multi-tenant later if you so wish
[1].
See also :
Runtime Settings -
Multi-Tenant,
Making a
Multi-Tenant Web Server Program, with different data folders /
databases .
Introduction
In a Multi-Tenant situation multiple distinct
groups of users exist. These groups are known as Companies. Before
the user can login they (may) have to first identify which company
they are logging in to
[2]. (To avoid
confusion, a Tenant is a Company, and a Company is a Tenant. The
terms can be used interchangeably. They both refer to a record in
the SecwinSettings table.)
Each company will have a record in the
SecwinSettings
table. In a single-tenant case a single record will be
created in the table. One of the records (or the only record) in the
table will be a designated "Default Record" and this in turn will be
the default values for any other companies that are added to the
list.
Users and User Groups belong to a specific company. If a user wants
to access multiple different companies they will need to be added to
multiple times (and will then exist as distinct users.) It is
possible for these uses to have the same login, however they are
fundamentally different records in the user's table. Thus they can
be assigned to different groups, and have different rights,
depending on which "user" is actually logging in. It is especially
worth noting they that can (and likely will) have different
passwords.
Note 1
If you are using SQL, then keeping your Secwin database
separate to your actual database may be something to consider at
this point. When you do implement multi-tenant then you will want
Secwin to be in a different database.
Note 2
See below for a unique-user approach.
If Company-and-user approach is used, then the company needs to be
identified. This may be done specifically by the user, or it may be
done using some other automated means. There are various techniques
to do this, especially on the web.
- The user could use a URL that identifies the company - for
example somecustomer.capesoft.com or someoneelse.capesoft.com.
- The user could pass a parameter to the login form. For example
www.capesoft.com?company=somecompany
- The user could select from a list (perhaps saving that
selection in a cookie for future use.)
- The user could enter a PIN value, matching the company PIN
value to identify the company they are logging into.
Company-And-User versus
Unique-User
There are two ways to identify a user.
Company-And-User
In this approach the user name and company
together are unique. This approach allows for multiple different
users to exist, with the same user login - as long as they are for
different companies. So two customers could each have a user
login (called say Humperdink), but since the company is also
captured during login it is clear who is logging in.
This approach is more flexible, but does REQUIRE that the user
identifies which company they belong to. (This may be active, as
in selecting from a list, entering a PIN code or passive - like by
using a specific URL.)
If the system is single-tenant then that company is assumed, and
the user does not need to identify the company.
Unique-User
In this approach the user name must be unique
across ALL users in the Secwin database, regardless of which data
set they will be accessing.
If Humperdink already exists for one tenant, then another tenant
may not also create a user called Humperdink. This is not a huge
issue for people related login names, (people can be very creative
with their login names) but it can become an issue when more
generic names would be used. For example Administrator or Sales or
other generic titles like that.
Login names in this situation are unique, so there is no need to
select the company during the login process - since the user is
unique, and the user is assigned to a company, the company is
known when the user name is entered.
In Self-sign-up situations it would still be necessary to
determine which tenant the user was signing up for. Again this
might be via selection from a list, PIN code, or URL.
Note: In self-sign-up
situations, where a new Settings record is created (ie a new
Company) then a new user MUST be created at the same time to login
to this company. If no user exists for a company, then it will be
necessary for the sysAdmin user to log in and create a user.
Selecting the Approach
This is one decision that the developer will
need to make.
It only needs to be made once provision for the second tenant is
required. Single tenant systems (or systems that are currently
single tenant) do not need to choose.
If the Unique-User approach is chosen, then it is possible to
switch to a Company-And-User approach with very little effort
later on. If the Company-and-User approach is chosen then
conversion to a Unique-User approach is likely to be more
difficult
[1]. For this reason the
Secwin tables are set up by default to assume Unique-User.
To Switch from Unique-User to Company-And-User the
UserLoginKey
in the
SecwinUsers Table,
in the dictionary must be changed from UNIQUE to NOT UNIQUE. Your
Secwin database (DSSW7.TPS or whatever) also needs to be converted
using your favorite table-converting technique.
Note 1
If all the user logins are unique at the time of conversion then
it will be simple to switch. If not then some users for some
tenants will need to have their login changed - which is likely
not ideal.
Note 2
Using a unique-user approach, make some of the other features more
complex. For example
Default User Name
from Windows would require a lot of effort, across all
tenants, to be useful.
Login Procedure
If multiple tenants exist, and the
Company-And-User approach to login names is being used, then the
user will need to identify their company in the SecwinLogin
procedure.
This is done via a Browse Control on the Company tab. The goal
of this control is to set the
LoginDesktop.SettingsGuid field to the value that the user
selects. The user may then click on the ?LoginButton
control (which will read as Select at this point.)
This approach is easy for the user, but does show the user a list of
tenants. In some cases this may not be desirable. If this is a
problem then entering a unique PIN code for the company can be used
instead. This PIN code is set by the SysAdmin user when creating the
company. A PIN field exists on the tab, and can be unhidden when the
Browse control is deleted.
If neither of these approaches is suitable then feel free to add any
UI to the Company Tab that you like. The only outcome that is
required is that the LoginDesktop.SettingsGuid
field is set to the SecSet:Guid field
of the appropriate company record.
Multi Tenant <> Distinct
Data Set
While it is probable that each tenant will have
a distinct data set (ie in a different database, or different TPS
folder) the two concepts should not be conflated.
Having multiple tenants does not imply multiple data sets. And
multiple data sets does not imply multiple tenants. It is possible
to have multiple tenants sharing the same database, and it's
possible for a single tenant to have multiple data sets.
Managing multiple data sets is a completely different task to
program access control, and so it falls outside the scope of what
Secwin provides. It should in turn be compatible with any
dataset-manager that you use.
Note that Secwin data should be stored in it's own database (or in
the case of TPS it's own TPS file location). In other words Secwin
data should not be inside any one data set. This will make creating
distinct data sets easier to do.
SysAdmin User
If a user has the user access level of SysAdmin,
then they are able to manage the multi-tenant setup. They are able
to create new tenants - create users, and groups, for tenants, and
generally maintain the access rights - across all the tenants.
A SysAdmin user is assigned to a specific set of settings and
policies, (such as password requirements) and these will apply to
her.
A SysAdmin has access to the SecwinBrowseTenants procedure, and from
here can create new tenants, as well as users and groups for those
tenants. In most cases when creating a new tenant, users will need
to be created as well (at the very least an Administrator user for
that tenant so they can add more users and groups)
On the SecwinBrowseTenants a COPY button exists to allow you to copy
settings from an existing tenant when making a new tenant. This will
copy the Settings, and Groups (including Group Access Rights).
When accessing the GlobalSetAccess screen, a SysAdmin will see the
settings for all the groups, and all the operators/guests for all
the tenants.
Licensing
Introduction
The goal of adding licensing to a program is to
increase the revenue received from the program. There are a number
of common approaches to increasing revenue, and Secwin attempts to
allow you to use whichever one(s) you prefer.
Piracy
It should be noted that the goal of licensing
is not "copy protection". While this may seem to be the same as
increasing revenue the two concepts are largely orthogonal, and in
some cases contradictory.
For example the perfect way to prevent piracy is simply not to
release your program. However that generally leads to low revenue.
By contrast high levels of piracy, for a program that is well
licensed, can turn pirate users into paying users, which has the
effect of increasing revenue.
Market Segmentation
Market Segmentation is the idea that all
customers are not equal. Managing the customer requirements, and
budget, allow you to price your product in many different ways
according to what the customer needs, and can afford.
Reoccurring Revenue
Relying on new sales as the primary point of
revenue is problematic when markets become mature, and saturated.
When the cost of the existing customer base exceeds the revenue
received from new customers, the business is in trouble. Some
programs need little or no after-sales support, and the cost of
the existing base is minimal. For other programs the need for
existing customers to adequately pay for after-sales costs has
lead to the reoccurring revenue model becoming both very necessary
and very popular.
Customer Branding
Being able to brand the program to a specific
customer encourages customers to move from being unpaid customers
to paying customers. While copying a program (and license) is
easy, it is less attractive if customer-specific branding appears
on reports etc.
Customer Details
The collection, and proper storage of customer
details is imperative to maintaining an ongoing relationship with
the customer.
Program Levels
Levels allow you to create variations in your
product offering - and thus presumably offer different pricing, and
feature sets to customers.
Levels are always accumulative. So Level 3 always includes all of
Levels 2 and 1.
You can have as many levels in your program as you like.
Programs have a level number, and a Level name.
Level Numbers do not need to be sequential - you can leaves gaps for
future possible interim levels.
Optional Modules
Optional modules serve the same purpose as
levels - allowing for product, and price, differentiation.
Unlike levels, modules are not additive. Access to a specific module
does not imply access to any other module.
Any number of modules can be created. Each one has a number and a
name.
Network Copies
The number of copies of the program, that can be
run, at the same time, on a LAN.
This feature requires NetTalk Desktop.
Expiry Date
The date on which the license will expire.
Online license servers make it easy to implement re-occurring
revenue situations because license expiry dates, and license
renewals, can be done automatically.
Attributes
Attributes are any other details that may affect
your program license, but which are unrelated to the levels or
modules that a user has purchased.
Each attribute has a name, and a value. There is no limit on the
number of attributes that you may create.
For example an attribute might be something like Free Delivery, or
Customer Service Level, or Account In Arrears, or anything of that
nature that you may find useful to add to the license.
In some cases you may find it useful to use attributes set, or
gleaned, from the client system. This is discussed in detail in the
section
Using License Attributes
for Client Generated Information.
Tables
You can limit the number of records that are
allowed in specific tables. So you may sell a system that is limited
to say 100 employee records, or 10 external devices, or whatever
else makes sense for your program.
Counters
Counters allow you to license your program for
specific amounts of usage. For example programs may see on a
per-report-generated basis, or page-view-displayed basis or other
items like that.
The use of counters requires that the program have access to the
internet while running the program, and also that an online
registration server is being used.
License Manager
Introduction
Adding licensing to a program you create is a
two part process. The program itself has to receive the license, and
manage the program in accordance with what the license states, but
equally the programmer needs to be able to create, and manage,
customer licenses. The License Manager utility assists with this
task.
This utility is designed to be run by the developer, not by the end
user.
It makes sense to do most license management online. Customers can
access their licenses (or more accurately, programs installed at
customer sites can access their license) online when the developer
is not awake. Developers can update licenses on the fly, and the new
license will be retried by the program.
In some cases customers may not be able to access the online license
server as their machines do not have access to the internet. In
cases like this the license file will need to be transferred to the
customer via some other means (Email etc.) Note that a small number
of license features require the use of an internet connection, so
for these users those features are not available.
The License Manager is provided as both a web application (based on
NetTalk 11 Server) and a desktop application (based on ABC). Both
applications have a similar feature set, and use a common
dictionary. Both are supplied as compiled EXE programs, and as
source APP files. Since they are meant to be working programs both
make use of other CapeSoft Accessories and are compiled in Clarion
11. You are free to compile the Exe's yourself if you wish to do so.
Non-critical accessories (that you don't have) can be removed or
replaced.
If you wish the benefits of an online server but don't have an
online server of your own, then you can make use of the CapeSoft
Secwin Online Server hosted service for a nominal annual fee.
Install
The License Manager programs
(LicenseManagerDesktop.Exe and LicenseManagerWeb.Exe) are installed
into your
\Clarion\Accessory\SecwinLicenseManager folder.
It is NOT recommended that you run the programs directly from this
folder. Rather move them from this folder to a production folder.
Items in this
\Clarion\Accessory\SecwinLicenseManager folder may be
updated by subsequent Secwin installs, so customizations in this
folder (or sub folders) could be lost.
The program and DLL's it uses, as installed in the above folder, is
(likely) compiled with a different version of Clarion to the one you
have. Therefore DLL's in this folder should be considered to be
"tied" to these Exes, and should not be copied to folders with other
Clarion programs.
Source
Source code for the programs are in the
\Clarion\Accessory\SecwinLicenseManager\source folder. The
source apps, and dictionary are written in Clarion 11. TXA's and a
DCTX file are provided if you wish to back-port the source to an
earlier Clarion version.
As these are primarily designed to be working programs "as is" they
include a number of accessories. If you do not have all the
accessories then these will be dropped from the app when you open
it. In some cases this will reduce functionality, but not inhibit
the core purpose of the program in generating licenses.
Desktop
Required |
Optional |
jFiles |
Draw |
MyTable |
File Manager 3 |
NetTalk (Desktop) |
Hyperactive |
RecentLookups |
OfficeInside |
Secwin |
Premiere |
StringTheory |
Resize and Split |
|
RunScreen |
|
SendTo |
|
xFiles |
|
WinEvent |
Web
Required |
Optional |
jFiles |
File Manager 3 |
MyTable |
SelfService |
NetTalk (Server) |
WinEvent |
RecentLookups |
|
Secwin |
|
StringTheory |
|
xFiles |
|
As at build 7.03 the Desktop program is "complete" and the Web
program API is "complete", but the Web interface needs work.
Products
Not surprisingly, the license process starts
with the product you have created. Most companies may end up with
only one product in the list - some others may end up with more.
Most of the product information concepts have been discussed
above,
but the following items are of interest here;
Product License Name |
This is the name as entered on the Secwin Global
Extension, License Tab |
Product Version |
This is the (major) version number as entered on the
Secwin Global Extension, License Tab |
Default License Period |
The default amount of time (in days) to allow when
temporary default licenses are issued. |
License Secret |
This is the secret as entered in the program, on the
Secwin Global Extension, Secrets tab. |
External ID |
An ID field provided for your use for linking this table
to other tables in other programs in your business. |
Customers
Company information is pretty straight-forward.
The only item of interest here is the External ID which can be used
to link this record to other records in other programs. You can put
whatever you like in this field.
Licenses
When the product is running at a customer site,
the program will periodically connect to the licensing server. In
this way the program can provide updated customer information to
you, and you can push updated license information to the customer.
In cases where the customer is not online (or the developer is not
making use of an online server) then the license can be generated by
the License Manager and transferred to the program via another
means. A typical license looks like this;
the license includes all the information, including the customer
information. So in an offline situation the customer does not need
to match their customer details to your customer details - you can
simply capture their details and send them the license.
The License Manager has the options to create an email, or copy the
license to the clipboard for you.
In addition to the customer, and product details there are a number
of other fields you can capture on the Update License window. Most
of these fields don't intrinsically mean anything, so you are free
to use them for any purpose.
Dealer |
The name, or ID of a dealer that delivered the sale. The
program doesn't do anything with this value, but allows you
to sort the browse by dealer. |
Serial Number |
The program doesn't do anything with this value, but
allows you to sort the browse by serial number. |
Type |
The form offers two radio options, Temporary and
Permanent. However you can add additional options here if
you like. Again this option does nothing by default, it is
mostly for information for the customer. Regardless of the
type the Expiry Date still applies. |
Secwin Online Server
Secwin Online Server is a hosted version of the
License Manager Web program. This means you don't need to host your
own servr, but rather make use of the one provided by CapeSoft.
As a hosted service there is a small annunal fee asociated with using
this server (currently $69 per year). This fee is fixed regardless of
how many client programs you sell that make use of the service. To
order the service go to
ClarionShop
Once your order has been processed you will be issued with a Dataset
name, Login and Password so that that you can access the site (
https://api7.secwinonline.com/.
Using this interface you can add products and customers, as well as
issue, or modify client licenses.
Online Setup
The minimum you will need to do on the server is
- Using your browser log onto https://api7.secwinonline.com/
- Go to the Browse / Products menu item
- Add your product to the list. the most important settings are on
the first tab. The Product License Name, Product Version and
Product License Secret must all match the settings
For more product details you can set see the section on Products
above.
Customer information can mostly be entered by the customer themselves
on the License window in your application.
You can control the license issued to the customer via the Licenses
menu option.
Program
Changes
Adding support for the Secwin Online Server to
your program is straight-forward.
- Go to the SecwinLicense procedure, to the FOR the
SecwinLicense Procedure Extension template.
- Set the Online Server URL to 'https://api7.secwinonline.com'
- Set the Online Server Dataset to the name issued to you by
ClarionShop.
Global Objects
To improve performance for some common tasks, and
to reduce access to the database, some global objects are generated by
the templates, and used in various places in the code. Primary it is
used as the user navigates around the program to determine the access
rights to that procedure. However they may also be useful to you for
quick access to information.
SecwinGroupsCache Global
Object
This is a global, unthreaded, object which is
internally thread safe. Do not access the properties of this object
directly - use the supplied methods. This object is available in
both desktop and web applications.
This object contains a cache of all the groups, and related group
information. the cache is loaded by a call to LoadCache, and if the
group information has been altered it can be refreshed with a call
to LoadCache(sw:force).
The GetNames method takes in one, or more guids (as a pipe separated
list, or json document) and returns one, or more, group names, as a
comma separated list.
In a multi-tenant program this object contains all the groups, for
all the tenants. To get a list of groups (as a pipe-separated list)
that belong to a specific tenant use the GetGuids method.
The internal list of group guids and names can be copied out of the
object, into a local queue, using the CopyQueue method. This is used
internally in the SetAccessRights and GlobalSetAccessRights screens.
For a complete class reference see SecwinGroupsCacheClass.
SecwinCurrentUser Global
Object
After a user has logged in, a global object
called SecwinCurrentUser is populated with the details of the user.
This class is designed to quickly access details about the current
user without needing to re-read the database. Internally it is used
to determine the user's access as she navigates around the program.
The SecwinCurrentUser object can also be used in your own code to
get information about the current user. This information is exposed
via a number of methods provided by the object.
For a complete class reference see
SecwinCurrentUserClass
SecwinProcedureList Global
Object
This object is populated globally when the
program starts. It is used to translate procedure names (such as you
would call when using say a button or menu item) to a procedure ID
(which is used for setting access rights).
This object is unthreaded, so is made threadsafe via a critical
section. You will not typically make se of this object from your own
hand-code.
For a complete class reference see
SecwinProcedureListClass.
Background Logo Procedure
The general idea of the Background Logo procedure
is to provide a background to your application frame which is more
than just a graphic or color. The window is an actual window in your
application, and as such can contain anything you want. This
window never gets focus, however it can contain buttons, so can make
for a background-menu of sorts.
Use of this feature is important for Branding, and can also provide a
useful place to display information to the user.
Support for this falls into two places;
MDI Logo Procedure
An extension to a normal Clarion window. This
window MUST have the MDI attribute ON.
For best results, set the FrameType (ie the border) of the window to
NONE, the Caption to nothing, the Position to CENTER.
TURN OFF the "Save and Restore window Position" on this window.
The examples include a window that behaves like this. It is the Background procedure. Not that this example
procedure also includes embed code, showing how to create custom
strings to display on the window.
This window will automatically be centered in the frame, and remain
centered in the frame. If you wish to trigger a refresh on this
window (because some item you have been displaying is updated
elsewhere, then you can post an event to the window, and it will
refresh.
Frame Procedure
An extension needs to be added to the
application frame procedure. This is the Run Logo Screen extension
template.
The only setting on this template is the name of the MDI Logo
Procedure, as defined above.
Adding Secwin
I understand you are in a hurry to get going, but
choices you make now will become important later on. It is strongly
recommended that you read through the
Program Access Control section before following
these steps. At a bare minimum please read through the section on
Multi-Tenant support.
Checklist
Done it many times before? Here's the checklist;
- Import Secwin7.dctx into
dictionary (\clarion\accessory\libsrc\win\secwin7.dctx)
- Import NetTalkEmail.dctx into
dictionary (\clarion\accessory\libsrc\win\NetTalkEmail.dctx)
- Optionally import NetTalkSMS.dctx into dictionary (\clarion\accessory\libsrc\win\NetTalkSms.dctx)
- Add Global Extensions (StringTheory, Cryptonite or NetTalk,
MyTable, jFiles, Secwin, [desktop] Secwin Auto Populate Screen
Security)
- If Multi-DLL then set Multi-DLL tab for all the above (excluding
NetTalk) as appropriate.
- Import NetTalk procedures (NetTalk Global Extension, Procedures
tab). Email, SMS and Active Directory
- [Desktop Apps] Disable User Access Control on SendEmail
and ActiveDirectory procedures.
- [Desktop Apps] Import Secwin Desktop Procedures (Secwin
Extension, Procedures Tab)
- [Desktop Apps] Set NetTalk procedures in Secwin Extension,
Procedures tab.
- [Web Apps] Import Secwin Web Procedures (Secwin Extension,
Procedures Tab)
- [Web Apps] Set optional Netalk procedures (Secwin Extension,
Procedures Tab, NetTalk Tab)
- Set Secrets (Secwin Extension, Secrets tab)
- SendEmail procedure, update use of GLO:UserEmail
and GLO:UserName
[1]
- [Desktop Apps] Buttons / Menu items to Frame (Logout, Login,
Users, Settings, GlobalSetAccess, Email Settings)
- [Desktop Apps] Add UserLogin Extension to Frame.
- [Desktop Apps] Always Allow Access to Frame. Set Min Level of
Frame to All.
- [Desktop Apps] On Frame, display LoggedIn Name, Level etc in
Status bar
- [Desktop Apps] Set options on Procedures, User Screen Security,
as desired.
- [Web Apps] Add Secwin Extension (FOR WebServer procedure) to
WebServer procedure
- [Web Apps] Add Secwin Extension (FOR WebHandler procedure) to
WebHandler procedure
- [Web Apps] Goto NetTalk Global Extension (Activate NetTalk Web
Server), WebApps tab, Tick on Use Secwin.
- [Web Apps] [Optionally] add <div
class="nt-current-user"><!-- Net:s:CurrentUser
--></div> to xHTML on Header or Footer.
- [Web Apps] Add menu items to Login, Logout, Users, Settings,
GlobalSetAccess
Multi DLL
If you have a multi-dll system (ie multiple apps)
then the instructions for adding Secwin are extended somewhat.
- Import the dictionary changes to the apps as normal
- The Global Extension is added to all the apps in the system.
For all the global extensions (ie for Secwin, StringTheory etc)
the Multi-DLL tab must be set correctly in all apps. This means
setting both checkboxes to ON in the data dll, and the first
checkbox to on in all the other apps. (ESPECIALLY the EXE apps)
- For all the apps, the Secrets on the Secwin global extension,
Secrets Tab, must be set to the same values.
- For all the apps the License details on the Secwin global
extension, License tab , must be set to the same values.
(Hint: For MultiDLL apps you may want to use global variables
here, which can then be set, and updated, in one place. (For ABC,
That's in the Data DLL, Program Setup embed point, Priority 10;
for Legacy that's in the Exe App,
Secwin
Procedures
The Secwin procedures are flexible, so you have
some choices when it comes to their location.
The obvious choice is to simply import them into your data DLL,
exporting them from there. Then they are normal External
Procedures in the other places where you need to call them.
However the procedures don't have to be in the Data DLL - they can
be in a "higher" DLL, with the understanding though that if they are
in a "higher" DLL, then procedures in "lower" DLL's cannot be
protected.
Secwin
Global Set Access Rights Procedure
One way of setting the access rights to specific
users is to use the SecwinGlobalSetAccessRights procedure. In a
Multi-DLL situation this procedure has to be aware of other apps in
the system that contain the Secwin extension. To do this;
- Go to the app that contains this procedure (probably the Data
DLL)
- Go to the SecwinGlobalSetAccessRights procedure, to the
template extensions
- Go to the FOR the SecwinGlobalSetAccessRights Procedure
extension template
- Go to the Apps tab
- Click on the Insert button and add the app
name of the other apps in the system. Just the app name
will do, no extension or quoes are needed.
Appname.Secwin.Inc Files
In a multi-DLL context the template will
generate appname.secwin.inc files for each app. These files are then
included by the Global Set Access Rights procedure, and this is used
to build the tree-list of all the protected procedures and controls
in the application.
Therefore, if you add procedures to an app, or add protected
controls to a window, you will need to compile that app and then
re-compile the app containing the Global Set Access Rights procedure
in order for those new controls and windows to appear in that
procedure.
Adding Secwin to Your
Dictionary
Secwin makes use of a number of tables to store
data in. These tables need to be added to your dictionary, and
possibly modified to match your requirements.
- Open your Dictionary
- Click on the dropdown next to the Import/Export button.
- From the drop down select Import Dictionary from Text
- Navigate to your \clarion\accessory\libsrc\win
folder and select Secwin7.dctx
You can leave the tables as-is, but it's possible you will want to
adjust the tables to match your requirements. The most likely change
at this point is to change the File Driver from TOPSPEED to whatever
database you are using. This would necessitate changing the Full
Path Name and Owner Name properties of
the tables.
The SecwinRights table (which is
only used by the NetTalk Web Server Apps) is set to make use of the
MEMORY driver. If you do not have the
MEMORY driver installed then change this table to use the TOPSPEED
(or any other) driver. (The Owner and Pathname properties for the
table are set so that changing the driver should be
straight-forward).
This may be a good time to consider whether the tables should be
part of your actual database, or kept in a separate database. For a
full discussion on that see Multi-Tenant.
Related to this is the choice between Company-And-User
versus Unique-User.
For a more indepth look at the various tables, see the Dictionary
Reference section of this document.
Blobs
Secwin makes extensive use of Blobs to store
various information in the tables. Information in these blobs are
encrypted, and then base64 encoded. As such they only contain ASCII
data, and don't need to be set as Binary.
For the TopSpeed driver Blobs have always been well supported, and
as long as the field is marked as a BLOB in the dictionary there is
nothing else to do.
For SQL systems, blob support has been a bit patchy, and there are
some "ideals" to strive for. Since the fields are always
base64 encoded, they can be treated as text. This means the BINARY
switch in the database can be OFF, and the backend can use a VARCHAR
as the datatype. If you use a VARCHARBINARY then the BINARY switch
in the Dictionary MUST be turned on.
Note that this applies to the SecwinConverter program as well.
Currently the Dictionary used by the converter is set for the blobs
to be not-binary, if you are going to use VARCHARBINARY on the
backend then you need to change the converter dictionary and
re-compile the converter program (currently requires Clarion 11 or
later.)
NetTalk
If you have NetTalk Desktop then you will
definitely want to make use of the Send Email features. You may also
want to make use of the Send SMS and Active Directory features.
If you have not already done so, this is a good time to import the
suggested NetTalk tables in NettalkEmail.dctx
and NetTalkSMS.dctx.
Adding Global Extensions
The following Global Extensions are required. Add
them to your app. If you have multiple apps then they will be need to
be added to all the apps.
- StringTheory
- Cryptonite (or NetTalk 11 Desktop or later)
- MyTable
- jFiles
- NetTalk (Desktop or later) - this one is optional but
recommended.
- Secwin 7
- Auto Populate User Screen Security (desktop apps only, not
web apps)
After adding the extensions, and BEFORE moving on, set the following
on the Secwin Global Extension;
- Secrets Tab: Program Secret
- Secrets Tab: Table Secret
If this is a Multi-App system, then all the APPs will need to have
Secrets set the same. Secrets can be changed, but only at the
cost of throwing away existing Secwin Tables, so you will want to
settle on suitable values here BEFORE distributing your application.
You can use Global Variables in these template options, but then you
will need to populate the global variables in your code, very early in
the program startup.
NetTalk Support (Desktop and Web)
Whether you are making a desktop app, or a web
app, Secwin can make use of a number of NetTalk features to make the
security system in your application better. If you are making a web
application these steps should be considered as "required". For a
desktop program these steps are optional, but recommended.
NetTalk Procedures
Optional NetTalk Procedures |
|
These procedures are provided by NetTalk, and
can be imported via the NetTalk Global Extension (Build
11.36 or later) on the Procedures Tab. |
SendEmail |
Allows the program to send emails. This is useful not just
for Secwin but for other features in your application. |
SendSMS |
|
ActiveDirectory_UserInGroup |
checks that the user is in an Active
Directory group on the Active Directory server. This
allows an Active Directory Administrator to control overall
user access to the program (for ALL user levels.) Once
inside the program users can have rights, and be in groups,
just like any other Login Type. |
ActiveDirectory_ValidateUser |
Allows the user to login via an Active
Directory Server. |
UpdateEmailSettings |
(Desktop only) Allows the program user to configure the
email settings. |
BrowseEmailLog |
(Desktop only) Allows you to browse the Email Send
Log to see what was sent, and to resend if necessary.
(Although resending Secwin Emails is meaningless, as they
time-expire anyway) |
Adding Email Support (optional)
Support for Email implies that you have a tool
suitable for sending emails in your Clarion toolbox. These
instructions apply to using NetTalk Desktop for emailing, however
any email tool can be used as long as you provide a procedure which
takes a parameter list declared as
(EmailParametersGroup pEmail)
This group structure is declared by Secwin for you if you don't have
NetTalk in the application.
Adding NetTalk Email
- If you don't already have them then import the EmailSettings
and EmailLog tables into
your dictionary.
- Make sure the Global Extension, Activate NetTalk,
has been added to your app.
- If you don't already have one, then import a SendEmail
procedure on the Procedures tab of the NetTalk Global
Extension.
This procedure can be tailored to your requirements, but should
have the prototype;
SendEmail(EmailParametersGroup
pEmail),Long,Proc
- Inside the SendEmail
procedure replace;
GLO:UserEmail with
SecwinCurrentUser.GetEmail() and
GLO:UserName with
SecwinCurrentUser.GetName()
- Disable the User Screen Security in the SendEmail procedure.
Adding SMS Support (optional)
Unlike Email, SMS costs money so your SMS
procedure will depend a lot on the SMS provider that you use. As
with Email you can use any tool you like to construct this
procedure.
Adding NetTalk SMS
- Make sure the Global Extension, Activate NetTalk,
has been added to your app.
- ImImport a SendSMS procedure
from either one of your other applications, or from the NetTalk
Twilio Demo app(Clarion11\Examples\NetTalk\WebClient\Twilio)
. This procedure can be tailored to your requirements, but
should have the prototype;
SendSms(SMSParametersGroup pSms),Long,Proc
- Go to the Global Secwin Extension in the application, to the
Procedures tab, and select the name of the SendSMS
procedure.
- Disable the User Screen Security in the SendSMS procedure.
Adding Active Directory
Support (optional)
To make use of the Active Directory features in
Secwin your application will need to communicate with the Active
Directory Server. This functionality is usually provided by NetTalk
Desktop. As with Email, and SMS, you can use another tool to create
the AD functions in your application if you wish.
The required procedures are;
ActiveDirectory_ValidateUser(LDAPParametersGroupType
pParms),Long
and
ActiveDirectory_UserInGroup(LDAPParametersGroupType
pParms),Long
Adding NetTalk Active Directory Support
- Make sure the Global Extension, Activate NetTalk,
has been added to your app.
- Import the ActiveDirectory_ValidateUser and
ActiveDirectory_UserInGroup procedures from the NetTalk Example
\Clarion11\Examples\NetTalk\NetLDAP\ABC\LdapDemo.app
or
\Clarion11\Examples\NetTalk\NetLDAP\Legacy\LdapDemo.app
- Go to the Global Secwin Extension in the application, to the
Procedures tab, and select the names of the two Active Directory
procedures.
- Disable the User Screen Security Extension Template in the two
Active Directory procedures.
Adding Secwin to Your Desktop
Program
Access Control
Adding Secwin procedures
(required)
Secwin uses a number of procedures to create a
user interface to the user. In order to give you complete control
over the UI of the procedures, so that they seamlessly fit into
the UI of the rest of your program, these are implemented as
procedures in your application.
These procedures can either be imported into the program
directly using one, or more, of the Global Extension,
Procedures Tab,
Import Procedures buttons, or
they can be imported from one of the example applications.
The following procedures may be added to the application. If this
is a multi-app system then do this in the Data DLL.
Access Control Procedures |
Description |
SecwinBrowseGroups |
A browse of all the User Groups. |
SecwinBrowseTenants |
A browse of all the Tenants. |
SecwinBrowseUsers |
A browse of all the Users. |
SecwinGlobalSetAccessRights |
A central screen which lets an Administrator set the
Access Rights for all the users, and all the groups, for
all the procedures in the application. |
SecwinLogin |
The login procedure. |
SecwinLogout |
The logout procedure. |
SecwinSetAccessRights |
A local screen for setting the access rights for all
groups and users, for a single procedure in the
application. |
SecwinUpdateGroups |
A form procedure for updating the details for a group. |
SecwinUpdatePassword |
A form procedure which allows a user to change their
password. |
SecwinUpdateSettings |
A from procedure for updating the policies and settings
for a tenant. |
SecwinUpdateUsers |
A form procedure for updating a user. |
Calling Procedures
From your Frame
TIP: A
Control template exists for adding these procedure calls to a
toolbar on the frame.
You will need to add Menu items, or Toolbar Buttons for the
following procedures;
Access Control
Required Calls To |
Description |
SecwinUpdateSettings |
This allows the end user to set policies for the
program. Until these policies are set, and the Users
added, there is no login required to access the program.
This procedure takes a single string parameter, so from
the Frame the parameter list should be set to ''. |
SecwinBrowseUsers |
In order to add Users this menu item is required. |
Access Control
Optional Calls To |
|
SecwinLogout |
Allows the User to Logout. This also clears the
"remember me" token if the user wants to be forgotten on
the machine. |
SecwinLogin |
Allows another user to login. This does not clear the
"remember me" token, unless the new user selects the
"remember me" checkbox. |
SecwinUpdatePassword |
Allows the user to set a new password for themself. |
SecwinGlobalSetAccessRights |
Allows an Administrator to set the access rights for all
users, and groups, globally. |
SecwinBrowseTenants |
Only necessary in situations where Multi-Tenant
support is desired. |
Licensing
Required Calls To |
|
SecwinLicense |
You'll need this so the user can register the
application. |
Calling the SecwinLogin procedure
In order to access most of your programs
features, your user will need to login. This can be done by
the User_Login extension template
(typically to the Main / Frame procedure), or using the Call
SecWin's Login function code template (also known as
the Call_ChangeLogin code template.)
The UserLoginHere template generates code into the window startup
code.
The Call_ChangeLogin code template allows the user to login, or
for a new user to login.
Adding Screen Security
The Access Rights to each screen are
controlled by the User Screen Security template. This can be
manually added to some subset of windows in the application, or it
can be added to all procedures globally. Adding globally is a lot
less work. To add globally
- Go to the Global Extensions for the APP.
- Highlight the Activate CapeSoft Secwin
item in the extensions list
- Click the Insert button
- Select AutoPopulateUserScreenSecurity
extension from the list (in the Class Secwin10 section).
Adding Licensing
Adding Secwin
Procedures (required)
Secwin uses a number of procedures to create a
user interface to the user. In order to give you complete control
over the UI of the procedures, so that they seamlessly fit into
the UI of the rest of your program, these are implemented as
procedures in your application.
These procedures can be imported into the program directly
by going to the Global Extension, Procedures Tab,
Import
Secwin Licensing Procedures button, or they can be
imported from one of the example applications.
The following procedures may be added to the application. If this
is a multi-app system then do this in the Data DLL.
Licensing Procedure |
|
SecwinLicense |
A registration window where the user can enter their
license details, and get activation codes from the web. |
Checking
program license on startup (or anywhere)
If you are using an online license server
(Secwin Online Server, or your own) then any procedure can be
automatically set to check the license when the procedure is
called. Setting this on the main application frame for example
would mean this test is done when the program starts up.
TIP : The test is only performed once per day - if you want to
repeat the test (while debugging or testing for example) then remove
the [license] checkdate setting from the secwin.ini file.
To set a procedure to do the test;
- Go to the procedure in the application tree
- Go to the User Screen Security extension.
- Go to the Licensing / Expiry tab
- Check on the option Check for new license from web here.
Note that the check is performed asynchronously on a separate
thread. The current window will progress with the current license -
if there is a new license it will be downloaded and silently
applied. However it will only become applicable the following time
the program is run.
Note also that this is a HTTPS connection to a remote server. So
this makes your program a TLS Client. See
https://www.capesoft.com/docs/NetTalk12/NetTalk.htm#DeployingAtlsClientOrServer
if you are unfamiliar with shipping a TLS client program.
Priming License Values
The SecwinLicence procedure is where the user
can alter their details, fetch a new license and so on. Note that
most of the fields on ths window are not set by the user, they are
set as part of the license itself. However fields in the
CustomerGroup (local data) can be primed in your code. Typically you
would only prime these details if they were blank.
Priming is done inside the INIT method, after the Window is Opened,
and after the calls to GetLicense. these calls load the groups,
especially, in this case, the CustomerGroup. You can then prime the
values. For example;
If cg:CompanyName = '' then cg:CompanyName =
'Wacky Wingnuts'.
Adding Number-of-Copies Test
(optional)
One of the licensing features allows you to
limit the number of copies running on a LAN. This is done using
NetTalk, so this feature requires NetTalk Desktop level (or higher.)
NOTE: The copies check takes a few seconds to complete as the
program starts. This is known as the startup window. Multiple
instances of the program starting inside this window can all fail
the test if they exceed the allowed copies. In other words starting
2 instances right after each other can result in both being
disqualified, even if one would typically be allowed. The default
startup window time is 5 seconds, although this can be adjusted if
necessary.
Unlike most of the other licensing features the Limit Copies feature
takes some extra steps in the application to activate.
- Only one of the procedures in the application does this test.
This procedure is most commonly the Frame procedure. Whichever
procedure is used it has to be the top-most window of a thread.
In other words, like the frame, it should remain as the top-most
window in the thread it is on.
- Add a NetTalk Object to the Extension list of this procedure.
The default name for this object is LimitCopies. The base class
must either be NetClient (NOT NetWebClient) or some class that
is derived from NetClient.
- On the Settings tab for this object set the service name to
something (typically something similar to the License Name is
useful), and make sure the Private Service option is OFF.
- In the same procedure, on the Secwin User Screen Security
extension, Licensing / Copies tab, tick on the option to Test to
License Copies here.
- Set the NetClient Object name to the same you specified in
step 2 above. This is typically LimitCopies.
- A second option here is Action. The default action is
"Default" which is described below. And alternative is "Message"
which simply displays a message to the user and closes the
procedure.
The default behavior though is somewhat more complex (under the
hood). It uses the NetTalk object (LimitCopies) to query the
other instances, and get their current user information. This is
presented to the user as a list of logged-in user names, and
also the machine names they are running on. This can help to
identify which users are using the program, and if necessary ask
them to exit.
Adding a Background Logo
Procedure (optional)
Adding License Branding
(optional)
It will encourage pirate users to convert to
paying users if you display program license information to users of
the program, and also on reports that may be distributed to external
people (customers, suppliers and so on). A simple mechanism is
provided to access any of the license or company information that
has been recorded.
The Security Tables are ultimately stored in either
a file on the disk (TPS) or inside a database (SQL). Security of this
data does not just extend to reading, and altering the information in
these tables, but also deleting records in the security database. The
scope of this problem depends a lot on your context.
The first important factor is the data storage. Disk files created by
ISAM drivers (TPS, DAT etc), which are visible to end users, are
more-or-less indefensible. SQL tables are much easier to protect using
the security features of your Server. Web applications may store data in
ISAM files but the disk is not visible to users, so this is not a
concern.
The second important factor are the two kinds of information which need
special protection;
- If you are using Secwin for Licensing, then the records in the SecwinSettings table are important.
- If you are using Secwin for Access Control then the records in
the SecwinSettings AND SecwinUsers
tables are important. Being able to empty the Users table,
but not the Settings table leads to extra complexities.
In conjunction with these two features, the behavior of Secwin when
either these tables, or specific records in the tables are missing,
becomes very important.
If your tables are secure (ie SQL, or WEB) then the program is free to
create users, and settings (tenants) in an unrestricted way. The
database administrator can empty the tables at any point, and they can
be re-created as needed. Obviously if they do drop the table data then
that data (and related data) is lost, so it is not recommended that they
drop data, and it is recommended that these tables be suitably protected
from malicious access.
If the database administrator does empty the SecwinSettings table then
all the license details for the application will be lost (requiring the
administrator to re-license the program.) All the other Secwin tables
will also then contain orphaned, useless, data. Without the original
SecwinSettings record this data will become useless. For this reason
implementing licensing on programs using Topspeed storage is
recommended.
If the database administrator leaves the settings record alone, but
instead deletes all the users, then the program behavior comes into
play, and you have choices.
As always, the records in all these tables are protected by the Program
Secret. So the database administrator does not have the ability to
create new records (or alter existing records) outside your actual
program.
In short there are two "threats" you need to consider here. The degree
to which these threats matter to you determines the program behavior
that you choose.
The Database Administrator
If the tables are limited to only the database administrator, and the
database administrator can be considered to be "non malicious" to the
interests of the customer, then the areas of concern are greatly
reduced.
The End User
If access to the tables themselves are impossible to the end user, then
this is not a concern. However in a traditional desktop program it
should be assumed that the user can delete (or otherwise remove) the
DSSW7.TPS file.
Threat |
Mitigation |
Desktop Program.
ISAM file on disk. |
- The TOPSPEED driver should be used, and all Secwin tables
should be inside the same SuperFile
- The tables should have an OWNER string (same for all the
tables)
- The program should not be able to create a new DSSW7.TPS
file (remove the CREATE attribute from these tables in the
dictionary)
- The DSSW7.TPS file should be supplied by the developer,
and be installed as part of the program install.
- It should contain a preexisting Settings record in the
SecwinSettings table
|
Web Program.
ISAM file on Web server disk. |
- The TOPSPEED driver should be used, and all Secwin tables
should be inside the same SuperFile
- The tables should have an OWNER string (same for all the
tables)
- Access to the server computer should be limited.
- Access to the DSSW7 file on the disk should be
limited.
|
SecwinSettings table is stored in a SQL database. |
- Access to the tables should be limited so that only the
program (and SysAdmin User) have access to the tables.
- The SecwinSettings, SecwinUsers and SecwinGroups tables
should not permit record deletions (at all).
|
This section contains a walk-though of some specific
implementations
Updating an
Attribute after a Successful Login
If you have added a custom attribute to the user
record, then one place where you may want to update that attribute is
when the user successfully logs in. This can be done by embedding in
the LoginComplete method, before the call to the parent method. For
example;
LoginDesktop.LoginComplete PROCEDURE ()
ReturnValue Long
CODE
self.SetAttribute('MyOwnAttribute','Last Login Time: ' &
format(clock(),@t4))
Parent.LoginComplete()
Editing the SecwinUser table
in code
Secwin 6 offered a number of functions for editing
user records. These functions were the only way to access the Users
table, since the table was not in the dictionary. In Secwin 7 though
the users are stored in the SecwinUsers table, and this is a table in
your dictionary. In concept you can access this table just like you
would any table in your dictionary, you can add records, delete
records, edit records and so on. With three catches (There are always
catches, right?)
Aside: Both techniques used by this table are provided by
MyTable, and you can easily do the same in your
own tables.
Catch 1: The row is encrypted.
Some of the fields in the row are encrypted,
some of them are hashed, meaning that the record cannot be tampered
with using TopScan or SQL Enterprise Manager or an equivalent
outside program. Thus, after a record is read from the database it
must be decrypted. Before writing it to the database it has to be
encrypted again. (And if you continue to use the record, it should
be decrypted again after writing.)
Conceptually this looks something like this;
SecUse:UserLogin = 'Englebert'
If Access:SecwinUsers.Fetch(SecUse:LoginKey) = Level:Benign
! decrypt record here
! do any adjustments to fields here
! encrypt record here
Access:SecwinUsers.Update() ! possible decrypt
record again here
End
Fortunately a class (
SecwinUserRecordClass)
has been provided to do all of the hard work for you, reducing the
encrypt and decrypt to single lines of code. You can see an example
of this class in action in the SecwinUpdateUsers form procedure.
You can declare an instance of the class like this;
secUser
SecwinUserRecordClass
The object has to be initialized before it can be used. This is done
with the
Init method in a
simple line of code.
secUser.Init(SecwinUsers,'KSLICO','CIRUXZ','')
The first parameter is the name of the table in the dictionary. The
next are the program, table and customer secrets (as set on your
Secwin global extension.) They will be different in your program to
the example used above. If you are going to be using the secrets
like this in hand-code it might be a good idea to make them Equates
somewhere, then you can use them here, and also on the global
extension.
Once the object has been initialized like this
then you can call
secuser.AfterLoad()
after any read from the table and
secuser.BeforeSave()
before any write to the table. If you want to continue to use the
record after it is written, then use AfterLoad again to decrypt it.
So conceptually the code now looks like;
secUser SecwinUserRecordClass
code
secUser.Init(SecwinUsers,'KSLICO','CIRUXZ','')
SecUse:UserLogin = 'Englebert'
If Access:SecwinUsers.Fetch(SecUse:LoginKey) = Level:Benign
secuser.AfterLoad()
! do any adjustments to fields here
secuser.BeforeSave()
Access:SecwinUsers.Update()
End
Catch 2: Some of the data is stored, as a JSON structure, in BLOB
fields.
Some of the fields in the table are blobs. these
blobs allow unstructured data to be stored about a user in a safe
way. Inside the blobs the data is stored in a JSON document, which
in turn makes it easier to access the individual fields. It is
probably no surprise though that the SecwinUserRecord class makes
interacting with this blob data easy.
Attributes Blob.
This blob is designed to hold all the
attributes for the user. These will vary from program to program,
but basically allow you to store any data about any user. The
SecwinUpdateUsers window can trivially be extended to support more
attributes. And in the program attributes for the current user can
be read using the SecwinCurrentUser.GetAttribute method.
So, editing attributes in code (using the SecwinUserRecordClass,)
only makes sense if you are wanting to write to the current user,
or write to some other user. Editing the attributes can be done in
one of two ways;
1. You can move the attributes into a Clarion GROUP structure.
What this GROUP consists of is up to you. The SecwinUpdateUsers
window contains a locally declared AttributesGroup (and you can
add more fields to this if you like.) The SecwinUserRecordClass
offers two methods, LoadAttributes and SaveAttributes which can
move all the attributes into and out of the group together. This
move is additive, in other words the group does not overwrite the
blob, rather the contents of the group are merged with the
contents of the blob.
2. You can read, and write attributes individually using the
GetAttribute, DeleteAttribute and SetAttribute methods. If you are
doing simple manipulations (like setting a single attribute) then
this approach removes the need to declare a local group.
Catch 3: Passwords are not stored
Passwords are not stored in the table, rather a
hash of the password is stored in the PasswordHash field. Typically
this is not an issue since you would seldom interact with the
password in code. However if you are wanting to specifically set a
password then you would need to do a lot of work to get it properly
hashed. To avoid this the table contains a "dummy" field called
NewPassword. If this field contains something then the call to
BeforeSave will automatically hash the contents of the NewPassword
field, and put the result in the PasswordHash field.
Other Things to Know
- The GUID field contains a random string of 16 characters. If
you are adding users you can use the StringTheory MakeGuid
method to populate this field. For example;
secuse:guid = secglo:st.MakeGuid()
- The SettingsGuid field is a relation to the SecwinSettings
table, Guid field. If you are adding a new user you can use the
SettingsGuid of the current user as a possible value. For
example;
secuse:SettingsGuid =
SecwinCurrentUser.GetSettingsGuid()
- The timestamps are a REAL value, representing thousandths of a
second since Jan 1, 1970. You should leave these as 0 (or as
they are.) If they are needed they will be set by triggers
elsewhere in the program.
- The EncryptionVersion field should not be touched. Before
decryption it will have a value > 0, after decryption it will
be equal to 0. You can read this field if you like, but do not
write to it.
- The RowHash (and all the other hash fields) should not be
touched.
- The UserLevel field should contain one of the following
equates; sw:sysadmin, sw:administrator,
sw:operator, sw:guest,
sw:nolevel
- The UserWorkGroup field is the same as the WorkGroup field in
Secwin 6.
- The Biometrics and Questions blobs are not used yet.
Making a Multi-Tenant Web
Server Program, (maybe with different data folders / databases)
This case study matches the example
\examples\nettalk\web
server\SecwinMultiTenant (88) .
The example is set up to use the Topspeed database, but a SQL database
would be set up in a similar way. The obvious difference is in the way
Full PathName and Owner mean somewhat different things in ISAM and
SQL. So bear that in mind when reading the instructions.
Tip: Setting up a multi-tenant program,
where user share the same database is covered by this as well. Just
use the same connection string for all the tenants.
In a multi-tenant situation, there are three categories of tables;
- Secwin data tables - these are shared across all the tenants.
- System configuration tables - these are shared across all the
tenants - in this example the emailSettings, emailLog, smsSettings
and smsLog tables fall into this category.
- Tenant tables - these are the tables containing the data unique
to the tenant. In this example this is Customers, Products,
Invoices and so on. In most cases each tenant will have their own
database, but they could also share a database.
The first task is to set the dictionary to cover the above
distinctions.
- For SQL you'll have a shared database for the shared tables
(Secwin tables, System tables and so on). So this will have one
owner string (called say SecGlo:SharedOwner).
Shared Topspeed tables will be placed in a directory common to all
tenants. This can be done using variables in the dictionary, or by
simply setting the table names in the dictionary. ISAM
SecwinTables are also encrypted with a password, in this example
that is set to !SecGlo:TableSecret
- In the dictionary set the Tenant tables to use global
THREADED variables for the Full PathName and/or Owner
Name. For ISAM the usual approach is to set the full path name and
possibly the owner, in SQL it's usual to set only the Owner.
- Add variables used in step 1 to Dictionary Globals list. Make
sure the Tenant variables are THREADed.
Next are changes to the Application.
- If all the tenants will be sharing the same security file, then
on the Secwin Global Extension, make sure the Customer Secret is a
fixed value. Although the tenants may use different databases, and
hence have different Customer Secrets, those secrets will apply to
the customer tables NOT the Secwin tables.
- Create a SetFileNames source
procedure to set tablename variables, and tableowner variable(s)
based on sessionvalues. This procedure will take one (optional)
parameter (<NetWebServerWorker p_web>).
Set this procedure to be Declared Globally.
- In the procedure set the variables in the case where;
a) p_Web.GetSessionLoggedIn() = False
b) p_Web.GetSessionLoggedIn() = True
Use session values where necessary, in the example SecwinDataSecret
and SecwinUserPath are used. See Step
6 for where these SessionValues are set.
For example;
folder cstring(255)
code
if omitted(p_web) or p_web.GetSessionLoggedIn() = False
SecGlo:CustomerSecret = 'loggedout'
folder = clip(p_web.site.DataPath)
& 'loggedout'
else
SecGlo:CustomerSecret =
p_web.GetSessionValue('SecwinDataSecret')
folder = clip(p_web.site.DataPath)
& p_web.GetSessionValue('SecwinUserPath')
end
p_web.webserver.CreateFolder(folder)
Glo:ProductsFileName = folder & '\Product.Tps'
! set all the rest of the filename variables here...
- In the WebHandler procedure, Secwin FOR_WebHandler Extension,
Options tab, select the SetFileNames procedure.
- In the WebHandler, SetSessionLoggedIn Method,
after the parent call (and before the call to SetFileNames) set
the session values used in step 4.
For example;
If p_Value
self.SetSessionValue('SecwinDataSecret',SecwinCurrentUser.GetAttribute('DataSecret'))
self.SetSessionValue('SecwinUserPath',SecwinCurrentUser.GetAttribute('DataPath'))
Else
self.SetSessionValue('SecwinDataSecret','loggedout')
self.SetSessionValue('SecwinUserPath','loggedout')
End
- The system will need a SecwinBrowseTenantsWeb
procedure if you don't already have one. This is a NetWebBrowse on
the SecwinSettings tab. This procedure should be limited to access
only by the sw:SysAdmin users on the
Secure tab. Link to the browse from the Security menu.
The form for this browse is the SecwinUpdateSettingsWeb procedure
(which you should already have, and should already be limited to
the level sw:Administrator . If you
have a menu item for Policies - which calls
SecwinUpdateSettingsWeb then keep that - this call to
SecwinBrowseTenants web should be in addition to that.
- The SecwinUpdateSettingsProcedure needs two
more attributes added. These attributes are used to set the
Session values in step 6 above. To create these;
a) Add them into the Local Data Pad, into the the Attributes
Group. In the example they are called DataPath and DataSecret.
Make them both STRING(255)
b) Add them to the form as Entry fields, likely on the
Multi-Tenant tab.
These settings are then moved into the session queue in step 6,
and from there into the File variables in step 4 above.
- The SecwinBrowseUsersWeb browse needs a new column on the
SecSet:Company field. This means relating SecwinSettings to
SecwinUsers (in the Data pad) using the Custom Join SecSet:Guid
= SecUse:SettingsGuid . The new column in the browse
should be set to require security level sw:SysAdmin.
I recommend making this the first column in the browse. See the
example app for an example of this column.
- The SecwinUpdateUsersWeb form needs a new field added to the
form (on the general tab, typically above the User Login field.)
This is the SecUse:SettingsGuid
field. Set the prompt to 'Tenant:' .
On the String tab turn on Lookup Button. On the Lookup Settings
tab set the Procedure to SecwinBrowseTenantsWeb,
From Table to SecwinSettings, OrderBy
and Description fields to SecSet:Company,
and Value Field to SecSet:Guid. Turn
on Display Description instead of Value. Set the Security so the
user must be logged in, and have a level >= sw:SysAdmin.
See the example app for an example of this field.
- Repeat steps 11 and 12 for the SecwinBrowseGroupsWeb and
SecwinUpdateGroupsWeb procedures.
Running the App for the First Time
- Click the Login button. There are no users at this point and
no policies, so you will be logged in as a SysAdmin.
- Go to the Security Menu, Browse Users, and add a User. This is
the SysAdmin who will have complete control over everything.
(Incidentally if you stop here ANY login to the system will
work, because the policies are still "no login required".)
- Go to the Security menu, Browse Tenants, and you should see
the Default tenant there. Edit this policy, at the very least
set the login type to Program Login. On the Multi-Tenant tab set
the data path, and data secret for this tenant.
In the example the data is stored in ISAM files, so the data
path becomes the folder name for the data set. And the Data
Secret is the TPS Encryption password for the TPS files. (The
example doesn't use this, but it could.)
From this point on a valid login will be required to get into the
program.
Adding a Tenant
- Login as the SysAdmin User. Go to the Security menu, to the
Browse Tenants option. Click the Insert button to add a tenant.
- On the Multi-Tenant tab set the Company name for the new
tenant. A unique PIN should be
generated for you, but you can make the PIN more descriptive (to
the company name or whatever) if you like. The PIN is not (much
of) a secret. Knowing the PIN for a different company does not
compromise security.
- Set the Data Path and Data Secret for this tenant.
- On the Login Policies tab Set the login type to (at least)
Program Login.
- On the Users tab add (at least) an Administrator user for the
new tenant.
Using
License Attributes for Client-Generated Information
It is not uncommon for developers to want to
supplement the license information with additional data, retrieved
from the client site. For example, you may choose to gather
information about the client hardware, and make use of that in the
license. This section walks through the process of both gathering, and
then checking, that information.
Note: It's worth pointing out that
binding licenses to hardware will likely result in licenses failing if
hardware changes. This can add substantial load on your support
department. Thus the use of this technique should be used cautiously.
It should also be noted that some "hardware" may only exist virtually,
and making use of hardware (in this era of Virtual Machines, and
Containers) to identify computers is not generally reliable in all
cases.
Create an Attribute
Whether you are setting the attribute yourself,
or setting it via code in the program, the first step is to define
the attribute. You do this in the LicenseManager (Desktop or Web)
program. go to the Products Browse, and edit your product there. On
the Attributes tab add an attribute name. Note that the name of the
attribute is visible to the end user, so you may want to use
something vague rather than a specific hardware name.
Set the Value of the Attribute in the Program when Getting a New
License
There are two ways you (typically) get a
license. One is from the Desktop License Manager program, the other
is from the Web License Manager.
Desktop License Manager
In the desktop program the client information
(Company name, Phone Number etc) is captured manually from the
client and entered into the desktop program. If you wish to capture
additional information, then you should make it available to the
user - ideally on the SecwinLicense screen, or elsewhere in the
program where it is appropriate to display it. Note that you don't
alter the Attributes Queue (in the SecwinLicense procedure) since
that information is part of the license itself.
You can then capture this information into the license (as an
attribute). When the license is generates this value will be
included with the license, and will automatically populate the
attribute on the client side.
Web License Manager
When making use of the Web License Manager,
information can (and is) sent from the client program to the server.
This allows the client to keep their data updated, and also to
receive licenses automatically.
If you are using this approach then your SecwinLicense procedure
will contain a NetWebClient (NetTalk) object, which communicates to
the License Server. A number of values are sent with the request -
these are generated for you by the template. You may choose to send
the information automatically, or you may not - that is up to you.
It's worth remembering that the goal of something like this is to
detect a change, and allow (presumably) a human in your support
department to evaluate the change, and if necessary, update the
license. If you update the information automatically then you negate
the point of the item in the first place. Nevertheless you may
choose to send this information to the Web License Manager.
If you inspect the code, you will for example see,
net.SetValue('machineid',secLicense.GetMachineId())
In the embed immediately before this code you can generate
additional values for the server;
net.SetValue('somethingNew',someValue)
This value could be something the user enters, or it could be
something you compute.
For example, say you have a function to get the hard drive serial
number. Then you might have a line like this;
net.SetValue('HardDrive',GetHardDriveSerialNumber())
This value will be added to the POST request that comes into the Web
License Manager, and you can use it there. You might use it to flag
a problem to support staff, or you may use it to update the
attribute for the license. What you do with it on the server side is
up to you.
Checking the License and Hardware still Match
Of course there's no point collecting the data if you do not make
use of it to validate the license in some way. You can do this by
embedding code into the secAccess.CheckLicense method in a
procedure. Add your attribute code AFTER the parent call. if you are
satisfied with the attribute value, set the return value to sw:ok,
otherwise set it to sw:notok.
For example;
ReturnValue = PARENT.CheckLicense (pPostEvent)
if ReturnValue = sw:ok
! do additional checks here
if SecwinCurrentUser.GetAttribute('HardDrive') <>
GetHardDriveSerialNumber()
ReturnValue = sw:notok
end
end
(Hint: The CurrentUser object inherits Attributes from the User,
from the Security Policies, as well as the License.)
All the tables used by Secwin are declared in your
dictionary. Secwin is designed so that you can extend these tables
without inhibiting the work that Secwin does. They are also designed to
allow you to store extra information in their fields. This section in
the documentation explores the technical workings of these tables.
Note that while fields can be added to the record structures, removal of
existing fields is not allowed. Existing fields should not be renamed
(but can have different External names if desired.) Existing field types
should be changed only with caution and understanding of the
implications.
New fields, and new keys on these fields may be added, however
additional keys should not have the UNIQUE attribute.
Database
Secwin supports
multi-tenant
systems. This means that data can be segmented into different
databases. When a user logs in they are then directed to a specific
database. If you make use of this feature it is probably desirable to
store your Secwin tables in a different database to your actual data
tables. Take this into account when planning the
Owner Name
and
Full Path Name properties
If the Secwin tables are stored in a separate database then this would
allow a user to login, and only once they have logged in, for other
table connection parameters to be set.
If the SecwinSettings table is deleted then the data in the
SecwinUsers and SecwinGroups tables become lost. In other words users,
and groups, are related to the parent Settings record.
For various reasons (auditing, data-distribution etc) Users and Group
records are not "deleted" when the delete button is used. Instead the
DeletedTimeStamp field is set. For this reason an Administrator or
SysAdmin user can undelete records by going to the respective forms,
and clicking on the Undelete button.
File Drivers
The tables are designed to use a minimal amount of
field types, and should work with any File Driver that supports these
types. The types used are
STRING,
REAL [2],
LONG,
DATE
[1] and
BLOB [3].
The timestamp fields have external names. These may need to be
tweaked.
[4]
When changing the file driver be sure to adjust the
Owner
Name and
Full Path Name properties in the
table properties to a value suitable for the driver.
Note 1
The
DATE type can be replaced by a
LONG if your chosen backend does not support
DATE.
Note 2
If using PostgreSQL then use
BIGINT on
the backend where there is a
REAL declared
in the dictionary.
Blobs should be TEXT on the backend (because the blobs are all ASCII
not BINARY).
Note 3
If Using MsSQL then use VARCHAR(MAX) for the BLOB fields (not IMAGE)
if the BINARY switch in the dictionary is OFF. If the Binary switch is
on (it should not need to be on) then use VARBINARY(MAX). If
using FM3 to create the table make use of the ForceSQLDataType option
on the blob fields (
https://www.capesoft.com/docs/fm3/fm3.htm#duoForceSQLDataType)
Note 4
If using Firebird then External Name fields must be in Uppercase. ie
TS, STS and DTS.
Unique Row Identifiers
All Secwin tables use a client-side string field
called GUID as the unique row
identifier. This value is used when encrypting values in the row, so
data cannot be copied (externally) from one row to another. Changing
the field value is not allowed - doing so will render the row invalid.
Record Timestamps
Three timestamp fields are in the tables. TimeStamp,
ServerTimeStamp and DeletedTimeStamp allow
support for undelete and distributed data should that become
necessary. These fields are not necessarily populated at this time.
Use of these fields by your own code is not recommended, however
filtering data based on DeletedTimeStamp > 0
is recommended.
Encryption
Because most of the data in most of the tables is
encrypted, most interactions with these tables will be done via the
supplied classes, and not directly through the Clarion drivers. That
said you can still use templates, and simple code, on the table
records, and on the unencrypted fields. For example it's still
possible to list all the Secwin Groups simply by browsing the
SecwinGroups
table.
Fields can be written to, and (if encrypted) read from only by using
the supplied class. Writing to fields, without using the supplied
class will likely result in the row becoming unusable.
Each table contains a field called
EncryptionVersion. This field is for internal use only. Do
not change the contents of this field. If you do so the data in the
record will not decrypt correct, and may lead to the data being lost.
The
rowhash field contains an encrypted
hash of the plain-text fields. This prevents tampering of these fields
outside the program.
The encryption algorithm used by the tables is AES256. Hashes are
SHA256. These values may be updated from time to time - conversion to
new values will be automatic, and invisible.
The underlying field encryption is provided by MyTable. If you wish to
understand the encryption level in more detail, refer to the
MyTable documentation.
SecwinSettings Table
The
SecwinSettings table
is the heart of the system, and the other tables are related to this.
This table can contain multiple records, thus acting as the root table
for multi-tenant systems.
Records, and values in this table can be accessed using an object of
type
SecwinSettingsRecordClass.
In addition to the primary key field (
Guid)
another field,
Company, is also a unique
value in the table. This field serves to identify each record to
humans. The table should contain at one record, with the DefaultRecord
option set. This row should not be renamed.
Field |
Encrypted |
Hashed |
Description |
Default Record |
No |
RowHash |
True(1) or false(0). Set to true if this is the default
record. One (and only one) row in the table should have this
set. In situations where the company is unknown, but settings
are required by the code, this record is used. |
Company |
No |
RowHash |
Contains a unique human-readable name for the record. This
field is only used in multi-tenant situations. |
PIN |
No |
RowHash |
A short code, that a user can use to identify the company
being logged into. Used in situations where it's not desired
to display a simple list of companies. This code must be
unique. |
Settings |
Yes |
SettingsHash |
This blob, and associated hash field, contain the Secwin
settings for this company. Editing these values is usually
done via the SecwinSettings procedure (desktop programs) or
the SecwinSettingsWeb procedure (web programs). |
License |
Yes |
LicenseHash |
This blob, and associated hash field, contain the Secwin
license for this company. Editing these values is usually done
via the SecwinLicense procedure (desktop programs) or the
SecwinLicenseWeb procedure (web programs). |
Attributes |
Yes |
AttributesHash |
This blob, and associated hash field, contain the
programmer-defined settings for this company. This allows the
programmer to add any additional (secure) information that is
needed to this table. To read, or set, attributes see the
Attribute Methods. |
SecwinGroups Table
The
SecwinGroups table
contains a list of user groups for the system.
Records, and values in this table can be accessed using an object of
type
SecwinGroupRecordClass.
Field |
Encrypted |
Hashed |
Description |
SettingsGuid |
No |
RowHash |
Links this group to a specific SecwinSettings
record. This allows group lists to be filtered based on the
company settings being used. |
Name |
No |
RowHash |
The name of the group |
Rights |
Yes |
RightsHash |
Contains a list of the user rights for this group. To
determine if a user has a specific right use the GetRight
method. |
Attributes |
Yes |
AttributesHash |
A place for any additional attributes of the group to be
placed. To read, or set, attributes see the Attribute
Methods. |
SecwinUsers Table
The
SecwinUsers table
contains a list of users for the system.
Records, and values in this table can be accessed using an object of
type
SecwinUserRecordClass.
Field |
Encrypted |
Hashed |
Description |
SettingsGuid |
No |
RowHash |
Links this user to a specific SecwinSettings
record. This will control items such as login approach,
password policies, and so on. |
UserLogin |
No |
RowHash |
An identification field for the user, used as part of the
login process. This field is unique. |
UserName |
No |
RowHash |
A human-readable name associated with the login. This field
is not unique. It is used for display purposes only. |
UserLevel |
No |
RowHash |
The user's Level. |
UserWorkgroup |
No |
RowHash |
The user's Workgroup. |
PasswordHash |
No |
|
A salted-hash of the user's current password. |
NewPassword |
No |
|
This field is used as a place-holder. It will not be written
to the database. |
Email |
Yes |
|
The user's email address. Used for Second Factor, Password
Resets and so on. |
EmailValid |
No |
|
Set to a value if the email address has been validated. 0
otherwise. |
Phone |
Yes |
|
The users mobile phone number. Used for Second Factor,
Password Resets and so on. |
PhoneValid |
No |
|
Set to a value if the phone number has been validated. 0
otherwise. |
Rights |
Yes |
RightsHash |
Contains a list of the user rights for this user. To
determine if a user has a specific right use the GetRight
method. |
Groups |
Yes |
GroupsHash |
Contains a list of the groups that the user is in. To
determine if the user is in a group use the InGroup method. |
Biometrics |
Yes |
BiometricsHash |
Not currently used. |
Questions |
Yes |
QuestionsHash |
Not currently used. |
Attributes |
Yes |
AttributesHash |
A place for any additional attributes of the user to be
placed. To read, or set, attributes see the Attribute
Methods. |
SecwinTokens Table
When the login
Remember Me
feature is on, and the user chooses to remember the login on a
specific machine, then an
Access Token is issued to the
user, and stored in this table. For desktop programs, tokens are
bound to a specific computer.
Adding fields to this table is not necessary, nor recommended. If you
wish to delete a token then either set the
DeletedTimeStamp
field, or set the
TokenExpiryDate to
earlier-than-today. Deleting the actual record is not recommended (for
distributed-data reasons.)
Records, and values in this table can be accessed using an object of
type
SecwinTokenRecordClass.
Field |
Encrypted |
Hashed |
Description |
UserGuid |
no |
RowHash |
The guid of the user this token belongs to. |
SettingsGuid |
no |
RowHash |
The guid for the settings this token belongs to. |
TokenVersion |
no |
RowHash |
Used internally to describe the algorithm used to generate
this token. |
TokenExpiryDate |
no |
RowHash |
The date when the token will expire. Changing this value
will invalidate the token. |
MachineId |
no |
RowHash |
The ID of the machine where the token can be used. Changing
this value will invalidate the token. |
Token |
yes |
|
The login token. |
SecwinLoginFactor Table
This table is used internally when doing
Second
Factor authentication. The records in it are short-lived .
Adding fields to this table is not necessary, nor recommended.
Records, and values in this table can be accessed using an object of
type
Secwin2FactorRecordClass.