Generic Provider Connection

Introduction


Generic Provider authentication connection is a plugin which allows clients to create their own input view, error view, as well as the handler to validate credentials. Safewhere*Identify will 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 configuration settings offered by this Authentication Connection type are:

  • Second factor authentication connection: If you want this WS-Federation Authentication Connection to have a second factor, you must choose this second factor among the different Authentication Connections that have been set up in the system. This includes 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 Safewhere*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 logging in without also 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. Safewhere*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.
  • Federated session lifetime (minutes): Specifies how long a federated session, which is established when a user uses this authentication connection to log in, will last.
  • Enabled for mobile use: Should be ticked if you also want to allow mobile users to authenticate using this connection.
  • IP-based filter for Home Realm Discovery: specifies IP addresses of RPs for the filter.An IP address consists of 4 sections of numbers between 1 and 255. The 4 sections of numbers are seperated by a dot. An IP range consists of two IP addresses separated by a dash. You can enter multiple IP addresses or IP ranges by seperating them with semicolons. E.g.: 192.168.1.1;192.168.1.2;192.168.0.0-192.168.1.255.
  • Credentials validator: A dropdown list of external DLLs. Please choose the one that should be used to validate credentials. Safewhere*Identify will then send credentials collected from the “Login View” as well as “Key/value pairs” (as specified in the the “Key/value pairs to pass the the external provider” setting) to this DLL.
  • Login view name: Name of the view that Safewhere*Identify will show to the user to collect credentials.
  • Error view name: Name of the view that Safewhere*Identify will show to the user when an error/exception happens or when the max allowed attempts are exceeded.
  • Error view URL: Similar to the above, but this time it is a URL. Either Error view or Error view URL must have value. If both have values, Error view takes precedence.
  • Key/value pairs to pass to the external provider: sets of static key/value pairs which Safewhere*Identify will pass to the external provider every time it calls the method to validate a user’s credentials.Multiple pairs can be added.

There are a whole range of fields that will help you set up a two factor authentication process. Below each of these are explained.

  • 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 logging in without also 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. Safewhere*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.

Case Example for using Generic Provider


DummyGenericProvider (as can be downloaded from https://safewhere.zendesk.com/attachments/token/tngvxqtgbdzumnf/?name=ExternalSamples.zip) is a demo generic provider for external authentication. It validates a user’s credentials against a database. First of all, we need to set up database for it:

  • Create a database named DummyGenericProvider
  • Execute the below script to create users for testing

It is assumed that Safewhere*Identify[glossary] was installed in the default folder and that the 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 resources in \App_GlobalResources to C:\Program Files\Safewhere\Identify\Tenants\identify1\runtime\App_GlobalResources

Use the Identify*Admin connections page to create a new Generic Provider Authentication Connection with the following settings:

  • Credentials validator: select the ExternalSamples from the dropdown list, named External.Samples.DummyGenericValidatorUsernamePassword, Safewhere.External.Samples, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
  • Login view name:set value to DummyGenericUsernamePasswordLogin
  • Error view name: set value to DummyGenericUsernamePasswordError
  • Error view url: leave it empty or set value to 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)

Clients are also able to allow user to return to Selector page to select another authentication connection when being at login page by adding section @Html.Partial(“ReturnToLoginSelectorLink”) to their login view.

Generic Provider Login page using External Samples will look as follows:

Generic Connection 1

Technical information for implementing external handler


The following chapter explains the technical requirements for implementing the external handlers.

General requirements

  • Implementing a custom generic provider for external authentication requires the following steps:
    • Implement the IGenericCredentialsProvider.
    • Create a login view and an error view.
    • Add text resources if needed.

The interfaces

The result code enumeration

  • Define all the possible results of a login.
  • A result can contain more than one state, for example it can be UserDisabled | UserLocked.
  • The Success state cannot be combined with any other states.

The 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 [glossary]Safewhere*Identify’s event log.

The result model class

  • The result object contains three properties:
    • UserIdentity: of all the key/value pairs which Safewhere*Identify passes to an external provider.There should always be one which is the user’s identity. It can – for example – be a username, email or CPR. The external provider is responsible for setting that value to the UserIdentity property so that Safewhere*Identify can use it to build the identity bearing claim.
    • ResultCode: an instance of the result code enumeration mentioned above.
    • ExternalErrorMessages: a list of error messages which the external implementation wants to pass to Safewhere*Identify.

View’s model

  • The object containing the data that Safewhere*Identify wants to pass to the login view.
  • The idea here is that Safewhere*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.

Processing flow

The processing flow is:

  1. A generic provider connection is selected.
  2. A custom login view is shown to a user.
  3. The user enters all the required fields and submits.
  4. Safewhere*Identify collects all the entered values whose keys are names of the controls, combines them with all the static key/value pairs and passes them to the configured external handler.
  5. The external handler returns a result object to Safewhere*Identify.
  6. Safewhere*Identify checks the result object:
    1. If the result code is Success, it will authenticates the user.
    2. If the result code is a combination of Success and the code “invalid state” it will redirect to the error view.
    3. If the result code is not Success:
      1. For each invalid state it contains, look up the corresponding error message and add them to the ErrorMessages list.
      2. Copy the ExternalErrorMessages list from the result object to the model object.
  • Initialize all the other properties of the model object.
  1. Show the login view.
  2. The login view will decide what and how error messages will be shown to the user.

Localization

  • The plugin will follow the standard localization design which other plugins use.
  • The external DLL will need its own text resources. These text resources will also be used for the custom views.
  • Safewhere*Identify’s text resource framework is built so that the default language is changeable. In addition, it is also possible to override default texts with some user-specific ones. The point is that these features didn’t come for free. In other words, a piece of magic code is required. Meanwhile, since we assume that external DLLs are meant only for a specific organization who already knows what default language itwants and also controls the text resource files completely, it mean we for external DLLs have chosen to use a simpler text resource model:
    • Add some resource files to the project.
    • Text resource 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 the 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.

Event ids

  • Event ids which are used by Safewhere*Identify for the new plugin:
    • 4810: GenericProviderCommonError.
    • 4811: GenericProviderCouldNotLoadExternalProviderError.
    • 4812: GenericProviderUnhandledExceptionFromExternalProviderError.
    • 4813: GenericProviderNameClaimIsEmptyOrCanNotParsed.
  • External providersare encouraged to use event ids between 4830 and 4899 for their errors.

 

Was this helpful ?Good Somewhat Bad