From ba5267843f1dd80b89ae1d16ecbfc8bc1df5322f Mon Sep 17 00:00:00 2001 From: gbutler Date: Thu, 30 Jul 2026 13:22:54 -0500 Subject: [PATCH 1/4] feat(auth): update password reset page UI and policy - Replace email field outline with filled/disabled style - Add password visibility toggle with eye icon - Add confirm field match indicator (empty circle / green check / red X) - Add password requirements list derived from config - Add help link below the card - Disable submit button until all requirements pass and fields match - Update card title and subheader to FN branding - Fix min password length to 10 (was 8) and add + to allowed special chars pattern - Add AUTH_PASSWORD_MIN_LENGTH, AUTH_PASSWORD_SHAPE_LIST, and AUTH_PASSWORD_ALLOWED_SPECIAL_CHARACTERS_TEXT config keys - Update local dev docs: queue drain command and config cache notes --- .env.example | 1 - LOCAL_DEVELOPMENT_HOWTO.md | 50 +++++++++++++ config/auth.php | 2 + resources/js/reset_password/reset_password.js | 70 +++++++++++++++---- .../reset_password/reset_password.module.scss | 41 ++++++++++- .../views/auth/passwords/reset.blade.php | 6 +- 6 files changed, 153 insertions(+), 17 deletions(-) diff --git a/.env.example b/.env.example index 04492f4d..54dbda2f 100644 --- a/.env.example +++ b/.env.example @@ -110,7 +110,6 @@ MAIL_SEND_WELCOME_EMAIL=1 DEFAULT_PROFILE_IMAGE= AUTH_PASSWORD_RESET_LIFETIME=1800 - AUTH_PASSWORD_SHAPE_PATTERN="^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-])" AUTH_PASSWORD_SHAPE_WARNING="Password must include at least one uppercase letter, one lowercase letter, one number, and one special character." diff --git a/LOCAL_DEVELOPMENT_HOWTO.md b/LOCAL_DEVELOPMENT_HOWTO.md index 7f888561..d48ad99d 100644 --- a/LOCAL_DEVELOPMENT_HOWTO.md +++ b/LOCAL_DEVELOPMENT_HOWTO.md @@ -29,6 +29,56 @@ SSL_ENABLED=false [https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-22-04](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-22-04) and [https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-22-04](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-22-04) 4.Run script ./start_local_server.sh (http://localhost:8001/) +Frontend Development +==================== + +openstackid is a Laravel app — blade templates reference compiled JS bundles in `public/assets/`, not source files. The source files in `resources/js/` must be compiled before changes take effect in the browser. + +**One-time setup:** The compiled assets in `public/assets/` are owned by root if they were originally built inside Docker. Fix ownership before running any build commands: + +```bash +sudo chown -R $(whoami) public/assets +``` + +**Build and watch** (recompiles automatically on save, Ctrl+C to stop): + +```bash +npm run build-dev +``` + +To do a one-shot build without watch mode: + +```bash +./node_modules/.bin/webpack --config webpack.prod.js +``` + +**Captcha:** The reset password and other pages require a Cloudflare Turnstile site key. Add test keys to `.env` to use the captcha locally without a real Cloudflare account: + +```dotenv +TURNSTILE_SITE_KEY=1x00000000000000000000AA +TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA +``` + +**Email:** Outbound email is logged to a date-stamped file in `storage/logs/` rather than sent. However, emails are queued via Redis by default, so they are not processed until a queue worker runs. After submitting the forgot password form, process the queue to trigger the log entry: + +```bash +docker exec idp-app php artisan queue:work --stop-when-empty +``` + +This processes all pending jobs and exits when the queue is empty. Use `--once` if you only want to process a single job. + +To retrieve a password reset link after processing the queue: + +```bash +grep "password/reset" storage/logs/laravel-$(date +%Y-%m-%d).log | tail -1 +``` + +After editing `.env`, clear the config cache: + +```bash +docker exec idp-app php artisan config:clear +``` + Redump the database =================== diff --git a/config/auth.php b/config/auth.php index 5da1b184..c4687d5a 100644 --- a/config/auth.php +++ b/config/auth.php @@ -103,8 +103,10 @@ 'password_min_length' => env('AUTH_PASSWORD_MIN_LENGTH', 8), 'password_max_length' => env('AUTH_PASSWORD_MAX_LENGTH', 30), 'password_allowed_special_characters' => env('AUTH_PASSWORD_ALLOWED_SPECIAL_CHARACTERS', '[A-Za-z0-9#?!@$%^&*+-]'), + 'password_allowed_special_characters_text' => env('AUTH_PASSWORD_ALLOWED_SPECIAL_CHARACTERS_TEXT', '#?!@$%^&*+-'), 'password_shape_pattern' => env('AUTH_PASSWORD_SHAPE_PATTERN', '^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*+\-])[A-Za-z0-9#?!@$%^&*+\-]+$'), 'password_shape_warning' => env('AUTH_PASSWORD_SHAPE_WARNING', 'Password must include at least one uppercase letter, one lowercase letter, one number, and one special character (#?!@$%^&*+-).'), + 'password_shape_list' => env('AUTH_PASSWORD_SHAPE_LIST', 'Uppercase letter,Lowercase letter,One number,Special character'), 'verification_email_lifetime' => env("AUTH_VERIFICATION_EMAIL_LIFETIME", 600), 'allows_native_auth' => env('AUTH_ALLOWS_NATIVE_AUTH', 1), 'allows_native_on_config' => env('AUTH_ALLOWS_NATIVE_AUTH_CONFIG', 1), diff --git a/resources/js/reset_password/reset_password.js b/resources/js/reset_password/reset_password.js index 6356d422..a2fe7488 100644 --- a/resources/js/reset_password/reset_password.js +++ b/resources/js/reset_password/reset_password.js @@ -8,7 +8,14 @@ import CardContent from "@material-ui/core/CardContent"; import Container from "@material-ui/core/Container"; import CssBaseline from "@material-ui/core/CssBaseline"; import Grid from "@material-ui/core/Grid"; +import IconButton from "@material-ui/core/IconButton"; +import InputAdornment from "@material-ui/core/InputAdornment"; import InfoOutlinedIcon from "@material-ui/icons/InfoOutlined"; +import Visibility from "@material-ui/icons/Visibility"; +import VisibilityOff from "@material-ui/icons/VisibilityOff"; +import CheckCircle from "@material-ui/icons/CheckCircle"; +import Cancel from "@material-ui/icons/Cancel"; +import RadioButtonUnchecked from "@material-ui/icons/RadioButtonUnchecked"; import PasswordStrengthBar from "react-password-strength-bar"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; @@ -39,6 +46,7 @@ const ResetPasswordPage = ({ const formEl = useRef(null); const captcha = useRef(null); const [captchaConfirmation, setCaptchaConfirmation] = useState(null); + const [showPassword, setShowPassword] = useState(false); useEffect(() => { if (resetPasswordError) { @@ -76,6 +84,8 @@ const ResetPasswordPage = ({ } }; + const passwordRequirementItems = passwordPolicy.shape_list.split(",").map(s => s.trim()); + return ( @@ -94,8 +104,8 @@ const ResetPasswordPage = ({ > + setShowPassword(!showPassword)} + edge="end" + size="small" + > + {showPassword ? : } + + + ) + }} /> {formik.values.password && ( + {!formik.values.password_confirmation + ? + : formik.values.password_confirmation === formik.values.password && formik.values.password + ? + : + } + + ) + }} /> - -   - -
- +

Your password must include:

+
    +
  • {passwordPolicy.min_length}–{passwordPolicy.max_length} characters
  • + {passwordRequirementItems.map((item, index) => ( +
  • {item}
  • + ))} +
+

Allowed:

@@ -195,6 +235,11 @@ const ResetPasswordPage = ({ disableElevation fullWidth type="submit" + disabled={ + !!formik.errors.password || + !formik.values.password_confirmation || + formik.values.password_confirmation !== formik.values.password + } > {submitButtonText} @@ -207,6 +252,7 @@ const ResetPasswordPage = ({ +

Need help? support@fntech.com

); }; diff --git a/resources/js/reset_password/reset_password.module.scss b/resources/js/reset_password/reset_password.module.scss index 3fcca6cd..25539084 100644 --- a/resources/js/reset_password/reset_password.module.scss +++ b/resources/js/reset_password/reset_password.module.scss @@ -23,6 +23,10 @@ color: $text-color-dark; background-color: white; + .email_field { + margin-bottom: 12px; + } + .turnstile { margin-top: 10px; margin-bottom: 10px; @@ -36,9 +40,36 @@ } .password_hint { - display: flex; color: $hint-text-color; - vertical-align: middle; + background-color: #fafafa; + margin: 8px 8px; + } + + .password_hint p:first-of-type { + margin: 0 0 8px; + } + + .password_hint ul { + list-style: none; + margin-top: 8px; + padding-left: 10px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4px 12px; + } + + .password_hint ul li { + display: flex; + align-items: center; + gap: 60px; + } + + .password_characters { + font-size: 0.85em; + } + + .password_characters span { + letter-spacing: 0.5em; } .error_label { @@ -46,5 +77,11 @@ font-size: 0.75rem; margin: 4px 0 4px 14px; } + + } + + .help_link { + margin: 1.5rem 0 0; + text-align: center; } } diff --git a/resources/views/auth/passwords/reset.blade.php b/resources/views/auth/passwords/reset.blade.php index 77ce2c32..60a19c0a 100644 --- a/resources/views/auth/passwords/reset.blade.php +++ b/resources/views/auth/passwords/reset.blade.php @@ -24,7 +24,9 @@ max_length: {{ Config::get("auth.password_max_length") }}, shape_pattern: '{{ Config::get("auth.password_shape_pattern") }}', allowed_special_characters: '{{ Config::get("auth.password_allowed_special_characters") }}', - shape_warning: '{{ Config::get("auth.password_shape_warning") }}' + allowed_special_characters_text: '{{ Config::get("auth.password_allowed_special_characters_text") }}', + shape_warning: '{{ Config::get("auth.password_shape_warning") }}', + shape_list: '{{ Config::get("auth.password_shape_list") }}' } @if ($errors->any()) @foreach($errors->all() as $error) @@ -46,7 +48,7 @@ resetPasswordError: error, sessionStatus: '{{ session("status") }}', showInfoBanner: parseInt('{{ Config::get("app.show_info_banner", 0) }}') === 1 ? true: false, - submitButtonText: '{{ __("Password Reset") }}', + submitButtonText: '{{ __("Set password") }}', } {!! script_to('assets/resetPassword.js') !!} From 8e3299ed81d87577e1cc2a59de5eeeae8596d69e Mon Sep 17 00:00:00 2001 From: gbutler Date: Fri, 31 Jul 2026 10:54:32 -0500 Subject: [PATCH 2/4] fix(auth): accessibility and safety improvements to password reset page - Add aria-label to password visibility toggle reflecting show/hide state - Add sr-only aria-live region for confirm field match status - Replace dangerouslySetInnerHTML with plain React child for special characters text; use Js::from() in blade template to safely serialize the value without HTML entity encoding - Update password_min_length default from 8 to 10 to match policy --- config/auth.php | 2 +- resources/js/reset_password/reset_password.js | 11 ++++++++++- .../js/reset_password/reset_password.module.scss | 12 ++++++++++++ resources/views/auth/passwords/reset.blade.php | 2 +- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/config/auth.php b/config/auth.php index c4687d5a..c8e42509 100644 --- a/config/auth.php +++ b/config/auth.php @@ -100,7 +100,7 @@ // in seconds 'password_reset_lifetime' => env('AUTH_PASSWORD_RESET_LIFETIME', 1800), - 'password_min_length' => env('AUTH_PASSWORD_MIN_LENGTH', 8), + 'password_min_length' => env('AUTH_PASSWORD_MIN_LENGTH', 10), 'password_max_length' => env('AUTH_PASSWORD_MAX_LENGTH', 30), 'password_allowed_special_characters' => env('AUTH_PASSWORD_ALLOWED_SPECIAL_CHARACTERS', '[A-Za-z0-9#?!@$%^&*+-]'), 'password_allowed_special_characters_text' => env('AUTH_PASSWORD_ALLOWED_SPECIAL_CHARACTERS_TEXT', '#?!@$%^&*+-'), diff --git a/resources/js/reset_password/reset_password.js b/resources/js/reset_password/reset_password.js index a2fe7488..e6a8dd68 100644 --- a/resources/js/reset_password/reset_password.js +++ b/resources/js/reset_password/reset_password.js @@ -152,6 +152,7 @@ const ResetPasswordPage = ({ onClick={() => setShowPassword(!showPassword)} edge="end" size="small" + aria-label={showPassword ? "Hide password" : "Show password"} > {showPassword ? : } @@ -195,6 +196,14 @@ const ResetPasswordPage = ({ ? : } + + {!formik.values.password_confirmation + ? "" + : formik.values.password_confirmation === formik.values.password && formik.values.password + ? "Passwords match" + : "Passwords do not match" + } + ) }} @@ -208,7 +217,7 @@ const ResetPasswordPage = ({
  • {item}
  • ))} -

    Allowed:

    +

    Allowed: {passwordPolicy.allowed_special_characters_text}

    diff --git a/resources/js/reset_password/reset_password.module.scss b/resources/js/reset_password/reset_password.module.scss index 25539084..17c30c79 100644 --- a/resources/js/reset_password/reset_password.module.scss +++ b/resources/js/reset_password/reset_password.module.scss @@ -80,6 +80,18 @@ } + .sr_only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; + } + .help_link { margin: 1.5rem 0 0; text-align: center; diff --git a/resources/views/auth/passwords/reset.blade.php b/resources/views/auth/passwords/reset.blade.php index 60a19c0a..f7fd50e3 100644 --- a/resources/views/auth/passwords/reset.blade.php +++ b/resources/views/auth/passwords/reset.blade.php @@ -24,7 +24,7 @@ max_length: {{ Config::get("auth.password_max_length") }}, shape_pattern: '{{ Config::get("auth.password_shape_pattern") }}', allowed_special_characters: '{{ Config::get("auth.password_allowed_special_characters") }}', - allowed_special_characters_text: '{{ Config::get("auth.password_allowed_special_characters_text") }}', + allowed_special_characters_text: {{ Illuminate\Support\Js::from(Config::get("auth.password_allowed_special_characters_text")) }}, shape_warning: '{{ Config::get("auth.password_shape_warning") }}', shape_list: '{{ Config::get("auth.password_shape_list") }}' } From 5eb77d2ad9fd5ba81244f0663a225c9f09fb754b Mon Sep 17 00:00:00 2001 From: gbutler Date: Fri, 31 Jul 2026 11:25:16 -0500 Subject: [PATCH 3/4] test: update test passwords to meet 10-character minimum policy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace test passwords (8–9 chars) with a new one (10 chars) across TestSeeder and four test files so the suite passes against the updated auth.password_min_length default. --- database/seeds/TestSeeder.php | 14 +++---- tests/OIDCProtocolTestCase.php | 52 ++++++++++++------------- tests/PasswordChangeRevokeTokenTest.php | 4 +- tests/UserApiTest.php | 4 +- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/database/seeds/TestSeeder.php b/database/seeds/TestSeeder.php index 1b5ceb79..1d365e89 100644 --- a/database/seeds/TestSeeder.php +++ b/database/seeds/TestSeeder.php @@ -248,7 +248,7 @@ private function createTestUsers(){ 'first_name' => 'Sebastian', 'last_name' => 'Marcet', 'email' => 'sebastian@tipit.net', - 'password' => '1Qaz2wsx!', + 'password' => '1Qaz2wsx!9', 'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4, 'gender' => 'male', 'address1' => 'Av. Siempre Viva 111', @@ -269,7 +269,7 @@ private function createTestUsers(){ 'first_name' => 'Sebastian', 'last_name' => 'Marcet IDN', 'email' => 'hei@やる.ca', - 'password' => '1Qaz2wsx!', + 'password' => '1Qaz2wsx!9', 'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4, 'gender' => 'male', 'address1' => 'Av. Siempre Viva 111', @@ -290,7 +290,7 @@ private function createTestUsers(){ 'first_name' => 'Márton', 'last_name' => 'Kiss', 'email' => 'mkiss@tipit.net', - 'password' => '1Qaz2wsx!', + 'password' => '1Qaz2wsx!9', 'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4, 'gender' => 'male', 'address1' => 'Av. Siempre Viva 111', @@ -311,7 +311,7 @@ private function createTestUsers(){ 'first_name' => '付', 'last_name' => '金刚', 'email' => 'fujg573@tipit.net', - 'password' => '1Qaz2wsx!', + 'password' => '1Qaz2wsx!9', 'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4, 'gender' => 'male', 'address1' => 'Av. Siempre Viva 111', @@ -332,7 +332,7 @@ private function createTestUsers(){ 'first_name' => 'Bharath', 'last_name' => 'Kumar M R', 'email' => 'mrbharathee@tipit.net', - 'password' => '1Qaz2wsx!', + 'password' => '1Qaz2wsx!9', 'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4, 'gender' => 'male', 'address1' => 'Av. Siempre Viva 111', @@ -353,7 +353,7 @@ private function createTestUsers(){ 'first_name' => '大塚', 'last_name' => '元央', 'email' => 'yuanying@tipit.net', - 'password' => '1Qaz2wsx!', + 'password' => '1Qaz2wsx!9', 'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4, 'gender' => 'male', 'address1' => 'Av. Siempre Viva 111', @@ -374,7 +374,7 @@ private function createTestUsers(){ 'first_name' => 'Ian Y.', 'last_name' => 'Choi', 'email' => 'ianyrchoi@gmail.com', - 'password' => '1Qaz2wsx!', + 'password' => '1Qaz2wsx!9', 'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4, 'gender' => 'male', 'address1' => 'Av. Siempre Viva 111', diff --git a/tests/OIDCProtocolTestCase.php b/tests/OIDCProtocolTestCase.php index fd95a2c7..7188b2a7 100644 --- a/tests/OIDCProtocolTestCase.php +++ b/tests/OIDCProtocolTestCase.php @@ -126,7 +126,7 @@ public function testLoginWithTrailingSpace() $response = $this->action('POST', "UserController@postLogin", [ 'username' => ' sebastian@tipit.net ', - 'password' => ' 1qaz2wsx ', + 'password' => ' 1Qaz2wsx!9 ', '_token' => Session::token(), 'flow' => 'password', ] @@ -172,7 +172,7 @@ public function testConsentPrompt() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -259,7 +259,7 @@ public function testConsentLogin() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -341,7 +341,7 @@ public function testAuthCode() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -426,7 +426,7 @@ public function testAuthCodeIDN() array ( 'username' => 'hei@やる.ca', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -539,7 +539,7 @@ public function testAuthCodeOpenIdScopeOnly() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -623,7 +623,7 @@ public function testMaxAge1AndWait2() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -687,7 +687,7 @@ public function testToken array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -849,7 +849,7 @@ public function testTokenSeveralScopes array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -997,7 +997,7 @@ public function testGetRefreshTokenWithPromptSetToConsentLogin() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -1140,7 +1140,7 @@ public function testFlowNativeDisplay() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => $json_response['required_params_valid_values']["_token"] ) @@ -1259,7 +1259,7 @@ public function testGetRefreshTokenFromNativeAppNTimes($n = 5) array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -1457,7 +1457,7 @@ public function testTokenResponseModePost() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -1604,7 +1604,7 @@ public function testNativeClientBasicAuth() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -1743,7 +1743,7 @@ public function testClientAuthenticationClientSecretJwt() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -1922,7 +1922,7 @@ public function testClientAuthenticationPrivateKeyJwt() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -2074,7 +2074,7 @@ public function testImplicitFlowTokenIdToken() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -2155,7 +2155,7 @@ public function testImplicitFlowIdToken() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -2240,7 +2240,7 @@ public function testImplicitFlowIdTokenMaxAge1000() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -2350,7 +2350,7 @@ public function testImplicitFlowAccessToken() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -2487,7 +2487,7 @@ public function testImplicitFlowResponseModePost() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -2657,7 +2657,7 @@ public function testHybridFlowCodeIdToken() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -2764,7 +2764,7 @@ public function testHybridFlowCodeIdTokenIdTokenHint() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -2985,7 +2985,7 @@ public function testHybridFlowCodeAccessToken() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -3103,7 +3103,7 @@ public function testHybridFlowCodeAccessTokenIdToken() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) @@ -3210,7 +3210,7 @@ public function testTryingAuthCodeTwice() array ( 'username' => 'sebastian@tipit.net', - 'password' => '1qaz2wsx', + 'password' => '1Qaz2wsx!9', 'flow' => 'password', '_token' => Session::token() ) diff --git a/tests/PasswordChangeRevokeTokenTest.php b/tests/PasswordChangeRevokeTokenTest.php index ad54021b..68dfa52e 100644 --- a/tests/PasswordChangeRevokeTokenTest.php +++ b/tests/PasswordChangeRevokeTokenTest.php @@ -93,7 +93,7 @@ public function testProfilePasswordChangePutsRevokeUserGrantsJobOnQueue(): void 'first_name' => $this->test_user->getFirstName(), 'last_name' => $this->test_user->getLastName(), 'email' => $this->test_user->getEmail(), - 'current_password' => '1Qaz2wsx!', + 'current_password' => '1Qaz2wsx!9', 'password' => 'NewP@ssw0rd!99', 'password_confirmation' => 'NewP@ssw0rd!99', ]; @@ -147,7 +147,7 @@ public function testCurrentSessionPreservedAfterPasswordChange(): void 'first_name' => $this->test_user->getFirstName(), 'last_name' => $this->test_user->getLastName(), 'email' => $this->test_user->getEmail(), - 'current_password' => '1Qaz2wsx!', + 'current_password' => '1Qaz2wsx!9', 'password' => 'Preserved@Sess10n!', 'password_confirmation' => 'Preserved@Sess10n!', ]; diff --git a/tests/UserApiTest.php b/tests/UserApiTest.php index 5d3e204e..de329c62 100644 --- a/tests/UserApiTest.php +++ b/tests/UserApiTest.php @@ -47,8 +47,8 @@ public function testCreate() 'last_name' => 'test', 'email' => 'test+1@test.com', 'country_iso_code' => 'US', - 'password' => '1Qaz2wsx!', - 'password_confirmation' => '1Qaz2wsx!', + 'password' => '1Qaz2wsx!9', + 'password_confirmation' => '1Qaz2wsx!9', 'active' => true, 'email_verified' => true, ]; From 65506e90eaea63b3aa9e2172433e7b756128b6ab Mon Sep 17 00:00:00 2001 From: gbutler Date: Fri, 31 Jul 2026 11:31:42 -0500 Subject: [PATCH 4/4] style(auth): replace deprecated clip with clip-path in .sr_only --- resources/js/reset_password/reset_password.module.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/reset_password/reset_password.module.scss b/resources/js/reset_password/reset_password.module.scss index 17c30c79..0dce2766 100644 --- a/resources/js/reset_password/reset_password.module.scss +++ b/resources/js/reset_password/reset_password.module.scss @@ -87,7 +87,7 @@ padding: 0; margin: -1px; overflow: hidden; - clip: rect(0, 0, 0, 0); + clip-path: inset(50%); white-space: nowrap; border: 0; }