Zend LDAP authentication - How to setIdentity and getIdentity - php

I am using adldap library to authenticate users against Active Directory. Below is the piece of code I use to authenticate
$username = $_POST['username'];
$password = $_POST['password'];
require_once '/adlap/adLDAP.php';
try {
$adldap = new adLDAP();
}
catch (adLDAPException $e) {
echo $e;
exit();
}
$authUser = $adldap->user()->authenticate($username, $password);
How should I setIdentity for the user?
In Login system where we store username and password we can setIdentity as mentioned below
$adapter = $this->_getAuthAdapter();
$adapter->setIdentity($values['username']);
$adapter->setCredential($values['password']);
protected function _getAuthAdapter() {
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('users')
->setIdentityColumn('username')
->setCredentialColumn('password')
->setCredentialTreatment('SHA1(CONCAT(?,salt))');
return $authAdapter;
}
I am not storing password in Database and checking it directly against Active Directory. So I couldn't use the above solution.
How shall I setIdentity of users so that I can check if user hasIdentity() like this
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()){
}
I referred the following Stackoverflow question
Get display name for Zend LDAP Authentication.
However I am not sure how we shall "get('LDAP_host')" Zend Registry and how should we set it before. Below is the line of code I'm confused with
'host' => Zend_Registry::get('LDAP_host'),
Can someone please help me?

Zend_Registry::get('LDAP_host') simply returnes the hostname of your LDAP-Server. Somewhere before that line of code you will find a line similar to Zend_Registry::set('LDAP_host', 'ldap.example.com') which sets ldap.example.com as LDAP-server.
getAuthAdapter() in your case returns an instance of Zend_Auth_Adapter_DbTable but you want an instance of Zend_Auth_Adapter_Ldap. So you will have to either call a different method/function getLdapAuthAdapter() or rewrite the current method.
public function getLdapAuthAdapter() {
return new Zend_Auth_Adapter_Ldap(array(
'host' => 'ldap.example.com',
'accountDomainName' => 'example.com',
'accountDomainNameShort' => 'EXAMPLE',
'accountCanonicalForm' => 3,
'username' => "CN=user1,DC=example,DC=com",
'password' => 'pass1',
'baseDn' => "DC=example,DC=com",
'bindRequiresDn' => true,
));
}
$adapter = $this->getLdapAuthAdapter();
$adapter->setIdentity($values['username']);
$adapter->setCredential($values['password']);
$result = $adapter->authenticate();
Hope that somehow helps.

Related

Which Active Directory's attribute corresponds to the "bind_password" parameter of the ldap_bind function in PHP

I am creating an API for registration and authentication by Active Directory.
When registering, I use the "userPassword" field to store the password.
$user = new User([
'cn' => $full_name,
'userPassword' => $password,
'samaccountname' => $username,
'mail' => $email
]);
$user->inside(config('ldap.connections.default.base_dn'));
$user->save();
Registration works fine.
But at the time of authentication, the Active Directory does not recognize the provided password:
$user = User::where('samaccountname', '=', $username)->firstOrFail(); // all is good here. print_r($user) shows user details
if (Container::getDefaultConnection()->auth()->attempt($user['distinguishedname'], $password)) {
// returns a response to the user
return \response()->json(
new UserResource($user), 200
);
} else {
return \response()->json(
[
'message' => 'invalid credentials or user not exists.'
], 403
);
}
Can someone help me.
Using plain stored password won't work, there are some encoding which need to be carried out but there's a mutator unicodePwd that will handle it for you. Try
$user = new User([
'cn' => $full_name,
'unicodePwd ' => $password,
'samaccountname' => $username,
'mail' => $email
]);
The attribute used to set the password of an account is unicodePwd. This attribute can only be set, not read.
There are some strict requirements about the format of what you put there, which are described in the Microsoft documentation. However, the LdapRecord library handles that for you, according to their documentation:
The password string you set on the users unicodePwd attribute is automatically encoded, you do not need to encode it yourself.
Their example on how to create an AD user looks like this:
$user = (new User)->inside('ou=Users,dc=local,dc=com');
$user->cn = 'John Doe';
$user->samaccountname = 'jdoe';
$user->unicodePwd = 'SecretPassword';
$user->userPrincipalName = 'jdoe#acme.org';
$user->save();
// Enable the user.
$user->userAccountControl = 512;
try {
$user->save();
} catch (\LdapRecord\LdapRecordException $e) {
// Failed saving user.
}

Instagram private InstagramAPI\Instagram::_setUser() error

I'm trying to implementing https://github.com/mgp25/Instagram-API on laravel and after successful login in Instagram i must to use _setUser to use exiting data after login, for example:
public function check()
{
$username = 'XXX';
$password = 'XXX';
$ig = new Instagram();
try {
$ig->_setUser($username, $password);
} catch (\Exception $e) {
echo 'Something went wrong: '.$e->getMessage()."\n";
exit(0);
}
}
in this code i get this error:
"Call to protected method InstagramAPI\Instagram::_setUser() from context 'App\Http\Controllers\InstagramController'"
This _setUser method used to be public in previous versions. The developers of the API seem to be recommending that you use login() function for every call and it will check if a new full login needs to be done, if it does not need to be done, _setUser will be called.
In the past doing a login() for every request was very slow, but seems to be much better now with newer versions of the private API.
For login, you can use this snippet:
$username = 'password';
$password = 'username';
$instagram = new Instagram(false, true, [
'storage' => 'mysql',
'dbhost' => 'localhost',
'dbname' => 'sessions',
'dbusername' => 'root',
'dbpassword' => '',
]);
$instagram->login($username, $password);
and for access user id you can do this:
$instagram->people->getUserIdForName($username);
and after you successfully logged in, try this one for accessing current user:
$instagram->account->getCurrentUser()->getUser();
The _setUser Function is Private, You can Edit Private to Public function then only you can use the function, and even if you don't change it will take automatically _setUser Method because of session store in Folder is Active. You can check Below
protected function _login(
$username,
$password,
$forceLogin = false,
$appRefreshInterval = 1800)
{
if (empty($username) || empty($password)) {
throw new \InvalidArgumentException('You must provide a username and password to _login().');
}
// Switch the currently active user/pass if the details are different.
if ($this->username !== $username || $this->password !== $password) {
$this->_setUser($username, $password);
}
// Perform a full relogin if necessary.
if (!$this->isMaybeLoggedIn || $forceLogin) {
$this->_sendPreLoginFlow();
try {
$response = $this->request('accounts/login/')
->setNeedsAuth(false)
->addPost('phone_id', $this->phone_id)
->addPost('_csrftoken', $this->client->getToken())
->addPost('username', $this->username)
->addPost('adid', $this->advertising_id)
->addPost('guid', $this->uuid)
->addPost('device_id', $this->device_id)
->addPost('password', $this->password)
->addPost('login_attempt_count', 0)
->getResponse(new Response\LoginResponse());
} catch (\InstagramAPI\Exception\InstagramException $e) {
if ($e->hasResponse() && $e->getResponse()->isTwoFactorRequired()) {
// Login failed because two-factor login is required.
// Return server response to tell user they need 2-factor.
return $e->getResponse();
} else {
// Login failed for some other reason... Re-throw error.
throw $e;
}
}
$this->_updateLoginState($response);
$this->_sendLoginFlow(true, $appRefreshInterval);
// Full (re-)login successfully completed. Return server response.
return $response;
}
// Attempt to resume an existing session, or full re-login if necessary.
// NOTE: The "return" here gives a LoginResponse in case of re-login.
return $this->_sendLoginFlow(false, $appRefreshInterval);
}

Unable to get User Credential grant type working

I have a Laravel 4.2 app that I have successfully implemented Authorization Code using oauth2-server-php. However, I can't seem to get User Credential grants working.
Here's my code setting up the oauth server:
App::singleton(
'oauth2',
function () {
$host = Config::get('database.connections.mongodb.host');
$hosts = is_array($host) ? $host : [$host];
$dbName = Config::get('database.connections.mongodb.database');
$dbOptions =
empty( Config::get('database.connections.mongodb.options') ) ? [] : Config::get(
'database.connections.mongodb.options'
);
$mongo = new MongoClient('mongodb://' . implode(',', $hosts) . '/' . $dbName, $dbOptions);
$storage = new OAuth2\Storage\Mongo($mongo->{$dbName});
$server = new OAuth2\Server(
$storage, [
'always_issue_new_refresh_token' => true,
'refresh_token_lifetime' => 2419200,
]
);
$userStorage = new \Medusa\Oauth\Storage\MedusaUserCredentials();
$server->addStorage($userStorage, 'users');
$userCredentialGrant = new Oauth2\GrantType\UserCredentials($userStorage);
$server->addGrantType(new OAuth2\GrantType\AuthorizationCode($storage));
$server->addGrantType(new OAuth2\GrantType\ClientCredentials($storage));
$server->addGrantType($userCredentialGrant);
$server->addGrantType(new OAuth2\GrantType\RefreshToken($storage));
return $server;
}
);
MedusaUserCredentials has the following code:
namespace Medusa\Oauth\Storage;
use OAuth2\Storage\UserCredentialsInterface;
class MedusaUserCredentials implements UserCredentialsInterface
{
public function checkUserCredentials($username, $password)
{
return Auth::attempt(['email_address' => strtolower($username), 'password' => $password, 'active' => 1]);
}
public function getUserDetails($username)
{
return ['user_id' => $username];
}
}
When I post to the web server to the token route using a raw payload of
grant_type=password&username=<USERNAME>&password=<PASSWORD>
I just get the login page. The token route looks like this
Route::post(
'oauth/token',
function () {
$bridgedRequest = OAuth2\HttpFoundationBridge\Request::createFromRequest(Request::instance());
$bridgedResponse = new OAuth2\HttpFoundationBridge\Response();
$bridgedResponse = App::make('oauth2')->handleTokenRequest($bridgedRequest, $bridgedResponse);
print_r($bridgedResponse); die();
return $bridgedResponse;
}
);
What am I missing?
Thanks!
I found the issue -- I had a namespace issue that I had to resolve. For some reason, my app returned a 200 OK response and the normal login page, so I didn't think to check the logs.
I know, bad dev, no cookie!

How can i send dynamic data in bootstrap file for Email in zend framework

I am sending email to user while registration. For that i am using Zend's default function.
For that i added code in my Bootstrap file.
protected function _initMail()
{
try {
$config = array(
'auth' => 'login',
'username' => 'username#gmail.com',
'password' => 'password',
'ssl' => 'tls',
'port' => 587
);
$mailTransport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', $config);
Zend_Mail::setDefaultTransport($mailTransport);
} catch (Zend_Exception $e){
}
}
Now my need is username,password and port i want to make this field dynamic. I want to fetch this record from the database. Can anyone please tell me how can i solve that problem. Any help will be appreciated.
I would say that you do not put these into the database. A better way would be to put them into a config file and then set them up from there. Doing a database call EVERY SINGLE time your application is called is not really optimal.
The way you should be doing it is:
protected function _initMail()
{
try {
$config = Zend_Controller_Front::getInstance()->getParam('bootstrap');
$config = $config->getOption("mail");
$mailTransport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', $config);
Zend_Mail::setDefaultTransport($mailTransport);
} catch (Zend_Exception $e){
}
}
That is assuming that your application.ini has this:
mail.auth="login"
mail.username="username#gmail.com"
mail.password="password"
mail.ssl="tls"
mail.port=587
However if you decide you want to do this, and have set up your database in the application.ini file (assuming you use ini files for config) something like this:
resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "your.database.host"
resources.db.params.dbname = "database_name"
resources.db.params.username = "username"
resources.db.params.password = "password"
resources.db.isDefaultTableAdapter = true
You can then do:
protected function _initMail()
{
$resource = $bootstrap->getPluginResource('db');
$db = $resource->getDbAdapter();
$select=$db->select()->from("emailSetup");
$credentials=$db->fetchOne($select);
[..email part here..]
}
P.S. I have not tested the select, but you should get the gist of it.

CakePHP Auth Facebook Connect not working (no plugin)

I have a strange situation and I don't know how to debug it.
One client requested to make a facebook login for a website that is on CakePHP version 1.2.12.
So i used Facebook PHP SDK and followed standard procedure. If the user is not registered then register with the data from Facebook generate a password and so on.
Then if the user is registered and he gets connected with his facebook account I want to use the CakePHP Auth Component to log him in.
Problem is that it kicks me out as cannot authenticate.
Here's what I did:
public function facebook_login_register() {
$fbUser = $this->Facebook->getUser();
if ($fbUser) {
//gets FB details about my profile
$fbUser = $this->Facebook->api('/me');
$registeredUser = $this->UserProfile->find('first', array('conditions' => array('UserProfile.email' => $fbUser['email']),
'fields' => array('UserProfile.email')));
if (!$registeredUser) {
... registration ...
}
else{
$usernameDisplay = $this->User->find('first', array('conditions' => array('User.username' => $fbUser['username']),
'fields' => array('User.username_display')));
}
$fb['username'] = $fbUser['username'];
$fb['password'] = $usernameDisplay['User']['username_display'];
$this->Auth->fields = array(
'username' => 'username',
'password' => 'username_display_encoded' //the encoded display_name (encoded with $this->Auth->password() or Security::hash(...). The result is correct when testing it for hashing)
);
if ($this->Auth->login($fb)) {
echo 'ok';
}
else{
echo 'not ok';
}
....
}
So when i am doing this it just kicks me out on the else branch.
Thanks in advance for your help!
Cheers.
I think your login is failing because you have an incorrect field mapped to password - the username_display_encoded field doesn't even exist in the array $fb which you're passing for the login. The array you intend to pass into $this->Auth->login() needs to match the users model's fields for username and password, since it's going to check what you've passed against the database.
$user = $this->User->find('first', array('conditions' => array('User.username' => $fbUser['username'])));
$this->Auth->fields = array(
'username' => 'username',
'password' => 'username_display'
);
if ($this->Auth->login($user['User'])) {
echo 'ok';
}
else{
echo 'not ok';
}
Also, take a look at How do I integrate Facebook SDK login with cakephp 2.x? which seems like it might be useful, though it's for a newer version of Cake.

Categories