Skip to content

Commit

Permalink
Merge pull request #6696 from RushanNanayakkara/fix_sms_otp_for_pw_re…
Browse files Browse the repository at this point in the history
…covery

Fix sms otp for pw recovery not working for multi attribute identifier and minor improvements
  • Loading branch information
RushanNanayakkara authored Aug 12, 2024
2 parents 24d1035 + b5d3245 commit 1165f22
Show file tree
Hide file tree
Showing 20 changed files with 92 additions and 18 deletions.
7 changes: 7 additions & 0 deletions .changeset/moody-pumas-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@wso2is/identity-apps-core": patch
"@wso2is/console": patch
"@wso2is/features": patch
---

Fix bugs in SM OTP for password recovery feature
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ features/themes/
apps/myaccount/src/main/
apps/console/src/main/
apps/*/cache
**/*/v8-compile-cache-0
apps/myaccount/src/themes/
apps/console/src/themes/
apps/console/src/login-portal-layouts
Expand Down
1 change: 1 addition & 0 deletions apps/console/src/extensions/i18n/models/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3099,6 +3099,7 @@ export interface Extensions {
passwordRecoveryOtpUseNumeric: FormAttributes;
passwordRecoveryOtpLength: FormAttributes;
};
smsProviderWarning: string;
};
recoveryOptionSubHeadingEmailLink: string;
recoveryOptionSubHeadingSMS: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3691,14 +3691,16 @@ export const extensions: Extensions = {
validations: {
empty: "Password recovery OTP length cannot be empty.",
maxLengthReached:
"Password recovery OTP length should be between 6 and 10 characters."
"Password recovery OTP length should be between 4 and 10 characters."
}
},
enableEmailBasedRecovery: {
hint: "This specifies whether to send an recovery link to the email address.",
label: "Enable email link based recovery"
}
}
},
smsProviderWarning:
"Ensure that an <1>SMS Provider</1> is configured for the OTP feature to work properly."
},
recoveryOptionSubHeadingEmailLink: "Email Link",
recoveryOptionSubHeadingSMS: "SMS OTP",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export class GovernanceConnectorConstants {
SMS_OTP_CODE_LENGTH_MAX_LENGTH: 2,
SMS_OTP_CODE_LENGTH_MAX_VALUE: 10,
SMS_OTP_CODE_LENGTH_MIN_LENGTH: 1,
SMS_OTP_CODE_LENGTH_MIN_VALUE: 6,
SMS_OTP_CODE_LENGTH_MIN_VALUE: 4,
SMS_OTP_EXPIRY_TIME_MAX_LENGTH: 4,
SMS_OTP_EXPIRY_TIME_MAX_VALUE: 1440
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@
div:nth-child(6),
div:nth-child(7),
div:nth-child(8),
div:nth-child(12),
div:nth-child(13) {
div:nth-child(13),
div:nth-child(14) {
margin-left: 50px;
}

.MuiChip-root {
margin-left: 10px !important;
}

.message {
margin-bottom: 1.5em;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

import Chip from "@oxygen-ui/react/Chip";
import { AppConstants, history } from "@wso2is/admin.core.v1";
import FeatureStatusLabel from "@wso2is/admin.extensions.v1/components/feature-gate/models/feature-gate";
import {
PasswordRecoveryConfigurationFormPropsInterface,
Expand All @@ -27,13 +28,13 @@ import {
} from "@wso2is/admin.server-configurations.v1";
import { CommonUtils } from "@wso2is/core/utils";
import { Field, Form } from "@wso2is/form";
import { Heading, Hint } from "@wso2is/react-components";
import { Heading, Hint, Link, Message } from "@wso2is/react-components";
import { FormValidation } from "@wso2is/validation";
import isEmpty from "lodash-es/isEmpty";
import React, { FunctionComponent, ReactElement, ReactNode, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Trans, useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
import { Divider } from "semantic-ui-react";
import { Divider, Icon } from "semantic-ui-react";
import { AppState } from "../../../admin.core.v1";
import { GovernanceConnectorConstants } from "../../constants/governance-connector-constants";
import { ServerConfigurationsConstants } from "../../constants/server-configurations-constants";
Expand Down Expand Up @@ -239,14 +240,14 @@ export const PasswordRecoveryConfigurationForm: FunctionComponent<PasswordRecove
} else if (!values.smsOtpLength) {
// Check for required error
errors.smsOtpLength = t("extensions:manage.serverConfigurations.accountRecovery." +
"passwordRecovery.form.fields.smsOtpLength.validations.empty");
"passwordRecovery.form.fields.passwordRecoveryOtpLength.validations.empty");
} else if (parseInt(values.smsOtpLength, 10) < GovernanceConnectorConstants
.PASSWORD_RECOVERY_FORM_FIELD_CONSTRAINTS.SMS_OTP_CODE_LENGTH_MIN_VALUE ||
parseInt(values.smsOtpLength, 10) > GovernanceConnectorConstants
.PASSWORD_RECOVERY_FORM_FIELD_CONSTRAINTS.SMS_OTP_CODE_LENGTH_MAX_VALUE) {
// Check for invalid input length.
errors.smsOtpLength = t("extensions:manage.serverConfigurations.accountRecovery." +
"passwordRecovery.form.fields.smsOtpLength.validations.maxLengthReached");
"passwordRecovery.form.fields.passwordRecoveryOtpLength.validations.maxLengthReached");
} else if (!values.maxResendCount) {
// Check for required error
errors.maxResendCount = t("extensions:manage.serverConfigurations.accountRecovery." +
Expand Down Expand Up @@ -426,6 +427,29 @@ export const PasswordRecoveryConfigurationForm: FunctionComponent<PasswordRecove
className="oxygen-menu-item-chip oxygen-chip-beta" />)
}
</Heading>
{
<Message info>
<Icon name="info circle" />
<Trans
i18nKey={
"extensions:manage.serverConfigurations.accountRecovery." +
"passwordRecovery.form.smsProviderWarning"
}
>
Ensure that an
<Link
external={ false }
onClick={ () => {
history.push(
AppConstants.getPaths().get("SMS_PROVIDER")
);
} }
>SMS Provider
</Link>
&nbsp;is configured for the OTP feature to work properly.
</Trans>
</Message>
}
<Field.Checkbox
ariaLabel="enableSMSBasedRecovery"
name="enableSMSBasedRecovery"
Expand Down Expand Up @@ -564,7 +588,7 @@ export const PasswordRecoveryConfigurationForm: FunctionComponent<PasswordRecove
}
label= { t("extensions:manage.serverConfigurations.accountRecovery." +
"passwordRecovery.form.fields.passwordRecoveryOtpLength.label") }
placeholder="SMS OTP Length"
placeholder="OTP Length"
required={ false }
maxLength={
GovernanceConnectorConstants
Expand Down
1 change: 1 addition & 0 deletions features/admin.server-configurations.v1/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@wso2is/admin.core.v1": "^2.24.7",
"@wso2is/admin.extensions.v1": "^2.22.2",
"@wso2is/admin.identity-providers.v1": "^2.21.44",
"@wso2is/admin.organizations.v1": "^2.20.96",
"@wso2is/admin.server-configurations.v1": "^2.21.56",
"@wso2is/admin.users.v1": "^2.20.114",
"@wso2is/admin.validation.v1": "^2.20.114",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ Please.enter.valid.email=Please enter a valid email address.
Please.enter.valid.input=Please enter a valid input.
Please.enter.your.email=Please enter your email address.
Please.enter.your.username=Please enter your username.
Please.enter.your.identifier=Please enter your identifier.
Go.to.MyAccount=Go to My Account
Back.to.application=Back to application
Password.set.success=Password Set Successfully
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Please.enter.valid.email=Bitte geben Sie eine gültige E-Mail-Adresse ein.
Please.enter.valid.input=Bitte geben Sie eine gültige Eingabe ein.
Please.enter.your.email=Geben Sie bitte Ihre Email-Adresse ein.
Please.enter.your.username=Bitte geben Sie Ihren Benutzernamen ein.
Please.enter.your.identifier=Bitte geben Sie Ihre Kennung ein.
Go.to.MyAccount=Zu Mein Konto gehen
Back.to.application=Zurück zur Registrierung
Password.set.success=Passwort erfolgreich erstellt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Please.enter.valid.email=Por favor, introduce una dirección de correo electrón
Please.enter.valid.input=Por favor ingrese una entrada válida.
Please.enter.your.email=Por favor, introduzca su dirección de correo electrónico.
Please.enter.your.username=Por favor, ingrese su nombre de usuario.
Please.enter.your.identifier=Por favor, introduzca su identificador.
Go.to.MyAccount=ir a mi cuenta
Back.to.application=Volver a la aplicación
Password.set.success=Contraseña establecida correctamente
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ Please.enter.valid.email=S'il vous plaît, mettez une adresse email valide.
Please.enter.valid.input=Veuillez saisir une entrée valide.
Please.enter.your.email=Veuillez saisir votre adresse e-mail.
Please.enter.your.username=S'il vous plaît entrez votre nom d'utilisateur.
Please.enter.your.identifier=Veuillez entrer votre identifiant.
Go.to.MyAccount=Accéder à mon Compte
Back.to.application=Retour à la candidature
Password.reset.Success=Mot de passe réinitialisé avec succès
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ Please.enter.valid.email=有効なメールアドレスを入力してくださ
Please.enter.valid.input=有効なエントリを入力してください。
Please.enter.your.email=メールアドレスを入力してください。
Please.enter.your.username=ユーザー名を入力してください。
Please.enter.your.identifier=識別子を入力してください。
Go.to.MyAccount=マイアカウントへ移動
Back.to.application=アプリケーションに戻る
Password.set.success=パスワードが正常に設定されました
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Please.enter.valid.email=or favor, insira um endereço de e-mail válido.
Please.enter.valid.input=Por favor, insira uma entrada válida.
Please.enter.your.email=Por favor, insira seu endereço de e-mail.
Please.enter.your.username=Por favor, insira seu nome de usuário.
Please.enter.your.identifier=Por favor, insira seu identificador.
Go.to.MyAccount=Ir para Minha Conta
Back.to.application=Voltar ao aplicativo
Password.set.success=Senha definida com sucesso
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Please.enter.valid.email=Por favor insira um endereço de e-mail válido.
Please.enter.valid.input=Por favor, insira uma entrada válida.
Please.enter.your.email=Por favor, indique o seu endereço de e-mail.
Please.enter.your.username=Por favor insira seu nome de usuário.
Please.enter.your.identifier=Por favor, introduza o seu identificador.
Go.to.MyAccount=Vá para Minha Conta
Back.to.application=De volta ao aplicativo
Password.set.success=Definido de senha com sucesso
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ Please.enter.valid.email=请输入有效的电子邮件地址。
Please.enter.valid.input=请输入有效的条目。
Please.enter.your.email=请输入您的电子邮件地址。
Please.enter.your.username=请输入您的用户名。
Please.enter.your.identifier=请输入您的标识符。
Go.to.MyAccount=转至“我的账户
Back.to.application=返回应用程序
Password.set.success=密码设置成功
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.model.recovery.v2.RecoveryResponse" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.model.recovery.v2.ResendRequest" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.model.recovery.v2.ResendResponse" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.PreferenceRetrievalClient" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.PreferenceRetrievalClientException" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.IdentityManagementEndpointConstants" %>

<%-- Include tenant context --%>
Expand Down Expand Up @@ -125,9 +127,21 @@
}
%>
<%
final String USERNAME_CLAIM_URI_FOR_TENANT = "http://wso2.org/claims/username";
String userIdentifierClaimKey = "http://wso2.org/claims/username";
final String MULTI_ATTRIBUTE_USER_IDENTIFIER_CLAIM_URI = "internal.user.identifier.claim.uri";
final RecoveryApiV2 recoveryApiV2 = new RecoveryApiV2();
try {
PreferenceRetrievalClient preferenceRetrievalClient = new PreferenceRetrievalClient();
if (preferenceRetrievalClient.checkMultiAttributeLogin(tenantDomain)) {
userIdentifierClaimKey = MULTI_ATTRIBUTE_USER_IDENTIFIER_CLAIM_URI;
}
} catch (PreferenceRetrievalClientException e) {
IdentityManagementEndpointUtil.addErrorInformation(request, e);
request.getRequestDispatcher("error.jsp").forward(request, response);
return;
}
String username = (String) request.getAttribute("username");
if (StringUtils.isBlank(username)) {
username = request.getParameter("username");
Expand All @@ -149,7 +163,7 @@
// Get the username claim string for the tenant
UserClaim userNameClaim = new UserClaim();
userNameClaim.setUri(USERNAME_CLAIM_URI_FOR_TENANT);
userNameClaim.setUri(userIdentifierClaimKey);
userNameClaim.setValue(MultitenantUtils.getTenantAwareUsername(username));
userClaims.add(userNameClaim);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,8 @@
"Please.enter.valid.email")%>";
const emptyUsernameErrorMsg = "<%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle,
"Please.enter.your.username")%>";
const emptyUserIdentifierMsg = "<%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle,
"Please.enter.your.identifier")%>";
let errorMsgContent = document.getElementById("error-message");
let userName = document.getElementById("username");
Expand All @@ -569,7 +571,8 @@
}
if ($("#username").val() === "") {
errorMsgContent.innerHTML = emptyUsernameErrorMsg;
errorMsgContent.innerHTML =
<%=isMultiAttributeLoginEnabledInTenant? "emptyUserIdentifierMsg" : "emptyUsernameErrorMsg"%>;
errorMessage.show();
submitBtnState( { disabled: true } );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,14 @@
String baseUrl = ServiceURLBuilder.create()
.addPath("/accountrecoveryendpoint/recoveraccountrouter.do").build()
.getRelativePublicURL();
String multiOptionPathWithQuery = urlQuery + "&username=" + username
+ "&selectedOption=SMSOTP";
String multiOptionPathWithQuery;
if (urlQuery.contains("&username=")) {
multiOptionPathWithQuery =
urlQuery.replaceAll("(&username=)[^&]+", "$1" + username);
} else {
multiOptionPathWithQuery = urlQuery + "&username=" + username
+ "&selectedOption=SMSOTP";
}
%>
<a class="ui primary basic button link-button" id="goBackLink"
href=<%=baseUrl + "?" + multiOptionPathWithQuery %>>
Expand Down
7 changes: 5 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1165f22

Please sign in to comment.