Safewhere*identify
User guideline
Generic Provider Plugin
1.Generic Provider Authentication Connection
Generic Provider authentication connection is a new plugin which allows clients to create their own input view, error view, and the handler to validate credentials.Identify will just send a set of key-value pairs collected from the views as well as some other connection settings to the handler, receive the result and process it accordingly.
The specific configuration for Generic Provider Authentication connection are:
- Maximum number of allowed authentication attempts before redirecting to an error page: define how many retries before redirecting user to Error View/Error View URL. This setting is not in use right now.
- Credentials validator: a dropdown list of the handlers which implement our interface to validate a credentials Identify passes to. Please note that dlls which contain validator implementation must be placed in the Runtime\Bin folder.
- Allow auto login without executing generic credentials validation: an option to allow (or disallow) auto-login without executing generic credentials validation.
- Login view name: name of the view which Identify will show to the user to collect credentials.
- Error view name: name of the view which Identify will show to the user when an error/exception happens, or when the max attempts exceeded.
- Error view url: similar to the above, but this time it is an url. Either Error view or Error view url must have value. If both have values, Error view is taken precedence.
- Key/value pairs to pass to the external provider: a set of static key/value pairs which Identify will pass to the external provider every time it calls the method to validate user’s credentials. It allows user to add new key/value, edit or remove them from the list.
The Generic Provider Authentication connection even include a whole range of fields that will help you set up a two factor authentication process. Each of these fields are explained below.
- Second factor authentication connection:If you want this Generic ProviderAuthentication Connection to use a second factor, you must choose this second factor among the different Authentication Connections that have been set up in the system. This also encompass all the One Time Password Connections.
- Two factor identities condition:When using two different Authentication Connections together (which is basically what you are doing when setting up two-factor authentication), then the two may try to identify the incoming user based on two different identity bearing claims. This dropdown is activated when a user has chosen, that the connection will have a second factor. Options in the dropdown are:
- Use the first identity: System will disregard the “Identity bearing claim” value of the second factor and just focus on identifying the user based on the first one.
- Two identities must be the same: The user will not be allowed to log in unless the identity of the user for the first factor is identical to that of the second factor.
- Use as second factor only: If you just want the Authentication Connection to be used as the second factor for other connections and not have it offered to users as a primary connection option, then this checkbox must be set to true.
- Ignored by second factor roles claim type:If there are subsets of users that you will allow to perform logins without having to authenticate using the second factor, you must specify whom these users are based on a rule. The rule states that any users who have a specific value for a specific claim type, will be excluded from the second factor. This setting specifies which claim will be tested. The setting below (“Ignored by second factor roles”) states which roles will be ignored. Identify will search in both the received assertion and local store.
- Ignored by second factor roles:The list of roles (claims type values) that a user must have at least one of in order to avoid having to authenticate via the second factor. You should use colon as seperator for these roles.
- Ignore roles check: If you do not want to let anyone log in without also authenticating via the second factor (thus in effect ignoring the two parameters above), you should set this checkbox to true.
There is also option to enable/disable support for specialized web pages for mobile use.
- Enabled for mobile use
2.Demonstration: A custom generic provider
DummyGenericProvider is a demo generic provider for external authentication. It validates user’s credentials against a database. First of all, we need to set up database for it:
-Create a database named DummyGenericProvider
-Execute below script to create users for testing
USEDummyGenericProvider
CREATETABLE[dbo].[DummyUser](
[UserName][nchar](10)NOTNULL,
[Password][nchar](10)NOTNULL,
[IsLocked][bit]NOTNULL,
[IsDisabled][bit]NOTNULL,
CONSTRAINT[PK_DummyUser]PRIMARYKEYCLUSTERED
(
[UserName]ASC
))
-- normal user
INSERTINTO[dbo].[DummyUser]([UserName],[Password],[IsLocked],[IsDisabled])
VALUES ('user','dummy', 0, 0);
-- disabled user
INSERTINTO[dbo].[DummyUser]([UserName],[Password],[IsLocked],[IsDisabled])
VALUES ('duser','dummy', 0, 1);
-- locked user
INSERTINTO[dbo].[DummyUser]([UserName],[Password],[IsLocked],[IsDisabled])
VALUES ('luser','dummy', 1, 0);
It is assumed that Identify was installed in default folder and tenant name is identify1.
-Copy all handler dlls in\bin to C:\Program Files\Safewhere\Identify\Tenants\identify1\runtime\bin
-Copy all views in \Views to C:\Program Files\Safewhere\Identify\Tenants\identify1\runtime\PlugIn
-Copy all text resoures in\App_GlobalResources to C:\Program Files\Safewhere\Identify\Tenants\identify1\runtime\App_GlobalResources
Using Identify*Admin to create a new Generic Provider Authentication Connection with some settings:
-Credentials validator: select the ExternalSamples from the dropdown list, named “Safewhere.External.Samples.DummyGenericValidatorUsernamePassword, Safewhere.External.Samples, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”
-Login view name:set value = DummyGenericUsernamePasswordLogin
-Error view name: set value = DummyGenericUsernamePasswordError
-Error view url: leave it empty or set value = redirected URL if Error view name is empty.
-Add key/value to allow ExternalSamples handler to connect to user’s table created above:
- Key = “ConnectionString” (case sensitive)
- Value = “Server=localhost; Database=DummyGenericProvider; Trusted_Connection=True; MultipleActiveResultSets=true;” (If using local SQL Server, use localhost, otherwise change to SQL Server Name)
Generic Provider Login page using ExternalSamples:
3.Technical information for implementing external handler:
3.1General requirement
-
-Implementing a custom generic provider for external authentication requires the following steps:
- Implement the IGenericCredentialsProvider.
- Create a login view and an error view.
oAdd text resources if needed.
3.2The interfaces
[Flags]
publicenumCredentialsValidationResultCode
{
None = 0,
Success = 1 < 0,
UserDisabled = 1 < 1,
UserLocked = 1 < 2,
UnknownUserName = 1 < 3,
IncorrectPassword = 1 < 4,
UnknownError = 1 < 5,
MissingRequiredFields = 1 < 6,
// Do we need a login failed flag? Or any value other than Success indicates a failed attempt.
}
publicinterfaceIGenericCredentialsValidator
{
///<summary>
/// Validates a user and returns validation result
///</summary>
///<param name="input">Including configuration and user input</param>
///<param name="logWriter"</param>
///<returns</returns>
CredentialsValidationResult Validate(IDictionarystring, string> input, IIdentifyLogWriter logWriter);
}
publicclassCredentialsValidationResult
{
public CredentialsValidationResult()
{
ExternalErrorMessages = newListstring>();
}
publicstringUserIdentity { get; set; }
publicCredentialsValidationResultCode ResultCode { get; set; }
publicIListstring> ExternalErrorMessages { get; privateset; }
}
3.3The result code enum
-Define all the possible results of a login.
-A result can contain more than one states, for example it can be UserDisabled | UserLocked.
-The Success state cannot be combined with any other states.
3.4The validator interface
-The interface has a method called Validate which receives all the necessary parameters and returns a result object.
-Parameters:
- input: is a dictionary of key/value pairs. It contains all the static key/value settings of a connection and all the input values collected from the login view. Please note that the keys are case-insensitive.
- logWriter: a logging object which the external implementation can use to log to Identify’s event log.
3.5The result model class
-The result object contains three properties:
- UserIdentity: of all the key/value pairs which Identify passes to an external provider, there should always be one which is the user’s identity. For example, it can be either a username, email or CPR. The external provider is responsible for setting that value to the UserIdentity property so that Identify can use it to build identity bearing claim.
- ResultCode: an instance of the result code enum mentioned above.
- ExternalErrorMessages: a list of error messages which the external implementation wants to pass to Identify.
3.6View’s model
-Aka the object which contains data which Identify wants to pass to the login view.
-The idea here is that Identify will try to pass as much information as possible to the custom login view. The view itself will decide what and how the error messages will be shown.
publicclassGenericProviderAuthenticationModel
{
public GenericProviderAuthenticationModel()
{
ErrorMessages = newListstring>();
ExternalErrorMessages = newListstring>();
}
publicbool UserDisabled { get; set; }
publicbool UserLocked { get; set; }
publicbool UnknownUserName { get; set; }
publicbool IncorrectPasword { get; set; }
publicbool UnknownError { get; set; }
publicbool MissingRequiredFields { get; set; }
publicIListstring> ErrorMessages { get; privateset; }
publicIListstring> ExternalErrorMessages { get; privateset; }
}
3.7Processing flow
The processing flow is:
- A generic provider connection is selected.
- A custom login view is shown to a user.
- The user enters all the required fields and submits.
- Identify collects all the entered values whose keys are names of the controls, combines them with all the static key/value pairs and passes to the configured external handler.
- The external handler returns a result object to Identify.
- Identify checks the result object:
- If the result code is Success: authenticates the user.
- If the result code is a combination of Success and another code: invalid state, redirect to the error view.
- If the result code is not Success:
- For each invalid state it contains, look up the corresponding error message and put to the ErrorMessages list.
- Copy the ExternalErrorMessages list from the result object to the model object.
- Initialize all the other properties of the model object.
- Show the login view.
- The login view will decide what and how error messages will be shown to the user.
3.8Localization
-The plugin will follow the standard localization design which other plugins use.
-The external will need its own text resources. These text resources will also be used for the custom views.
-Identify’s text resources framework is built so that the default language is changeable. In addition, it is also possible to override default texts with some company-specific ones. The point is that these features didn’t come for free. In other words, a piece of magic code is required. Meanwhile, an external dll is used for a specific client who knows what default language itwant, and it controls the text resources files totally. It means that it can use a simpler text resources model:
- Add some resource files to the project.
- Text resources files' properties must be set correctly:
- Build Action: None
- Copy to output: Do not copy
- Custom tool: GlobalResourceProxyGenerator
- Upon deploying the dll, also copy the resource files to appropriate folders.
-It is recommended that when logging messages to event log, the external dll should hard code messages in the language of its choice instead of reading from text resources. Otherwise, messages may be logged in the user’s preferred language.
3.9Event ids
-Event ids which are used by Identify for the new plugin:
- 4710: GenericProviderCommonError.
- 4711: GenericProviderCouldNotLoadExternalProviderError.
- 4712: GenericProviderUnhandledExceptionFromExternalProviderError.
Each external provider is encouraged to pick some event ids between 4730 and 4799 to use.
Safewhere A/SSafewhere*identify -Version 3.4Page1