Reset Password using SMS and OTP

This section will show how to use one-time password (OTP) distributed with an SMS as a method to let users prove their identity before resetting their password.

Requirements : 

  • A PhenixID Message Gateway account or an other way to distribute One-time Password via SMS.
  • LDAP must be configured, note the ID of the connection it will be used in later steps.
    (in config UI, SCENARIOS -> CONNECTIONS -> LDAP)

Do the following steps in the ADVANCED  tab in the Configuration GUI

 

Step 1 - Authentication - HTTP

Add the following configuration to “Authentication - HTTP” 

{
	"alias": "changepwdsms",
	"name": "Registration",
	"configuration": {
		"stages": [
			{
				"pipeid": "changepwdsms-start",
				"template": "changepwd/changepwd-common-otp-start",
				"allowLanguageChange": "true",
				"sessionValues": [
					"username"
				],
				"templateVariables": {
					"cancel_href": "/ppss/authenticate/logout/?nextTarget=/ppss/authenticate/changepwdchoice/"
				},
				"enableHoneypot": "true",
				"translation": [
					"common.messages.human",
					{
						"key": "header",
						"mapKeyTo": "ppsspassms.messages.header"
					},
					{
						"key": "subheader",
						"mapKeyTo": "ppsspassms.messages.subheader"
					},
					{
						"key": "helptext",
						"mapKeyTo": "ppsspas.common.helptext.username"
					},
					{
						"key": "paragraph",
						"mapKeyTo": "ppsspassms.messages.paragraph.start"
					},
					{
						"key": "label.username",
						"mapKeyTo": "ppsspas.common.label.username"
					},
					{
						"key": "label.newpassword",
						"mapKeyTo": "ppsspas.common.label.newpassword"
					},
					{
						"key": "label.otpcode",
						"mapKeyTo": "ppsspas.common.label.otpcode"
					},
					{
						"key": "button.requestotp",
						"mapKeyTo": "ppsspas.common.button.requestotp"
					},
					{
						"key": "button.verifyotp",
						"mapKeyTo": "ppsspas.common.button.verifyotp"
					},
					{
						"key": "button.continue",
						"mapKeyTo": "ppsspas.common.button.continue"
					},
					{
						"key": "title",
						"mapKeyTo": "ppsspas.common.title"
					},
					{
						"key": "error.user",
						"mapKeyTo": "ppsspas.common.error.user"
					},
					{
						"key": "error.otp",
						"mapKeyTo": "ppsspas.common.error.otp"
					},
					{
						"key": "error.lockout",
						"mapKeyTo": "ppsspas.common.error.lockout"
					},
					{
						"key": "error.ldappwd",
						"mapKeyTo": "ppsspas.common.error.ldappwd"
					}
				]
			},
			{
				"pipeid": "changepwdsms-verify",
				"template": "changepwd/changepwd-common-otp-start",
				"sessionValues": [
					"username",
					"sentotp"
				],
				"templateVariables": {
					"cancel_href": "/ppss/authenticate/logout/?nextTarget=/ppss/authenticate/changepwdchoice/"
				},
				"enableHoneypot": "true",
				"translation": [
					"common.messages.human",
					{
						"key": "header",
						"mapKeyTo": "ppsspassms.messages.header"
					},
					{
						"key": "subheader",
						"mapKeyTo": "ppsspassms.messages.subheader"
					},
					{
						"key": "helptext",
						"mapKeyTo": "ppsspas.common.helptext.otp"
					},
					{
						"key": "paragraph",
						"mapKeyTo": "ppsspassms.messages.paragraph.sentotp"
					},
					{
						"key": "label.username",
						"mapKeyTo": "ppsspas.common.label.username"
					},
					{
						"key": "label.newpassword",
						"mapKeyTo": "ppsspas.common.label.newpassword"
					},
					{
						"key": "label.otpcode",
						"mapKeyTo": "ppsspas.common.label.otpcode"
					},
					{
						"key": "button.requestotp",
						"mapKeyTo": "ppsspas.common.button.requestotp"
					},
					{
						"key": "button.verifyotp",
						"mapKeyTo": "ppsspas.common.button.verifyotp"
					},
					{
						"key": "button.continue",
						"mapKeyTo": "ppsspas.common.button.continue"
					},
					{
						"key": "title",
						"mapKeyTo": "ppsspas.common.title"
					},
					{
						"key": "error.user",
						"mapKeyTo": "ppsspas.common.error.user"
					},
					{
						"key": "error.otp",
						"mapKeyTo": "ppsspas.common.error.otp"
					},
					{
						"key": "error.lockout",
						"mapKeyTo": "ppsspas.common.error.lockout"
					},
					{
						"key": "error.ldappwd",
						"mapKeyTo": "ppsspas.common.error.ldappwd"
					}
				]
			},
			{
				"pipeid": "changepwdsms-setpwd",
				"template": "changepwd/changepwd-common-otp-start",
				"sessionValues": [
					"username",
					"otpverified",
					"sentotp"
				],
				"enableHoneypot": "true",
				"templateVariables": {
					"password_validity": {
						"contains_lowercase": "true",
						"contains_uppercase": "true",
						"contains_special": "true",
						"contains_number": "true",
						"password_length": "8"
					},
					"cancel_href": "/ppss/authenticate/logout/?nextTarget=/ppss/authenticate/changepwdchoice/"
				},
				"translation": [
					"common.messages.human",
					{
						"key": "header",
						"mapKeyTo": "ppsspassms.messages.header"
					},
					{
						"key": "subheader",
						"mapKeyTo": "ppsspassms.messages.subheader"
					},
					{
						"key": "helptext.username",
						"mapKeyTo": "ppsspas.common.helptext.username"
					},
					{
						"key": "helptext.otp",
						"mapKeyTo": "ppsspas.common.helptext.otp"
					},
					{
						"key": "paragraph",
						"mapKeyTo": "ppsspassms.messages.paragraph"
					},
					{
						"key": "validation.header",
						"mapKeyTo": "ppsspas.common.validation.header"
					},
					{
						"key": "validation.lowercase",
						"mapKeyTo": "ppsspas.common.validation.lowercase"
					},
					{
						"key": "validation.uppercase",
						"mapKeyTo": "ppsspas.common.validation.uppercase"
					},
					{
						"key": "validation.special",
						"mapKeyTo": "ppsspas.common.validation.special"
					},
					{
						"key": "validation.number",
						"mapKeyTo": "ppsspas.common.validation.number"
					},
					{
						"key": "validation.length",
						"mapKeyTo": "ppsspas.common.validation.length"
					},
					{
						"key": "label.username",
						"mapKeyTo": "ppsspas.common.label.username"
					},
					{
						"key": "label.newpassword",
						"mapKeyTo": "ppsspas.common.label.newpassword"
					},
					{
						"key": "label.otpcode",
						"mapKeyTo": "ppsspas.common.label.otpcode"
					},
					{
						"key": "button.requestotp",
						"mapKeyTo": "ppsspas.common.button.requestotp"
					},
					{
						"key": "button.verifyotp",
						"mapKeyTo": "ppsspas.common.button.verifyotp"
					},
					{
						"key": "button.continue",
						"mapKeyTo": "ppsspas.common.button.continue"
					},
					{
						"key": "title",
						"mapKeyTo": "ppsspas.common.title"
					},
					{
						"key": "error.user",
						"mapKeyTo": "ppsspas.common.error.user"
					},
					{
						"key": "error.otp",
						"mapKeyTo": "ppsspas.common.error.otp"
					},
					{
						"key": "error.lockout",
						"mapKeyTo": "ppsspas.common.error.lockout"
					},
					{
						"key": "error.ldappwd",
						"mapKeyTo": "ppsspas.common.error.ldappwd"
					}
				]
			},
			{
				"pipeid": "changepwdsms-complete",
				"template": "changepwd/changepwd-common-complete",
				"sessionValues": [],
				"templateVariables": {
					"done_href": "/ppss/authenticate/logout/?nextTarget=/ppss/authenticate/changepwdchoice/"
				},
				"translation": [
					{
						"key": "header",
						"mapKeyTo": "ppsspassms.messages.completeheader"
					},
					{
						"key": "paragraph",
						"mapKeyTo": "ppsspassms.messages.completetext"
					},
					{
						"key": "title",
						"mapKeyTo": "ppsspas.common.title"
					},
					{
						"key": "button.done",
						"mapKeyTo": "ppsspas.common.button.done"
					}
				]
			}
		]
	},
	"id": "changepwdsms"
}

Adjust the following settings to match your password policy:

Requires lower case character set this value to true else false- "contains_lowercase": "true", 

Requires upper case character set this value to true else false- "contains_uppercase": "true",

Requires special character set this value to true else false - "contains_special": "true",

Requires a number set this value to true else false -  "contains_number": "true",

Minimum length of the password , in this example minimum 8 characters- "password_length": "8"

Verify that "nextTarget" on both “cancel_href” and “done_href” values match your requirements.

If needed change nextTarget value see the following example:

"done_href": "/ppss/authenticate/logout/?nextTarget=/ppss/authenticate/changepwdchoice/"
"done_href": "/ppss/authenticate/logout/?nextTarget=https://www.phenixid.se"

Step 2 - Pipes

Add the following configuration to “Pipes"

{
	"id": "changepwdsms-start",
	"valves": [
		{
			"name": "SessionLoadValve",
			"config": {
				"id": "{{request.session_id}}"
			}
		},
		{
			"name": "LockoutCheckValve",
			"config": {
				"userid_param_name": "{{request.username}}",
				"lockout_enabled": "true",
				"lockout_login_attempts": "3",
				"lockout_time": "30",
				"lockout_login_window": "5"
			}
		},
		{
			"name": "LDAPSearchValve",
			"config": {
				"connection_ref": "replace-ldap-ref",
				"base_dn": "replace-base_dn",
				"scope": "SUB",
				"size_limit": "0",
				"filter_template": "replace-ppss-filter_request",
				"attributes": "mobile"
			}
		},
		{
			"name": "FlowFailValve",
			"config": {
				"message": "User does not exist",
				"exec_if_expr": "flow.items().isEmpty()"
			}
		},
		{
			"name": "FlowFailValve",
			"config": {
				"message": "User does not exist",
				"skip_if_expr": "flow.isSingle()"
			}
		},
		{
			"name": "FlowFailValve",
			"config": {
				"message": "No phone number",
				"exec_if_expr": "",
				"skip_if_expr": "flow.items().get(0).containsProperty('mobile')"
			}
		},
		{
			"name": "SessionBindToUidValve",
			"config": {
				"userid": "{{request.username}}"
			}
		},
		{
			"name": "OTPGeneratorValve",
			"config": {
				"length": "6",
				"alpha_numeric": "false",
				"name": "generated_otp",
				"valid_time_in_seconds": "300",
				"exec_if_expr": "",
				"skip_if_expr": ""
			}
		},
		{
			"name": "SessionPropertyAddValve",
			"config": {
				"name": "generated_otp",
				"value": "{{item.generated_otp}}",
				"skip_if_expr": ""
			}
		},
		{
			"name": "SessionPropertyAddValve",
			"config": {
				"name": "username",
				"value": "{{request.username}}",
				"skip_if_expr": ""
			}
		},
		{
			"name": "SessionPropertyAddValve",
			"config": {
				"name": "sentotp",
				"value": "true",
				"skip_if_expr": ""
			}
		},
		{
			"name": "OTPBySMSValve",
			"config": {
				"gw_username": "replace-ppss-gw_username",
				"gw_password": "replace-ppss-gw_password",
				"recipient_param_name": "{{item.mobile}}",
				"generated_otp_name": "generated_otp",
				"use_flash": "true",
				"userid_param_name": "{{request.username}}",
				"exec_if_expr": "",
				"skip_if_expr": ""
			}
		},
		{
			"name": "SessionPersistValve",
			"config": {}
		}
	]
},
{
	"id": "changepwdsms-verify",
	"valves": [
		{
			"name": "SessionLoadValve",
			"config": {
				"id": "{{request.session_id}}"
			}
		},
		{
			"name": "ItemCreateValve",
			"config": {
				"dest_id": "{{request.session_id}}"
			}
		},
		{
			"name": "LockoutCheckValve",
			"config": {
				"userid_param_name": "{{session.username}}",
				"lockout_enabled": "true",
				"lockout_login_attempts": "3",
				"lockout_time": "30",
				"lockout_login_window": "5"
			}
		},
		{
			"name": "OTPValidationValve",
			"config": {
				"provided_otp_param_name": "{{request.otp}}",
				"generated_otp_param_name": "generated_otp",
				"proceed_on_error": "true",
				"exec_if_expr": "",
				"userid_param_name": "{{session.username}}",
				"lockout_enabled": "true",
				"lockout_login_attempts": "3",
				"lockout_time": "30",
				"lockout_login_window": "5"
			}
		},
		{
			"name": "FlowFailValve",
			"config": {
				"message": "Wrong verification code",
				"exec_if_expr": "attributes.user_authenticated === false"
			}
		},
		{
			"name": "SessionPropertyAddValve",
			"config": {
				"name": "otpverified",
				"value": "true",
				"skip_if_expr": ""
			}
		},
		{
			"name": "SessionPersistValve",
			"config": {}
		}
	]
},
{
	"id": "changepwdsms-setpwd",
	"valves": [
		{
			"name": "SessionLoadValve",
			"config": {
				"id": "{{request.session_id}}"
			}
		},
		{
			"name": "InputParameterExistValidatorValve",
			"config": {
				"param_name": "password"
			}
		},
		{
			"name": "LDAPSearchValve",
			"config": {
				"connection_ref": "replace-ldap-ref",
				"base_dn": "replace-base_dn",
				"scope": "SUB",
				"size_limit": "0",
				"filter_template": "replace-ppss-filter_session",
				"attributes": ""
			}
		},
		{
			"name": "FlowFailValve",
			"config": {
				"message": "User does not exist",
				"exec_if_expr": "flow.items().isEmpty()"
			}
		},
		{
			"name": "replace-ppss-pwdvalve",
			"enabled": "true",
			"config": {
				"connection_ref": "replace-ldap-ref",
				"value": "{{request.password}}"
			}
		},
		{
			"name": "EventValve",
			"config": {
				"event_key": "EVT_000054",
				"parameters": [
					{
						"parameter": "duser",
						"value": "{{session.username}}"
					}
				]
			}
		},
		{
			"name": "SessionPersistValve",
			"config": {}
		}
	]
},
{
	"id": "changepwdsms-complete",
	"valves": [
		{
			"name": "SessionLoadValve",
			"config": {
				"id": "{{request.session_id}}"
			}
		},
		{
			"name": "SessionRemoveValve",
			"config": {}
		}
	]
}

Replace the following Pipe settings:

“replace-ldap-ref” with your LDAP connection id, example “731c93fb-f123-403a-9b4f-45720eeed474”

“replace-base_dn” with your “base_dn”, example “DC=phenixid,DC=local”

"replace-ppss-gw_username" with your Message Gateway account

"replace-ppss-gw_password"  with your Message Gateway password

"replace-ppss-filter_request" with either "sAMAccountName={{request.username}}" if you have Active Directory or "uid={{request.username}}" for other LDAP catalogs

"replace-ppss-filter_session" with either "sAMAccountName={{session.username}}" if you have Active Directory or "uid={{session.username}}" for other LDAP catalogs

"replace-ppss-pwdvalve" with "ADPasswordChangeValve" if you have Active Directory,
for other LDAP catalogs replace with "LDAPModifyValve" and add "modification_type": "REPLACE",
to the config section of the valve

Verify that “filter_template” and “attributes” match your environment.

Make sure that "lockout_login_attempts", "lockout_time" and "lockout_login_window" follows your security policy.

Browse to https://"Server address":"port"/ppss/authenticate/changepwdsms,
example https://www.phenixid.se:8443/ppss/authenticate/changepwdsms