Skip to content

Commit

Permalink
fix: improve default password policy to follow latest OWASP recommend…
Browse files Browse the repository at this point in the history
…ations

fixes AM-526

(cherry picked from commit 4dcaf23)

# Conflicts:
#	gravitee-am-test/specs/gateway/login-flow.jest.spec.ts
#	gravitee-am-test/specs/gateway/remember-me.jest.spec.ts
  • Loading branch information
leleueri authored and mergify[bot] committed Nov 28, 2023
1 parent 5e29308 commit 8097483
Show file tree
Hide file tree
Showing 13 changed files with 452 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -258,17 +258,17 @@ user:
password:
policy:
# Regex pattern for password validation (default to OWASP recommendations).
# 8 to 32 characters, no more than 2 consecutive equal characters, min 1 special characters (@ & # ...), min 1 upper case character.
pattern: ^(?:(?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))(?!.*(.)\1{2,})[A-Za-z0-9!~<>,;:_\-=?*+#."'&§`£€%°()\\\|\[\]\-\$\^\@\/]{8,32}$
# Example : ^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}$
# ^ # start-of-string
#(?=.*[0-9]) # a digit must occur at least once
#(?=.*[a-z]) # a lower case letter must occur at least once
#(?=.*[A-Z]) # an upper case letter must occur at least once
#(?=.*[@#$%^&+=]) # a special character must occur at least once
#(?=\S+$) # no whitespace allowed in the entire string
#.{8,} # anything, at least eight places though
#$ # end-of-string
# Password must be at least 12 characters long, contain at least one digit, one upper case letter, one lower case letter, one special character, and no more than 2
pattern: ^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!~<>.,;:_=?/*+\-#\"'&§`£€%°()|\[\]$^@])(?!.*(.)\1{2,}).{12,128}$
# Example : ^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!~<>.,;:_=?/*+\-#\"'&§`£€%°()|\[\]$^@])(?!.*(.)\1{2,}).{12,128}$
# ^ # start-of-string
#(?=.*[0-9]) # a digit must occur at least once
#(?=.*[A-Z]) # an upper case letter must occur at least once
#(?=.*[a-z]) # a lower case letter must occur at least once
#(?=.*[!~<>.,;:_=?/*+\-#\"'&§`£€%°()|\[\]$^@]) # a special character must occur at least once
#((?!.*(.)\1{2,}) # no more than 2 consecutive equal characters
#.{12,128} # anything, between 12 and 128 characters
#$ # end-of-string

## Password dictionary to exclude most commons passwords
## You need to enable the feature in the AM management console
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,17 +311,17 @@ user:
password:
policy:
# Regex pattern for password validation (default to OWASP recommendations).
# 8 to 32 characters, no more than 2 consecutive equal characters, min 1 special characters (@ & # ...), min 1 upper case character.
pattern: ^(?:(?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))(?!.*(.)\1{2,})[A-Za-z0-9!~<>,;:_\-=?*+#."'&§`£€%°()\\\|\[\]\-\$\^\@\/]{8,32}$
# Example : ^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}$
# ^ # start-of-string
#(?=.*[0-9]) # a digit must occur at least once
#(?=.*[a-z]) # a lower case letter must occur at least once
#(?=.*[A-Z]) # an upper case letter must occur at least once
#(?=.*[@#$%^&+=]) # a special character must occur at least once
#(?=\S+$) # no whitespace allowed in the entire string
#.{8,} # anything, at least eight places though
#$ # end-of-string
# Password must be at least 12 characters long, contain at least one digit, one upper case letter, one lower case letter, one special character, and no more than 2
pattern: ^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!~<>.,;:_=?/*+\-#\"'&§`£€%°()|\[\]$^@])(?!.*(.)\1{2,}).{12,128}$
# Example : ^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!~<>.,;:_=?/*+\-#\"'&§`£€%°()|\[\]$^@])(?!.*(.)\1{2,}).{12,128}$
# ^ # start-of-string
#(?=.*[0-9]) # a digit must occur at least once
#(?=.*[A-Z]) # an upper case letter must occur at least once
#(?=.*[a-z]) # a lower case letter must occur at least once
#(?=.*[!~<>.,;:_=?/*+\-#\"'&§`£€%°()|\[\]$^@]) # a special character must occur at least once
#((?!.*(.)\1{2,}) # no more than 2 consecutive equal characters
#.{12,128} # anything, between 12 and 128 characters
#$ # end-of-string

## Password dictionary to exclude most commons passwords
## You need to enable the feature in the AM management console
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class PasswordSettings {
/**
* See https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
*/
public static final int PASSWORD_MAX_LENGTH = 64;
public static final int PASSWORD_MAX_LENGTH = 128;
public static final int PASSWORD_MIN_LENGTH = 8;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
@Component("defaultPasswordValidator")
public class DefaultPasswordValidatorImpl implements PasswordValidator {

private static final String DEFAULT_PASSWORD_PATTERN_VALUE = "^(?:(?=.*\\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))(?!.*(.)\\1{2,})[A-Za-z0-9!~<>,;:_\\-=?*+#.\"'&§`£€%°()\\\\\\|\\[\\]\\-\\$\\^\\@\\/]{8,32}$";
private static final String DEFAULT_PASSWORD_PATTERN_VALUE = "^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!~<>.,;:_=?/*+\\\\-#\\\\\\\"'&§`£€%°()|\\\\[\\\\]$^@])(?!.*(.)\\\\1{2,}).{12,128}$";

private static final String MESSAGE = "Field [password] is invalid";
private static final String ERROR_KEY = "invalid_password_value";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Copyright (C) 2015 The Gravitee team (http://gravitee.io)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.gravitee.am.service.validators;

import io.gravitee.am.service.validators.password.PasswordValidator;
import io.gravitee.am.service.validators.password.impl.DefaultPasswordValidatorImpl;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* @author Eric LELEU (eric.leleu at graviteesource.com)
* @author GraviteeSource Team
*/
public class DefaultPasswordValidatorTest {
@ParameterizedTest
@MethodSource("providerValidatePassword")
void validatePassword(String password, boolean expected) {
PasswordValidator validator = new DefaultPasswordValidatorImpl(
"^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!~<>.,;:_=?/*+\\-#\\\"'&§`£€%°()|\\[\\]$^@])(?!.*(.)\\1{2,}).{12,128}$"
);
assertEquals(expected, validator.validate(password));
}

private static Stream<Arguments> providerValidatePassword() {
return Stream.of(
Arguments.of("a1!atjubclzf", false),
Arguments.of("A1!ABVREFAGD", false),
Arguments.of("Aa!AHYaeffSF", false),
Arguments.of("AaBbCcDd1324", false),
Arguments.of("Aa1!", false),
Arguments.of("Password12!", false),
Arguments.of("Passsword123!", false),
Arguments.of("Password123!!!", false),
Arguments.of(
"MA48*xP:344MA48*xP:344MA48*xP:344MA48*xP:344MA48*xP:344MA48*xP:344MA48*xP:344MA48*xP:344MA48*xP:344MA48*xP:344MA48*xP:344MA48*xPz:",
false
),
Arguments.of("Password1231!", true),
Arguments.of("Password123!2£1", true),
Arguments.of("MA48*xP:344d", true),
Arguments.of("Ab0!~<>,;:_-=?*+#.\"'&§`€%°()|[]$^@", true),
Arguments.of("SomeP@ssw0rd", true)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ describe('AM - User Pre-Registration - Reset Password to confirm', () => {
expect(confirmationLink).toBeDefined();
await clearEmails();

await resetPassword(confirmationLink, 'Test123!');
await resetPassword(confirmationLink, 'SomeP@ssw0rd');
});

it('must be enabled', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ let openIdConfiguration;
let application;
let user = {
username: 'SelfAccountUser',
password: 'Test123!',
password: 'SomeP@ssw0rd',
firstName: 'SelfAccount',
lastName: 'User',
email: '[email protected]',
Expand Down Expand Up @@ -135,7 +135,7 @@ describe('SelfAccount - Change Password', () => {
describe('With default settings', () => {
describe('End User', () => {
it('must be able to change his password', async () => {
user.password = 'Test1234!!';
user.password = 'SomeP@ssw0rd!';

await performPost(
`${process.env.AM_GATEWAY_URL}/${domain.hrid}/account/api/changePassword`,
Expand Down
2 changes: 1 addition & 1 deletion gravitee-am-test/specs/gateway/enduser-logout.jest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ let openIdConfiguration;
let application;
let user = {
username: 'LogoutUser',
password: 'Test123!',
password: 'SomeP@ssw0rd',
firstName: 'Logout',
lastName: 'User',
email: '[email protected]',
Expand Down
2 changes: 1 addition & 1 deletion gravitee-am-test/specs/gateway/flow-execution.jest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ let openIdConfiguration;
let application;
let user = {
username: 'FlowUser',
password: 'Test123!',
password: 'SomeP@ssw0rd',
firstName: 'Flow',
lastName: 'User',
email: '[email protected]',
Expand Down
16 changes: 16 additions & 0 deletions gravitee-am-test/specs/gateway/login-flow.jest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ beforeAll(async () => {
});

describe('multiple user', () => {
<<<<<<< HEAD
const contractValue = '1234';
let user1;
const user1Password = 'Zxc123!!';
Expand All @@ -70,6 +71,21 @@ describe('multiple user', () => {
let user6;
const secondCommonPassword = 'Phd123!!';
const secondCommonEmail = '[email protected]';
=======
const contractValue = '1234';
let user1;
const user1Password = 'ZxcPrm7123!!';
let user2;
const commonPassword = 'AsdPrm7123!!';
const commonEmail = '[email protected]';
let user3; //user3 has same password as user2
let user4;
const user4Password = 'QwePrm7123!!';
let user5;
let user6;
const secondCommonPassword = 'PhdPrm7123!!';
const secondCommonEmail = '[email protected]';
>>>>>>> 4dcaf234bb (fix: improve default password policy to follow latest OWASP recommendations)

beforeAll(async () => {
user1 = await createUser(domain.id, accessToken, {
Expand Down
Loading

0 comments on commit 8097483

Please sign in to comment.