Symfony 3: RememberMe Cookie is not set - symfony

In my Symfony 3 app I have my login page at the root url "/" (and therefor not "/login".
Unfortunately the app is not setting the REMEMBER_ME cookie although its properly configured in security.yml:
# To get started with security, check out the documentation:
# http://symfony.com/doc/current/book/security.html
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
dev:
pattern: ^/(_(profiler|wdt|error)|css|images|js)/
security: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
check_path: /login_check
login_path: /
default_target_path: /home
use_forward: false
failure_path: null
failure_handler: ccdn_user_security.component.authentication.handler.login_failure_handler
require_previous_session: false
logout:
path: /logout
target: /
security: true
anonymous:
secret: "%secret%"
remember_me:
secret: "%secret%"
lifetime: 604800 # 1 week in seconds
path: /
secure: true
switch_user: true
access_control:
- { path: ^/admin, role: ROLE_ADMIN,requires_channel: "%protocol%" }
- { path: ^/user, roles: ROLE_USER, requires_channel: "%protocol%"}
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: "%protocol%" }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: "%protocol%" }
- { path: ^/, role: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: "%protocol%" }
I don't have listeners setup of any kind which was something that this OP was running into:
Symfony2: remember me token is not set
I have adjusted the SecurityController of the FOSUserBundle as follows:
/**
* Controllers for Anonymous Index Page
*/
class SecurityController extends BaseController
{
/**
* #param Request $request
*
* #return Response
*/
public function loginAction(Request $request)
{
$securityContext = $this->container->get('security.authorization_checker');
if ( $securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED') or $securityContext->isGranted('IS_AUTHENTICATED_FULLY') ) {
return $this->redirect($this->generateUrl('home'));
}
$response = parent::loginAction($request);
return $response;
}
}
but as u can see this is just redirecting the user in case he is already logged in.
However the AuthenticationListener shipped with the FOSUserBundle never seems to be triggered.
Finally, in case u need it, this is my remember me widget in the login form:
<div class="checkbox checkbox-css m-b-30">
<input name="_remember_me" checked type="checkbox" id="remember_me_checkbox" />
<label for="remember_me_checkbox">Onthoudt mij</label>
</div>
Does anyone have an idea why the cookie is not being set?
The users are automatically logged out after 20 min or so. I guess this is because of the PHP session expiry?

Answer based on the comment section:
The secure: true means the cookie will only be sent over secure connection. You may want to remove this line, for testing purposes, or to check if your web server has been properly configured to handle https traffic.
Make sure you visit your app via https. I am not sure if self-signed cert could potentially have any impact on this. Based on Gumbo's answer from https://stackoverflow.com/a/9606871/662615, it should not have...
Another thing: in order to prevent premature logout, increase your session timeout instead. AFAIK, the remember_me only helps if user goes away during the session duration...
Hope this helps...

Related

API Platform - Swagger UI with JWT Authentication

I'd like to add the "Authorize" button on Swagger, like described here : https://api-platform.com/docs/core/jwt#documenting-the-authentication-mechanism-with-swaggeropen-api
I installed LexikJWTAuthenticationBundle, it works fine with Curl. But when I browse to http://localhost:8000/api, I only see {"code":401,"message":"JWT Token not found"}.
Am I missing something?
Here's my security.yaml:
security:
encoders:
App\Entity\User:
algorithm: bcrypt
providers:
db_provider:
entity:
class: App\Entity\User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api_login:
pattern: ^/api/login
stateless: true
anonymous: true
form_login:
check_path: /api/login_check
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
require_previous_session: false
api:
pattern: ^/api
stateless: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
main:
pattern: ^/
anonymous: ~
provider: db_provider
form_login:
login_path: app_security_login
check_path: app_security_login
csrf_token_generator: security.csrf.token_manager
logout:
path: /logout
target: /
remember_me:
secret: '%kernel.secret%'
lifetime: 604800
path: /
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
access_decision_manager:
strategy: unanimous
And my api_platform.yaml:
api_platform:
title: 'My project'
version: '0.0.1'
mapping:
paths: ['%kernel.project_dir%/src/Entity']
swagger:
api_keys:
apiKey:
name: Authorization
type: header
Bit late to this, but I faced this same issue. Your security configuration is stating that any route beginning with /api requires authentication, which includes /api itself. If you want to keep the documentation on the /api route, add a trailing slash to the security configuration;
firewalls:
...
api:
pattern: ^/api/
and
access_control:
- { path: ^/api/, roles: IS_AUTHENTICATED_FULLY }
This will leave /api as publicly accessible, whilst requiring a valid token to be provided for /api/*.
Alternatively, you can leave the security configuration as it is and move the documentation to a different URL (e.g. /docs). For this, you may need to add /docs as an IS_AUTHENTICATED_ANONYMOUSLY path under access_control depending on your other rules.
Then when the documentation page is accessible, click the Authorize button at the top of the page and enter Bearer <valid JWT token>.
It's old but here is the solution in 2021
You have to decorate open api factory
Edit :
Don't put hyphen (-) in the name of the authorization and in the scheme key otherwise it won't work (probably other special characters)
In config/packages/api_platform.yaml :
swagger:
versions: [3]
api_keys:
JWT: // The name of the authorization to display on swagger UI
name: Authorization
type: header
In config/services.yaml :
App\OpenApi\JwtDecorator:
decorates: 'api_platform.openapi.factory'
arguments: [ '#App\OpenApi\JwtDecorator.inner' ]
autoconfigure: false
enter code here
The decorating service : in OpenApi\JwtDecorator
class JwtDecorator implements OpenApiFactoryInterface
{
public function __construct(
private OpenApiFactoryInterface $decorated
) {}
public function __invoke(array $context = []): \ApiPlatform\Core\OpenApi\OpenApi
{
$openApi = ($this->decorated)($context);
$schemas = $openApi->getComponents()->getSecuritySchemes();
$schemas['JWT'] = new \ArrayObject([
'type' => 'http',
'scheme' => 'bearer',
'bearerFormat' => 'JWT'
]);
return $openApi;
}
}
I could fix my problem. In my case problem was, in public and private openssl keys. First I fixed it, the second, problem was in encoding. I used the source below to achieve result. Just take a look to link below
LexikJWTAuthenticationBundleSandbox

Redirect anonymous users from restricted areas in Symfony2

I've built a web app using Symfony 2.8 and I've now got to the task of separating the admin area from the front end. I have done that using the following code in the security.yml file:
security:
encoders:
MyApp\Bundle\CoreBundle\Entity\Users:
algorithm: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_BLOCKED
providers:
main:
entity: { class: MyApp\Bundle\CoreBundle\Entity\Users, property: username }
firewalls:
default:
anonymous: ~
secured_area:
pattern: ^/admin
anonymous: ~
access_denied_url: core_login
form_login:
check_path: core_login_check
login_path: core_login
failure_path: core_login
default_target_path: ^/admin/booking/today/
logout:
path: core_logout
target: core_login
access_control:
- { path: ^/admin, roles: 'ROLE_ADMIN' }
- { path: ^/ajax/admin, roles: 'ROLE_ADMIN' }
- { path: ^/ajax/backend, roles: 'ROLE_ADMIN' }
- { path: ^/, roles: 'IS_AUTHENTICATED_ANONYMOUSLY' }
This is working for me in terms of blocking access to the areas I want. However, if the anonymous user tries to access /admin I get the following message:
Full authentication is required to access this resource.
When I do this in the production environment, I just get the standard 500 error.
What I want to have happen is the user be redirected to the login page. This isn't happening at the moment, so what can I do to acheive this?

Symfony login redirects on itself

When I try and login, the page keeps redirecting on itself. This is the Firefox error I get:
The page isn't redirecting properly
Firefox has detected that the server is redirecting the request for
this address in a way that will never complete.
Any ideas what could be causing it?
SECURITY.YML:
security:
encoders:
FixedApp\Model\User:
algorithm: sha1
encode_as_base64: false
iterations: 1
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_LIMITED_ADMIN]
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
administrators:
entity: { class: FixedApp\Model\User, property: username }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/$
security: false
secured_area:
pattern: ^/
form_login:
check_path: fixed_app_authentication_login
login_path: fixed_app_authentication_homepage
username_parameter: username
password_parameter: password
default_target_path: fixed_app_authentication_homepage
always_use_default_target_path: true
success_handler: security.authentication.success_handler
logout:
path: fixed_app_authentication_logout
target: fixed_app_homepage
# To give access to the ROLE_LIMITED_ADMIN, use - role: [ROLE_USER, ROLE_LIMITED_ADMIN]
access_control:
- { path: ^/log-in$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /home, roles: ROLE_USER }
ROUTING.YML:
fixed_app_homepage:
pattern: /
defaults: { _controller: FixedAppAuthenticationBundle:Default:index }
fixed_app_authentication_homepage:
pattern: /home
defaults: { _controller: FixedAppAuthenticationBundle:Default:loggedIn }
fixed_app_authentication_logout:
path: /log-out
# Verify the log in
fixed_app_authentication_login:
pattern: /log-in
AUTHENTICATIONSUCCESSHANDLER.PHP
It makes no difference if I comment the return line out though.
function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
return new RedirectResponse($this->router->generate('fixed_app_authentication_homepage'));
}
form_login:
login_path: fixed_app_authentication_homepage
Is not where you redirect to after login but in fact where you login from and it has to allow anonymous users as you get redirected there on authentication fail. So if you're seeing an authentication fail you'll get that endless redirect behaviour.
You need to allow it to be IS_AUTHENTICATED_ANONYMOUSLY
E.g.
- { path: /home, roles: IS_AUTHENTICATED_ANONYMOUSLY }
If that's not what you intended, you need to make a separate page for login_path and then redirect to your secure /home page on success.

Symfony2 how to invalidate all the session attributes

In my Symfony2 project i have a logout button which redirect to the index page but when i click the Login button it connects directly without asking me for user and password.
how can i validate all session attributes, so if i login again it should ask me for user and password
this is my logout Action:
public function logoutAction(Request $request)
{
$this->get('security.context')->setToken(null);
$this->get('request')->getSession()->invalidate();
$url = $this->generateUrl('my_route');
$response = new RedirectResponse($url);
$response->headers->clearCookie('PHPSESSID');
$response->send();
return $response;
}
here's the security.yml:
security:
encoders:
Envivio\UserBundle\Entity\User: sha512
role_hierarchy:
ROLE_USER: ROLE_USER
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ]
providers:
mine:
id: ib_user.oauth_user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
pattern: ^/
oauth:
resource_owners:
salesforce: "/login/check-salesforce"
login_path: /login
#use_forward: false
failure_path: /login
default_target_path: /upload
oauth_user_provider:
service: ib_user.oauth_user_provider
remember_me:
key: "%secret%"
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, role: ROLE_ADMIN }
You can try :
$this->get('session')->clear();
or
$session = $this->get('session');
$ses_vars = $session->all();
foreach ($var as $key => $value) {
$session->remove($key);
}
It may also be a cookie problem check your cookies in the response->headers then try clearing it with that function :
http://api.symfony.com/2.3/Symfony/Component/HttpFoundation/ResponseHeaderBag.html#method_clearCookie
Edit :
Since you have remember me enabledyou need to clear that cookie too otherwise the next request you do will reauthenticate the user, you can specify a name for the cookie :
#security.yml
remember_me:
name: "%session.remember_me.name%"
add in parameters.yml the name of the cookie
parameters:
session.remember_me.name: EXTSESS
then in your controller logout action :
$response = $this->redirectToRoute('homepageroute'); //redirect prepare the route to redirect
$this->get('security.context')->setToken(null);
$this->get('request')->getSession()->invalidate();
$remember_sess_name = $this->container->getParameter('session.remember_me.name');
$response->headers->clearCookie($remember_sess_name);
return $response;
it should work now. if this doesn't then ALT+F4 :D
You don't need to do it manually. The Symfony2 firewall can perform a logout like this:
# app/config/security.yml
security:
firewalls:
secured_area:
# ...
logout:
path: /logout
target: /
# ...
Next, you'll need to create a route for this URL (but not a
controller):
# app/config/routing.yml
logout:
path: /logout
And that's it! By sending a user to /logout (or whatever you configure
the path to be), Symfony will un-authenticate the current user.
Once the user has been logged out, they will be redirected to whatever
path is defined by the target parameter above (e.g. the homepage).
Link to the related doc: http://symfony.com/doc/current/book/security.html#logout

Two different login forms in Symfony 2

Background
According to the Symfony documentation the login form needs to be specified on the security.yml file, also hes login_check path. Until now my app is working fine, users tries to access a secure page (mysite.com/edit/123) next if they are not logged they will be redirected to /login and after they login they will be redericted again to the original intended path (/edit/123).
Similar question: Two separate login pages in Symfony 2
Problem
The problem now is, i need a different login form, lets say /minimal_login, i need to include that on the security.yml but the only way i know is creating a different firewall, and as i saw on the documentation this creates a separate identification scheme, so i suppose users logged by differents firewall can not share the same secured pages, and thats not what i want.
What is need
If the user tries to access any secure page but /popup they will be redirected to /login, BUT if they tries to access /popup (and they are not logged) they will be redirected to /minimal_login. And no matter how the user logs into my app, they will always share the same access, i mean, if they log in using /login or /minimal_login they can access the same pages.
My secuity.yml
jms_security_extra:
secure_all_services: false
expressions: true
security:
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ]
providers:
main:
entity: {class: Done\PunctisBundle\Entity\User, property: username}
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
remember_me:
key: %secret%
lifetime: 3600
path: /
domain: ~
pattern: ^/
anonymous: ~
form_login:
login_path: /login
check_path: /login_check
logout:
path: /logout
target: /
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/signup, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/verification, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/popup/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/ajax/track, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/ajax/socialbox, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
encoders:
Done\PunctisBundle\Entity\User:
algorithm: md5
iterations: 1
encode_as_base64: false
I faced a similar problem and I solved using the firewall context configuration.
firewalls:
somename:
# ...
context: my_context
othername:
# ...
context: my_context
http://symfony.com/doc/current/reference/configuration/security.html#firewall-context

Resources