[VPAT-27] chore(security): disable autocomplete on sensitive input fields #8517
Disable autocomplete on authentication and security-related forms to prevent browsers from storing sensitive credentials. This affects sign-in, password reset, account security, and onboarding forms across admin, web, and space apps. Modified components: - Auth forms (email, password, unique code, forgot/reset/set password) - Account security pages - Instance setup and profile onboarding - Shared UI components (auth-input, password-input)
This commit is contained in:
parent
d3c6e5ec94
commit
e9b011896d
20 changed files with 52 additions and 40 deletions
|
|
@ -8,10 +8,7 @@ import React, { useState } from "react";
|
|||
import { cn } from "@plane/utils";
|
||||
import { AuthInput } from "./auth-input";
|
||||
|
||||
export interface AuthConfirmPasswordInputProps extends Omit<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
"autoComplete"
|
||||
> {
|
||||
export type TAuthConfirmPasswordInputProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
||||
password: string;
|
||||
label?: string;
|
||||
error?: string;
|
||||
|
|
@ -19,9 +16,8 @@ export interface AuthConfirmPasswordInputProps extends Omit<
|
|||
containerClassName?: string;
|
||||
labelClassName?: string;
|
||||
errorClassName?: string;
|
||||
autoComplete?: "on" | "off";
|
||||
onPasswordMatchChange?: (matches: boolean) => void;
|
||||
}
|
||||
};
|
||||
|
||||
export function AuthConfirmPasswordInput({
|
||||
password,
|
||||
|
|
@ -35,7 +31,7 @@ export function AuthConfirmPasswordInput({
|
|||
onChange,
|
||||
onPasswordMatchChange,
|
||||
...props
|
||||
}: AuthConfirmPasswordInputProps) {
|
||||
}: TAuthConfirmPasswordInputProps) {
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
|
||||
const confirmPassword = value as string;
|
||||
|
|
@ -77,7 +73,7 @@ export function AuthConfirmPasswordInput({
|
|||
onChange={handleChange}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
autoComplete="on"
|
||||
autoComplete="off"
|
||||
/>
|
||||
{confirmPassword && passwordsMatch && <p className="text-13 text-success-primary">Passwords match</p>}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,13 +9,12 @@ import React, { useState } from "react";
|
|||
import { Input } from "../form-fields/input";
|
||||
import { cn } from "../utils";
|
||||
|
||||
export interface AuthInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "autoComplete"> {
|
||||
export type TAuthInputProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
||||
label?: string;
|
||||
error?: string;
|
||||
showPasswordToggle?: boolean;
|
||||
errorClassName?: string;
|
||||
autoComplete?: "on" | "off";
|
||||
}
|
||||
};
|
||||
|
||||
const baseContainerClassName = "flex flex-col gap-1.5";
|
||||
|
||||
|
|
@ -26,8 +25,9 @@ export function AuthInput({
|
|||
errorClassName = "",
|
||||
className = "",
|
||||
type = "text",
|
||||
autoComplete = "off",
|
||||
...props
|
||||
}: AuthInputProps) {
|
||||
}: TAuthInputProps) {
|
||||
const { id } = props;
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const isPasswordType = type === "password";
|
||||
|
|
@ -45,6 +45,7 @@ export function AuthInput({
|
|||
<Input
|
||||
{...props}
|
||||
type={inputType}
|
||||
autoComplete={autoComplete}
|
||||
className={cn(
|
||||
"rounded-md disable-autofill-style h-6 w-full placeholder:text-14 placeholder:text-placeholder p-0 border-none",
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,17 +10,16 @@ import { cn, getPasswordStrength } from "@plane/utils";
|
|||
import { PasswordStrengthIndicator } from "../form-fields/password/indicator";
|
||||
import { AuthInput } from "./auth-input";
|
||||
|
||||
export interface AuthPasswordInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "autoComplete"> {
|
||||
export type TAuthPasswordInputProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
||||
label?: string;
|
||||
error?: string;
|
||||
showPasswordStrength?: boolean;
|
||||
showPasswordToggle?: boolean;
|
||||
containerClassName?: string;
|
||||
errorClassName?: string;
|
||||
autoComplete?: "on" | "off";
|
||||
onPasswordChange?: (password: string) => void;
|
||||
onPasswordStrengthChange?: (strength: E_PASSWORD_STRENGTH) => void;
|
||||
}
|
||||
};
|
||||
|
||||
export function AuthPasswordInput({
|
||||
label = "Password",
|
||||
|
|
@ -35,7 +34,7 @@ export function AuthPasswordInput({
|
|||
onPasswordChange,
|
||||
onPasswordStrengthChange,
|
||||
...props
|
||||
}: AuthPasswordInputProps) {
|
||||
}: TAuthPasswordInputProps) {
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
|
@ -73,7 +72,7 @@ export function AuthPasswordInput({
|
|||
onChange={handleChange}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
autoComplete="on"
|
||||
autoComplete="off"
|
||||
/>
|
||||
{showPasswordStrength && value && isFocused && (
|
||||
<PasswordStrengthIndicator password={value as string} showCriteria />
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export { AuthConfirmPasswordInput } from "./auth-confirm-password-input";
|
|||
export { AuthForgotPassword } from "./auth-forgot-password";
|
||||
|
||||
export type { AuthFormProps, AuthFormData, AuthMode } from "./auth-form";
|
||||
export type { AuthInputProps } from "./auth-input";
|
||||
export type { AuthPasswordInputProps } from "./auth-password-input";
|
||||
export type { AuthConfirmPasswordInputProps } from "./auth-confirm-password-input";
|
||||
export type { TAuthInputProps } from "./auth-input";
|
||||
export type { TAuthPasswordInputProps } from "./auth-password-input";
|
||||
export type { TAuthConfirmPasswordInputProps } from "./auth-confirm-password-input";
|
||||
export type { AuthForgotPasswordProps } from "./auth-forgot-password";
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement>
|
|||
inputSize?: "xs" | "sm" | "md";
|
||||
hasError?: boolean;
|
||||
className?: string;
|
||||
autoComplete?: "on" | "off";
|
||||
}
|
||||
|
||||
const Input = React.forwardRef(function Input(props: InputProps, ref: React.ForwardedRef<HTMLInputElement>) {
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
*/
|
||||
|
||||
import { Eye, EyeClosed } from "lucide-react";
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { Tooltip } from "@plane/propel/tooltip";
|
||||
import { cn } from "@plane/utils";
|
||||
|
||||
interface PasswordInputProps {
|
||||
type TPasswordInputProps = {
|
||||
id: string;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
|
|
@ -17,7 +17,8 @@ interface PasswordInputProps {
|
|||
className?: string;
|
||||
showToggle?: boolean;
|
||||
error?: boolean;
|
||||
}
|
||||
autoComplete?: React.HTMLInputAutoCompleteAttribute;
|
||||
};
|
||||
|
||||
export function PasswordInput({
|
||||
id,
|
||||
|
|
@ -27,7 +28,8 @@ export function PasswordInput({
|
|||
className,
|
||||
showToggle = true,
|
||||
error = false,
|
||||
}: PasswordInputProps) {
|
||||
autoComplete = "off",
|
||||
}: TPasswordInputProps) {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
return (
|
||||
<div className="relative">
|
||||
|
|
@ -45,6 +47,7 @@ export function PasswordInput({
|
|||
className
|
||||
)}
|
||||
placeholder={placeholder}
|
||||
autoComplete={autoComplete}
|
||||
/>
|
||||
{showToggle && (
|
||||
<Tooltip tooltipContent={showPassword ? "Hide password" : "Show password"} position="top">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue