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
Related
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...
With sf3
symfony 3 password can be checked but with a static dn
dn_string: 'uid={username},dc=example,dc=com'
So I created my own UserAuthenticationProvider class
But now I don't know how to declare it in my security.yml ?
security.yml
providers:
your_db_provider:
entity:
class: AcSecurityBundle:User
property: username
fos_userbundle:
id: fos_user.user_provider.username
secured_area:
pattern: ^/
anonymous: true
provider: your_db_provider
form_login:
csrf_token_generator: security.csrf.token_manager
use_referer: true
form_login_ldap:
service: ldap
use_referer: true
logout: true
AcSecurityBundle/AcUserAuthenticationProvider.php
class AcUserAuthenticationProvider extends UserAuthenticationProvider
{
function checkAuthentication(UserInterface $user, UsernamePasswordToken $token)
{
$username = $token->getUsername();
$password = $token->getCredentials();
if ('' === $password) {
throw new BadCredentialsException('The presented password must not be empty.');
}
try {
$query = "(sAMAccountName=$username)";
$search_dn = "CN=app,OU=apps,DC=domain,DC=be";
$search_password = "mdp";
$this->ldap->bind($search_dn, $search_password);
$t = $this->ldap->query("OU=At,OU=user,DC=domain,DC=be", $query);
$entry = $t->execute();
if ($entry->count() > 0) {
$dn = $entry[0]->getDn();
}
$this->ldap->bind($dn, $password);
} catch (ConnectionException $e) {
throw new BadCredentialsException('The presented password is invalid.');
}
}
}
Thank you
Since Symfony 3.1 Symfony uses a new ldap provider
Symfony\Component\Ldap\Ldap
Provider Example:
services:
app.ldap:
class: Symfony\Component\Ldap\Ldap
factory: [ 'Symfony\Component\Ldap\Ldap', 'create']
arguments:
- ext_ldap
- host: srv-host
#debug: true
The string associated to the adapter you wish to use. Only one is
supported for now, which is ext_ldap.
New Ldap provider by Symfony, explained.
Security Provider Example:
providers:
#webservice_provider:
#id: app.webservice_user_provider
company_ldap:
ldap:
service: app.ldap
base_dn: DC=example, DC=local
search_dn: "CN=AdminName,OU=YourAdminGroup,DC=example,DC=LOCAL"
search_password: 'AdminPass'
default_roles: ROLE_USER
Now you are allowed to look in your ldap system. If you set your
form_login_ldap right, your users can authenticate via your form
Security form_login_ldap Example:
form_login_ldap:
provider: company_ldap
service: app.ldap #system/provider your user authenticate to
dn_string: '{username}#example.local'
csrf_token_generator: security.csrf.token_manager
check_path: /login_check #make sure the check is behind the firewall
login_path: /login #make sure login IS_AUTHENTICATED_ANONYMOUSLY
logout:
path: /logout #logout path
target: /login #after logout redirect to login
anonymous: true
Access_control/firewall Example:
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
- { path: ^/, role: ROLE_USER } #all pages require user to be logged in
Now you have your dynamic ldap login form.
Symfony login form setup.
Hope this helps you. Took me 8 days to figure this out by myself.
You don't need to do any of the above. You can use the DN string as:
dn_string: '{username}'
That's actually the default value according to the docs.This will work because AD supports several bind methods in addition to a full DN (such as the sAMAccountName or UPN).
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.
After login failure, the application does not redirect to the login page.Here is my security.yml configuration:
security:
encoders:
Acme\SecurityBundle\Entity\Users: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
providers:
main:
entity: { class: Acme\SecurityBundle\Entity\Users}
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login$
security: false
secured_area:
pattern: ^/admin/
form_login:
check_path: /login_check
login_path: /login
logout:
path: /logout
target: /home
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
Here is my controller:
class LoginController extends Controller {
/**
* #Route("/login",name="login")
*/
public function loginAction() {
//displays login form and renders the login.html.twig
}
/**
* #Route("/login_check", name="login_check")
*/
public function loginCheckAction() {
// The security layer will intercept this request
}
After login failure I get error as :
The controller must return a response (null given). Did you forget to add a return statement somewhere in your controller?
500 Internal Server Error - LogicException
I tried the login section inside the Demo that ships with symfony. I found the same result.
What modification should I have to make in order redirect to login form after login failure ?
You don't need to create a controller class for the login and logout actions. You just need to specify those routes inside of routing.yml, something like:
login_path:
pattern: /login
login_check_path:
pattern: /admin/login_check
logout_path:
pattern: /admin/logout
These routes are automatically handled by the security component.
In the firewall configuration, your check_path should be defined as /admin/login_check. The logout path should be /admin/logout.
I have two tables in this project of mine. One table is for the site admin which stores all the admin users details, and the other table stores all the login data for clients to the site.
At the moment, I can log in using the admin details fine. However, I am now trying to login with the client details and it doesn't seem to be working. So far, when a user clicks on a link it will go to /clientarea/login. This page loads up fine. But when I try to log in I get an error.
The error I am getting is this:
Unable to find the controller for path "/clientarea/login_check". Maybe you forgot to add the matching route in your routing configuration?
In my security.yml file, I have the following code: (By the way, I'm using plaintext for development only, it will be changed when it goes live):
providers:
admin_db:
entity: { class: Shout\AdminBundle\Entity\User, property: username }
client_db:
entity: { class: Shout\AdminBundle\Entity\Userclients, property: username }
encoders:
Shout\AdminBundle\Entity\User:
algorithm: plaintext
Shout\AdminBundle\Entity\Userclients:
algorithm: plaintext
firewalls:
secured_area:
pattern: ^/
anonymous: ~
provider: admin_db
form_login:
check_path: /login_check
login_path: /login
logout:
path: /logout
target: /index
client_area:
pattern: ^/
anonymous: ~
provider: client_db
form_login:
check_path: /clientarea/login_check
login_path: /clientarea/login
logout:
path: /clientarea/logout
target: /index
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/clientarea/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/clientarea, roles: ROLE_USER }
In my routing.yml I have this code:
login:
pattern: /login
defaults: { _controller: ShoutAdminBundle:Security:login }
login_check:
pattern: /login_check
logout:
pattern: /logout
clientlogin:
pattern: /clientarea/login
defaults: { _controller: ShoutAdminBundle:Security:clientlogin }
clientlogin_check:
pattern: /clientarea/login_check
clientlogout:
pattern: /clientarea/logout
Here is the code in the controller. The code is identical for the login and clientlogin functions, the only thing that is different is the twig file they point to:
$request = $this->getRequest();
$session = $request->getSession();
// get the login error if there is one
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} else {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
}
return $this->render('ShoutAdminBundle:Security:clientlogin.html.twig', array(
// last username entered by the user
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
));
The action path of the Client Login form points to clientlogin_check.
What am I doing wrong?
I've managed to get it working, but in a very basic way. I don't have time due to a deadline to make the login pages pretty looking.
But here is the code:
client_area:
pattern: ^/clientarea
anonymous: ~
provider: client_db
http_basic:
realm: "Secured Client Area"
Basically, you can have users from more than one table. However, I have still been unable to make it work using a proper login form. But the basic HTTP login box works just as well for what I'm doing.