cordova-plugin-ionic-webview icon indicating copy to clipboard operation
cordova-plugin-ionic-webview copied to clipboard

Login form validation issues with auto-fill from password manager

Open ZaLiTHkA opened this issue 2 years ago • 1 comments

firstly, two important notes here:

  1. I do not have the issue described in #636. I use Bitwarden password manager, and I get the "Passwords" input auto-fill option exactly as expected every time.
  2. I do not have access to a Mac for debugging this issue.. I've requested one from my boss numerous times, but nothing has happened with that process as yet. the only device I currently have for testing is a 6th gen iPad running 15.3.1 (19D52).

when running the app on iOS, selecting either the "email" or "password" and filling in details with a password manager does not mark the other field as "filled in", resulting in the "Login" button remaining disabled with no further feedback.

because the "Passwords" auto-fill prompt only appears when a login form is given focus, the observed behaviour changes depending on which field was focused to initiate this process. where the problem described here will then affect the other input field.

furthermore, the form field validation messages only show for an input field after that field has received and lost focus. I would assume in order to validate the user's input after something is entered.

see the following screenshots for clarification (app logo and email address obscured for privacy reasons, this is an un-announced application for my current employer):

auto-fill with "email" field focussed auto-fill with "password" field focussed
password-manager-issue-email-first - obscured password-manager-issue-password-first - obscured
incorrect error shows up after focussing and leaving the "password" input field. incorrect error shows up after focussing and leaving the "email" input field.

please note: this problem does not happen on Android, both login form fields refresh correctly and the "Login" button is enabled as expected.


my ionic info output is as follows:

Ionic:

   Ionic CLI                     : 6.19.0 (C:\Users\agreeff\AppData\Local\Volta\tools\image\packages\@ionic\cli\node_modules\@ionic\cli)
   Ionic Framework               : @ionic/angular 6.0.12
   @angular-devkit/build-angular : 12.2.16
   @angular-devkit/schematics    : 12.2.16
   @angular/cli                  : 12.2.16
   @ionic/angular-toolkit        : 5.0.3

Cordova:

   Cordova CLI       : 11.0.0
   Cordova Platforms : android 10.1.1
   Cordova Plugins   : cordova-plugin-ionic-keyboard 2.2.0, cordova-plugin-ionic-webview 5.0.0, cordova-plugin-ionic 5.5.1, (and 4 other plugins)

Utility:

   cordova-res : 0.15.4
   native-run  : 1.5.0

System:

   Android SDK Tools : 26.1.1 (C:\android-sdk)
   NodeJS            : v14.19.0 (C:\Users\agreeff\AppData\Local\Volta\tools\image\node\14.19.0\node.exe)
   npm               : 6.14.16
   OS                : Windows 10

and my package.json file lists the following dependencies:

{
  "dependencies": {
    "@angular/common": "12.2.16",
    "@angular/core": "12.2.16",
    "@angular/forms": "12.2.16",
    "@angular/platform-browser": "12.2.16",
    "@angular/platform-browser-dynamic": "12.2.16",
    "@angular/router": "12.2.16",
    "@awesome-cordova-plugins/app-version": "5.40.0",
    "@awesome-cordova-plugins/core": "5.40.0",
    "@awesome-cordova-plugins/firebase-x": "5.40.0",
    "@awesome-cordova-plugins/splash-screen": "5.40.0",
    "@awesome-cordova-plugins/status-bar": "5.40.0",
    "@ionic/angular": "6.0.12",
    "@ionic/storage": "3.0.6",
    "@ionic/storage-angular": "3.0.6",
    "cordova-android": "10.1.1",
    "cordova-ios": "6.2.0",
    "rxjs": "6.6.7",
    "tslib": "2.3.1",
    "zone.js": "0.11.5"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "12.2.16",
    "@angular-eslint/builder": "12.7.0",
    "@angular-eslint/eslint-plugin": "12.7.0",
    "@angular-eslint/eslint-plugin-template": "12.7.0",
    "@angular-eslint/template-parser": "12.7.0",
    "@angular/cli": "12.2.16",
    "@angular/compiler": "12.2.16",
    "@angular/compiler-cli": "12.2.16",
    "@angular/language-service": "12.2.16",
    "@ionic/angular-toolkit": "5.0.3",
    "@types/jasmine": "3.10.4",
    "@types/jasminewd2": "2.0.10",
    "@types/node": "14.18.12",
    "@typescript-eslint/eslint-plugin": "5.16.0",
    "@typescript-eslint/parser": "5.16.0",
    "cordova-plugin-app-version": "0.1.13",
    "cordova-plugin-device": "2.0.3",
    "cordova-plugin-firebasex": "git+https://github.com/dpa99c/cordova-plugin-firebasex.git#751ba5a35fe7461731cde6a1ea5fd1b973941572",
    "cordova-plugin-ionic": "5.5.1",
    "cordova-plugin-ionic-keyboard": "2.2.0",
    "cordova-plugin-ionic-webview": "5.0.0",
    "cordova-plugin-splashscreen": "6.0.0",
    "cordova-plugin-statusbar": "3.0.0",
    "eslint": "7.32.0",
    "eslint-plugin-import": "2.25.4",
    "eslint-plugin-jsdoc": "30.7.13",
    "eslint-plugin-prefer-arrow": "1.2.3",
    "jasmine-core": "3.99.1",
    "jasmine-spec-reporter": "5.0.2",
    "karma": "6.3.17",
    "karma-chrome-launcher": "3.1.1",
    "karma-coverage": "2.2.0",
    "karma-coverage-istanbul-reporter": "3.0.3",
    "karma-jasmine": "4.0.1",
    "karma-jasmine-html-reporter": "1.7.0",
    "prettier": "2.6.0",
    "protractor": "7.0.0",
    "ts-node": "8.10.2",
    "typescript": "4.4.4"
  }
}

my login.page.html file contains the following:

<ion-content>
  <form (ngSubmit)="login()" [formGroup]="credentials" class="login-form">
    <div class="login-logo-wrapper">
      <img src="/assets/app-logo.png" alt="Application Logo" class="login-logo" />
    </div>

    <div class="input-group">
      <ion-item>
        <ion-input type="email" placeholder="Email" formControlName="email"></ion-input>
      </ion-item>
      <div *ngIf="(email.dirty || email.touched) && email.errors" class="errors">
        <span *ngIf="email.errors?.required">Email is required</span>
        <span *ngIf="email.errors?.pattern">Email is invalid</span>
      </div>
      <ion-item>
        <ion-input type="password" placeholder="Password" formControlName="password"></ion-input>
      </ion-item>
      <div *ngIf="(password.dirty || password.touched) && password.errors" class="errors">
        <span *ngIf="password.errors?.required">Password is required</span>
      </div>
    </div>

    <ion-button type="submit" expand="block" [disabled]="!credentials.valid">Log in</ion-button>
  </form>
</ion-content>

while my login.page.ts component file contains the following (with unrelated code blocks removed):

@Component({
  selector: "app-login",
  templateUrl: "./login.page.html",
  styleUrls: ["./login.page.scss"],
})
export class LoginPage implements OnInit {
  credentials: FormGroup;

  private loginLoader: HTMLIonLoadingElement;

  constructor(
    private formBuilder: FormBuilder,
    private authService: AuthenticationService,
    private loadingController: LoadingController,
  ) {}

  get email() {
    return this.credentials.get("email");
  }

  get password() {
    return this.credentials.get("password");
  }

  async ngOnInit() {
    const emailValidationPattern = /^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+(?:\\.[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+)*@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$/;

    this.credentials = this.formBuilder.group({
      email: ["", [Validators.required, Validators.pattern(emailValidationPattern)]],
      password: ["", [Validators.required]],
    });

    this.loginLoader = await this.loadingController.create();
    this.loginLoader.message = "Initialising...";
    this.loginLoader.present();

    // attempt to auto-login using a "refresh token"
    await this.authService.refreshAuthToken();

    this.loginLoader.dismiss();
  }
}

ZaLiTHkA avatar Mar 28 '22 09:03 ZaLiTHkA

old webkit bug whereas autofill does not emit an input event

Workaround is to register a change event handler as in https://gist.github.com/dtarnawsky/fc92869c1c67b9c74c66de8af3e081b2

See also https://capacitorjs.com/docs/guides/autofill-credentials

vbraun avatar Feb 08 '23 17:02 vbraun