diff --git a/README.md b/README.md index c2e2fb0..23a7b43 100644 --- a/README.md +++ b/README.md @@ -217,5 +217,28 @@ If correct you'll receive: The response headers will include a secure cookie containing the JWT token to allow future authenticated calls. +## 2FA Remember this device + +The remember device functionality allows users to skip the 2fa for a configurable amount of days. The default configuration is set to false, which means it doesn't set a REMEMBER_DEVICE cookie after logging in. +The default amount of days is set to 30. + +To configure: + + +In the config/packages folder of the root project create a new file called: +`connect_holland_secure_jwt.yaml` + +In this file the configuration can be set: + +```yaml +connect_holland_secure_jwt: + is_remembered: true + expiry_days: 14 +``` + +As mentioned before, after logging in a REMEMBER_DEVICE cookie will be set. It will contain a unix expiry time and the email of the user. + +Besides placing the cookie it will be persisted in the: `secure_jwt_remember_device_token` table. This entity can be found in `src/Entity/RememberDeviceToken.php` + ## Recover codes You can retrieve recovery codes for 2FA which allow you to reset 2FA. If a valid recovery code is entered as `challenge`, 2FA will be reset and you'll get a QR code response. diff --git a/src/Entity/RememberDeviceToken.php b/src/Entity/RememberDeviceToken.php index 1acc059..a1ad0e9 100644 --- a/src/Entity/RememberDeviceToken.php +++ b/src/Entity/RememberDeviceToken.php @@ -30,7 +30,7 @@ class RememberDeviceToken private string $token; /** - * @ORM\Column(type="text") + * @ORM\Column(type="string", length=180) */ private string $username; diff --git a/tests/Security/Http/Authentication/AuthenticationSuccessHandlerTest.php b/tests/Security/Http/Authentication/AuthenticationSuccessHandlerTest.php index 0403df8..bac6aea 100644 --- a/tests/Security/Http/Authentication/AuthenticationSuccessHandlerTest.php +++ b/tests/Security/Http/Authentication/AuthenticationSuccessHandlerTest.php @@ -32,7 +32,7 @@ public function testOnAuthenticationSuccess(): void $request = $this->getRequest(); $token = $this->getToken(); - $response = (new AuthenticationSuccessHandler(new LexikAuthenticationSuccessHandler($this->getJWTManager('secrettoken'), $this->getDispatcher()), $this->getEncoder(), 'strict', $this->getFalseRememberDeviceResolver(), $this->getDoctrine())) + $response = (new AuthenticationSuccessHandler(new LexikAuthenticationSuccessHandler($this->getJWTManager('secrettoken'), $this->getDispatcher()), $this->getEncoder(), 'strict', $this->getRememberDeviceResolver(false), $this->getDoctrine())) ->onAuthenticationSuccess($request, $token); $this->assertInstanceOf(JsonResponse::class, $response); @@ -52,7 +52,7 @@ public function testOnAuthenticationSuccess(): void public function testHandleAuthenticationSuccess() { - $response = (new AuthenticationSuccessHandler(new LexikAuthenticationSuccessHandler($this->getJWTManager('secrettoken'), $this->getDispatcher()), $this->getEncoder(), 'strict', $this->getFalseRememberDeviceResolver(), $this->getDoctrine())) + $response = (new AuthenticationSuccessHandler(new LexikAuthenticationSuccessHandler($this->getJWTManager('secrettoken'), $this->getDispatcher()), $this->getEncoder(), 'strict', $this->getRememberDeviceResolver(false), $this->getDoctrine())) ->handleAuthenticationSuccess($this->getUser()); $this->assertInstanceOf(JsonResponse::class, $response); @@ -72,7 +72,7 @@ public function testHandleAuthenticationSuccess() */ public function testHandleAuthenticationSuccessWithGivenJWT(string $sameSite) { - $response = (new AuthenticationSuccessHandler(new LexikAuthenticationSuccessHandler($this->getJWTManager('secrettoken'), $this->getDispatcher()), $this->getEncoder(), $sameSite, $this->getFalseRememberDeviceResolver(), $this->getDoctrine())) + $response = (new AuthenticationSuccessHandler(new LexikAuthenticationSuccessHandler($this->getJWTManager('secrettoken'), $this->getDispatcher()), $this->getEncoder(), $sameSite, $this->getRememberDeviceResolver(false), $this->getDoctrine())) ->handleAuthenticationSuccess($this->getUser(), 'jwt'); $this->assertInstanceOf(JsonResponse::class, $response); @@ -95,7 +95,7 @@ public function testRememberDeviceCookieIsSetAfterAuthenticationSuccess() $request = $this->getRequest(); $token = $this->getToken(); - $response = (new AuthenticationSuccessHandler(new LexikAuthenticationSuccessHandler($this->getJWTManager('secrettoken'), $this->getDispatcher()), $this->getEncoder(), 'strict', $this->getTrueRememberDeviceResolver(), $this->getDoctrine())) + $response = (new AuthenticationSuccessHandler(new LexikAuthenticationSuccessHandler($this->getJWTManager('secrettoken'), $this->getDispatcher()), $this->getEncoder(), 'strict', $this->getRememberDeviceResolver(true), $this->getDoctrine())) ->onAuthenticationSuccess($request, $token); $this->assertInstanceOf(JsonResponse::class, $response); @@ -213,29 +213,18 @@ private function getDispatcher() return $dispatcher; } - private function getFalseRememberDeviceResolver() + private function getRememberDeviceResolver($status) { $rememberDeviceResolver = $this->createMock(RememberDeviceResolver::class); $rememberDeviceResolver ->expects($this->any()) ->method('getRememberDeviceStatus') - ->willReturn(false); + ->willReturn($status); return $rememberDeviceResolver; } - private function getTrueRememberDeviceResolver() - { - $rememberDeviceResolver = $this->createMock(RememberDeviceResolver::class); - - $rememberDeviceResolver - ->expects($this->any()) - ->method('getRememberDeviceStatus') - ->willReturn(true); - - return $rememberDeviceResolver; - } private function getDoctrine() {