Symfony 5 LDAP JumpCloud Authentication - symfony

I am just trying to configure LDAP authentication using JumpCloud service.
JumpCloud is public LDAP server with web adminisration. For connectiong to LDAP I am using built-in modul and following this tutorial: http://symfony.com/doc/current/security/ldap.html
It seems the system will connect succesly on to LDAP but cannot authenticate users.
Output header:
Output header
Here are my settings:
config/services.yaml
Symfony\Component\Ldap\Ldap:
arguments: ['#Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
arguments:
- host: ldap.jumpcloud.com
port: 636
encryption: ssl
options:
protocol_version: 3
referrals: false
config/packages/security.yaml
providers:
my_ldap:
ldap:
service: Symfony\Component\Ldap\Ldap
base_dn: ou=Users,o=MY_ORG_ID,dc=jumpcloud,dc=com
default_roles: ROLE_USER
uid_key: uid
extra_fields: ['mail']
filter: ({uid_key}={username})
firewalls:
main:
anonymous: false
http_basic_ldap:
service: Symfony\Component\Ldap\Ldap
dn_string: 'uid=LDAP_ADMIN_USERNAME,ou=Users,o=MY_ORG_ID,dc=jumpcloud,dc=com'
search_password: 'LDAP_ADMIN_PASS'
Manual connection test:
$dn = "uid=LDAP_ADMIN_USERNAME,ou=Users,o=MY_ORG_ID,dc=jumpcloud,dc=com";
$password = "LDAP_ADMIN_PASS";
$ldap = Ldap::create('ext_ldap', ['connection_string' => 'ldaps://ldap.jumpcloud.com:636']);
$ldap->bind($dn, $password);
$query = $ldap->query('ou=Users,o=MY_ORG_ID,dc=jumpcloud,dc=com', '(objectClass=inetOrgPerson)');
$results = $query->execute();
This code have returned valid output:
array (size=3)
0 => object(Symfony\Component\Ldap\Entry)[5504]
private 'dn' => string 'uid=janakdom,ou=Users,o=MY_ORG_ID,dc=jumpcloud,dc=com' (length=68)
private 'attributes' => ..
1 => object(Symfony\Component\Ldap\Entry)[5093]
private 'dn' => string 'uid=ldapservice,ou=Users,o=MY_ORG_ID,dc=jumpcloud,dc=com' (length=71)
private 'attributes' => ...
2 => object(Symfony\Component\Ldap\Entry)[4926]
private 'dn' => string 'uid=test,ou=Users,o=MY_ORG_ID,dc=jumpcloud,dc=com' (length=64)
private 'attributes' => ...
A absolutely don't know where the problem could be. I tried everything what occurred to me. I also use oficial JumpCloud documentation
I would ask you for help.
Thank you very much
DJ

Full disclosure, I work for JumpCloud, in support for the last couple years, and in a technical editor capacity now. A couple of changes to your configuration may help:
1) Under "providers > my_ldap > ldap:", there is no "search_dn", which will need to be the service LDAP Bind DN created in JumpCloud and appears to have been configured under "security > firewalls > main > http_basic_ldap:" per the screenshot above as 'uid=LDAP_ADMIN_USERNAME,ou=users,o=,dc=jumpcloud,dc=com'.
2) Under "security > firewalls > main > http_basic_ldap:", the "dn_string" is used to construct the FUll LDAP Bind DN of the user being authenticated. Per the example in the documentation, this needs to be set with the proper syntax for value substitution as noted below.
'uid={username},ou=users,o=,dc=jumpcloud,dc=com'
Hope this helps -- if not, I would definitely suggest opening a case with support#jumpcloud.com.
Brandon

Related

JWTRefreshTokenBundle change user_identity_field Symfony 5.4 + ApiPlatform

I am using : Symfony 5.4 + ApiPlatform + JWTRefreshTokenBundle 1.1
JWTRefreshTokenBundle => https://github.com/markitosgv/JWTRefreshTokenBundle
I need to change this parameter "user_identity_field" but there is no way to change this :
I tried to change the Yaml =>
gesdinet_jwt_refresh_token:
user_identity_field: email
user_provider: app_user_provider
I tried to modify this function in my user provider (app_user_provider) entity User.php :
public function getUserIdentifier(): string
{
return (string) $this->id;
}
Right now the better I can get is to have the ID instead of the E-mail in the user name column in my database, but as soon as I try to refresh the token, I get this message => " 401 "Invalid credentials".
I am tried to have "ID" instead of "E-MAIL" as user_identity_field.
Has anyone found a solution ?
Thanks.
Sf 5,4+
#gesdinet_jwt_refresh_token.yaml
gesdinet_jwt_refresh_token:
user_identity_field: email
ttl: 2592000
firewall: login
user_provider: security.user.provider.concrete.app_user_provider
i think you need to change the app_user_provider in the security.yaml file :
app_user_provider:
entity:
class: App\Entity\User
property: id
jwt:
lexik_jwt:
class: App\Entity\User
i think the problem is : symfony try to authneticate user with the app_user_provider and you have a conflict because id's are in your JWT but framework search for email.
For verify that you can check your tokens on : https://jwt.io/
The JWTRefreshTokenBundle (gesdinet/jwt-refresh-token-bundle) is build upon the JWTAuthenticationBundle (lexik/jwt-authentication-bundle), which is the bundle that defines the user_identity_field configuration:
# config/packages/lexik_jwt_authentication.yaml
lexik_jwt_authentication:
user_identity_field: 'email'

syntax for token_provider in symfony remember_me

I'm building remember_me functionality in symfony. Instead of tokens being stored in cookies I want to store them in database So, I'm trying to use an option called token_provider but there is not much information detailed on Symfony.com.
I am new to Symfony, can any one share the syntax of "token_provider" in security.yml->firewalls->remember_me?
any help will be appreciated.
Changes I have done
Created a custom service which extends Symfony\Bridge\Doctrine\Security\RememberMe\DoctrineTokenProvider and passed the db connection object from the constructor
class CustomTokenService extends DoctrineTokenService
{
public function __construct(EntityManagerInterface $em){
parent::__construct($em->getConnection());
}
}
Registered this service in app/config/services.yml
custom service in services.yml:
token_service:
alias:{App}\Bundle\Services\Utilities\CustomTokenService
public: true
In Security.yml:
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
path: /
domain: ~
remember_me_parameter: _stay_signedin
token_provider: token_service

FR3DLdapBundle Login with email

I'm new on LDAP concept and i have to make a integration with LDAP and FosUserBundle.
I've installed both bundles, fosuser and FR3DLdapBundle, fosuser is working but i'm missing something about LDAP login.
I need to login with email.
I have the following config: http://pastebin.com/USkJqtbD
I'm using this website for tests: http://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/
I'm using email: riemann#ldap.forumsys.com and password: password
But i have the following error
[2015-05-18 16:36:58] ldap_driver.DEBUG: ldap_search(cn=read-only-admin,dc=example,dc=com, (&(objectClass=*)(uid=riemann#ldap.forumsys.com)), uid,mail) [] []
[2015-05-18 16:36:58] security.INFO: User riemann#ldap.forumsys.com not found on ldap [] []
Thank you in advance for you help
With the FR3D Ldap bundle the first attribute that you add in the attributes list is then one that it uses to search by.
In your config the first attribute is uid, so I would suspect that if you used the uid as the username then it would properly. To sort it you will just need to switch up the order so the your mail attribute is first in the list.
fr3d_ldap:
// ...
user:
// ...
attributes: # Specify ldap attributes mapping [ldap attribute, user object method]
- { ldap_attr: mail, user_method: setEmail } # Default
- { ldap_attr: uid, user_method: setUsername }
You have to adapt the search query for find by email.
https://github.com/Maks3w/FR3DLdapBundle/blob/master/Resources/doc/index.md#4-configure-configyml
# app/config/config.yml
fr3d_ldap:
driver:
accountFilterFormat: (&(email=%s)) # Optional. sprintf format %s will be the username

Set the display name using memory provider in Symfony2

I am currently trying to create some tests for an application, but I'm stuck on authentication.
In the app I use ldap authentication, which also determines the role of each user. It works well, but to simplify the testing (and to not use real users) I use the in_memory provider in my tests.
The problem is that in my views I use {{ app.user.displayname }}, and the display name is not available with the in_memory provider.
Is there a way to add it ? For example this solution (which does not work) would be perfect :
providers:
in_memory:
memory:
users:
john: { password: john, roles: 'ROLE_USER', displayname: 'John Doe' }
admin: { password: admin, roles: 'ROLE_ADMIN', displayname: 'Admin' }
You could either modify the class
src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php
so it uses the displayname as well or (even better) create your own class which will extend the InMemoryUserProvider and use your own provider (http://symfony.com/doc/current/cookbook/security/custom_provider.html)

Login in symfony2

I'm trying to implement very basic authentication in Symfony2. Here are main parts of the code I really don't see any problem
EDIT
complete security.yml
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
firewalls:
login:
pattern: ^/login
anonymous: ~
secured_area:
pattern: ^/
stateless: true
form_login:
login_path: /login
check_path: /login_check
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
This works fine, anonymous user is always redirected to loginAction controller.
EDIT
Here is the complete code
<?php
namespace AcmeBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
class SecurityController extends Controller {
public function loginAction() {
$providerKey = 'secured_area';
$token = new UsernamePasswordToken('test', 'test', $providerKey, array('ROLE_USER'));
$this->container->get('security.context')->setToken($token);
return $this->redirect($this->generateUrl('fronthomepage'));
}
}
I don't see any problem, anonymous user is redirected to loginAction, there is created authenticated user, saved to token and than redirected to secured area as an authenticated user. Unfortunately my code ends with redirect loop which looks like security firewall doesn't accept user as authenticated. Do you see any problem?
Well, your controller job is to render just form but not to populate security context. Symfony2 security firewall will do that for you automatically. You don't need to handle it unless you want to build you own custom authentication.
In other words, your job is to display the login form and any login
errors that may have occurred, but the security system itself takes
care of checking the submitted username and password and
authenticating the user.
Please read this document for clear picture.
If you want to do some custom stuff when a user logs in, in Symfony2 you have to add an event listener that will fire after the user successfully logged in. The event that is fired is security.interactive_login and to hook to it you have to specify this in services.yml file form your bundle Resources/config directory:
Pretty sure you need an actual user object before setting an authenticated user. I did something like this:
class BaseController
protected function setUser($userName)
{
if (is_object($userName)) $user = $userName;
else
{
$userProvider = $this->get('zayso_core.user.provider');
// Need try/catch here
$user = $userProvider->loadUserByUsername($userName);
}
$providerKey = 'secured_area';
$providerKey = $this->container->getParameter('zayso_core.provider.key'); // secured_area
$token = new UsernamePasswordToken($user, null, $providerKey, $user->getRoles());
$this->get('security.context')->setToken($token);
return $user;
}
However doing something like this bypasses much of the security system and is not recommended. I also wanted to use a 3rd party authentication system (Janrain). I looked at the authentication system and initially could not make heads or tails out of it. This was before the cookbook entry existed.
I know it seems overkill but once you work through things then it starts to make more sense. And you get access to a bunch of nifty security functions. It took me quite some time to start to understand the authentication system but it was worth it in the end.
Hints:
1. Work through the cook book backward. I had a real hard time understanding what was going on but I started with adding a new firewall to security.yml and then adding the alias for my security factory. I then sort of traced through what the factory was being asked to do. From there I got the listener to fire up and again traced through the calls. Finally the authentication manager comes into play. Again, time consuming, but worth it in the end. Learned a lot.
One thing that drove me crazy is that classes are scattered all over the place. And the naming leaves something to be desired. Very hard to get an overview. I ended up making my own authentication bundle then putting everything under security.
If you want another example of a working bundle then take a look at: https://github.com/cerad/cerad/tree/master/src/Cerad/Bundle/JanrainBundle

Resources