FOS and Fr3d ldap Bundle with symfony2.1 - symfony

Login for the first time and getting registered in the database. Though now I got the problem that I can't login a second time.
"symfony/symfony": "2.1.*"
"fr3d/ldap-bundle": "2.0.*#dev"
I have seen similar issies, but if "bindRequiresDn: true" i get in my logs:
[2013-07-10 11:37:18] ldap_driver.DEBUG: ldap_bind(Nikita, **) [] []
[2013-07-10 11:37:18] ldap_driver.DEBUG: 0x1: Failed to retrieve DN for account: Nikita [Binding requires username in DN form] [] []
and can't login.
But if i change:
.../vendor/fr3d/ldap-bundle/FR3D/LdapBundle/Driver/ZendLdapDriver.php
if ($user instanceof LdapUserInterface && $user->getDn()) {
$bind_rdn = $user->getDn();
} else {
$bind_rdn = $user->getUsername();
}
on
if ($user instanceof LdapUserInterface) {
$bind_rdn = $user->getDn();
} else {
$bind_rdn = $user->getUsername();
}
all works good.
My config
fr3d_ldap:
driver:
host: "%ldap_host%"
port: "%ldap_port%"
username: "%ldap_username%"
password: "%ldap_password%"
baseDn: ou=hello, dc=h, dc=i, dc=ru
bindRequiresDn: true
accountFilterFormat: (&(samaccountname=%s))
user:
baseDn: ou=hello, dc=h, dc=i, dc=ru
filter: (&(objectClass=user))
attributes:
- { ldap_attr: samaccountname, user_method: setUsername }

I had problems when initially using FR3DLdapBundle and after logging out and then trying to login the 2nd time.
You may want to read through my blog article here:
Symfony AD Integration
I'm not sure if you already got an answer or got this working, but hopefully this helps someone else out!

Related

Can't send emails using SwiftMailer (Symfony4): wrong SMTP parameters?

I'm coding a small website using Symfony 4.
There's a simple contact form that is supposed to send emails, seemed easy until I realize I can't configure it ^^
I've followed Symfony doc instructions from here:
[https://symfony.com/doc/current/email.html][1]
Meaning mainly having the Swift mailer dependy:
composer require mailer
And my Controller looks like this:
/**
* #Route("/contact", name="contact_handling")
*/
public function contactHandler(Request $request, \Swift_Mailer $mailer)
{
$contact = new Contact();
$form = $this->createForm(ContactType::class, $contact);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$message = (new \Swift_Message('Hello Email'))
->setFrom('send#example.com')
->setTo('myownemail#hotmail.fr')
->setBody("plopppp mail")
;
$mailer->send($message);
$contact = $form->getData();
return $this->render('home.html.twig', array(
'form' => $form->createView(),
));
}
return $this->render('home.html.twig', array(
'form' => $form->createView(),
));
No matter what it does next in the return (I'm also trying to figure out how to avoid the page reload and just return an answer like "OK" or "not OK" then my Javascript pops up a message)
For dev environment (I'll have the same problem when moving to prod by the way),
my .env conf file has this parameter:
MAILER_URL=smtp://smtp-mail.outlook.com:587?encryption=tls&username=myownemail#hotmail.fr&password=mypwd
while trying to use my own email account, which could be my problem
Smtp address, port and encryption are some parameters found on website like this one:
[https://www.lifewire.com/what-are-the-outlook-com-smtp-server-settings-1170671][1]
Of course, I've never received anything.
If someone familiar whith this could help me it would be very nice :)
I'm using Windows10 + PhpStorm + php7 + built-in symfony server
Thanks!
Edit:
Output from: php bin/console debug:config SwiftmailerBundle
swiftmailer:
default_mailer: default
mailers:
default:
url: '%env(MAILER_URL)%'
spool:
type: memory
path: 'C:\www\h4h\var\cache\dev/swiftmailer/spool'
id: null
transport: smtp
command: '/usr/sbin/sendmail -bs'
username: null
password: null
host: localhost
port: null
timeout: 30
source_ip: null
local_domain: null
encryption: null
auth_mode: null
delivery_addresses: { }
logging: true
delivery_whitelist: { }
Edit 2:
I've just tried putting the conf in the config/packages/swiftmailer.yaml without more success, but at least, php bin/console debug:config SwiftmailerBundle outputs the correct info:
swiftmailer:
transport: gmail
username: mylogin
password: mypwd
host: smtp.gmail.com
port: 587
encryption: ssl
auth_mode: login
spool:
type: file
path: '%kernel.cache_dir%/swiftmailer/spool'
sender_address: ~
antiflood:
threshold: 99
sleep: 0
delivery_addresses: []
disable_delivery: ~
logging: '%kernel.debug%'

symfony validation doesn't work

I guess there is something I'm missing.
I have a User entity which is validated through a yml file but every time I send a post request to the route it seems it doesn't get my request. With this I mean that the route works fine but I keep getting the error messages that the password and username should not be blank (due to the constraints i set). So it seems it's not getting my request validated against the entity.
I made sure to have this settings triggered in my config:
validation: { enabled: true, enable_annotations: true }
Here is my routing.yml:
user_login_homepage:
path: /check
defaults: { _controller: UserLoginBundle:Login:checkCredentials }
methods: [POST]
Here is my validation.yml
User\UserBundle\Entity\User:
properties:
username:
- NotBlank: ~
password:
- NotBlank: ~
Here is my controller (LoginController.php)
public function checkCredentialsAction(Request $request)
{
$recursiveValidator = $this->get('validator');
$user = new User();
$errors = $recursiveValidator->validate($user);
if (count($errors) > 0) {
$errorsString = (string) $errors;
return new Response($errorsString);
}
return new Response('Yuppy');
}
I've just tried to follow the instructions but I'm not able to have it work :(
Am I missing something?
you are creating an empty User so It's correct the error, try this (I have imagine that username and password are passed into POST data right?):
$user = new User();
$postData = $request->request->all();
$user->setUsername($postData['username'];
$user->setPassword($postData['password'];
$errors = $recursiveValidator->validate($user);

Nodemail to send mail for firebase app with service account

I get the following message when trying to send mail with Nodemailer :
'535-5.7.8 Username and Password not accepted.
Learn more at\n535 5.7.8 https://support.google.com/mail/?p=BadCredentials y42sm13399804wrc.51 - gsmtp',
responseCode: 535,
command: 'AUTH XOAUTH2' }
I am using a service account from a firebase project, and have granted access to the GMail API. But the nodemailer docs for 2LO is really scarce so I wonder if anyone could help me find if I use the correct credentials ?
user (functions.config().gmail.user) : myfirebaseproject#appspot.gserviceaccount.com
-
function sendContactMail(contactName, contactEmail, contactDate, contactText) {
// Create transport
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
type: 'OAuth2',
user: functions.config().gmail.user,
serviceClient: functions.config().gmail.client_id,
privateKey: functions.config().gmail.private_key
//accessToken: 'ya29.Xx_XX0xxxxx-xX0X0XxXXxXxXXXxX0x',
//expires: 1484314697598
}
});
// Mail Options
let mailOptions = {
from: `"${APP_NAME}" <${SENDER}>`,
replyTo: `${contactEmail}`,
to: 'recipient#gmail.com',
subject: `Nouveau contact photo de ${contactName}`,
html: `Nom : ${contactName}<br/>
Email : ${contactEmail}<br/>
Date du mariage : ${contactDate}<br/>
Message : ${contactText}`,
disableFileAccess: true,
disableUrlAccess:true
};
// Send Mail
return transporter.sendMail(mailOptions);
}
Has your account two steps authentication enabled? In that case generate an app password on https://myaccount.google.com/apppasswords and use it instead of your normal password:
const mailTransport = nodemailer.createTransport(
`smtps://user#gmail.com:generatedAppPassword#smtp.gmail.com`);
I have Cloud Function with this code and it's work fine. Try this
mailTransport = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: ${email},
pass: ${password}
}
});

Flow router and filtering roles - Meteor

I'm dealing with one problem more than 10 days now, and I don't know what to do with it, so I hope that I'll get my solution here.
I have two roles 'admin' and 'user': the first user is added as the admin thanks to the alanning:roles package. However, the problem is that I'm not sure if I set the 'user' role as default.
The picture below shows the code for the createUser function.
Client//Account//account.js
Template.signup.events({
'submit form': function(event) {
event.preventDefault();
var nameVar = event.target.signupName.value;
var emailVar = event.target.signupEmail.value;
var passwordVar = event.target.signupPassword.value;
Accounts.createUser({
name: nameVar,
email: emailVar,
password: passwordVar,
profile: {
roles: ["user"]
}
});
}
});
And below code is the Accounts.onLogin function:
Client//Lib//routes.js
if (Meteor.user().roles = 'admin'){
FlowRouter.go('dashboard');
}
else if (Meteor.user().roles = 'user'){
FlowRouter.go('account');
}
I hope that you understand what my problem is and I looking forward the solution. In conclusion, I need to have 'admin' and 'user' role, and when it is admin it should go to /admin-dashboard route, if it is user it should go to /account route.
Thank you all :D
Problem is here:
if (Meteor.user().roles = 'admin'){ // assigning, not equality check
FlowRouter.go('dashboard');
}
else if (Meteor.user().roles = 'user'){
FlowRouter.go('account');
}
But roles field is an array, so do this instead:
if (Meteor.user().roles.indexOf('admin') !== -1){
FlowRouter.go('dashboard');
}
else if (Meteor.user().roles.indexOf('user') !== -1){
FlowRouter.go('account');
}

How to add External Service logins to an already existing account in Meteor?

Having created a profile page for my app, I would like to display a list of social services that the user is on. It struck me that the easiest way would be to use Meteor's built in accounts system for this.
Is there a good way to add external services to an existing account?
Also, will the user then be able to log in with either (e.g.) Facebook and his password from my app?
Another question that naturally follows: Is there a good way to add an application specific password to an account that was created with an external service?
Here's an alternate method. In this solution, I'm overriding a core function and adding some custom behavior. My goal is to associate the service data with the currently logged in user, then allow the core function to do its thing like normal.
orig_updateOrCreateUserFromExternalService = Accounts.updateOrCreateUserFromExternalService;
Accounts.updateOrCreateUserFromExternalService = function(serviceName, serviceData, options) {
var loggedInUser = Meteor.user();
if(loggedInUser && typeof(loggedInUser.services[serviceName]) === "undefined") {
var setAttr = {};
setAttr["services." + serviceName] = serviceData;
Meteor.users.update(loggedInUser._id, {$set: setAttr});
}
return orig_updateOrCreateUserFromExternalService.apply(this, arguments);
}
Pros:
Avoids creation of unnecessary accounts
Code is short and easy to understand
Code is easy to remove if this functionality is added to Meteor core
Cons:
Requires the user to be logged in. If a user logs in with twitter initially, logs out, and then logs in with facebook, then two seperate accounts will be created.
Users who share a computer may get their accounts merged unintentionally.
Relies on knowledge of how updateOrCreateUserFromExternalService works. This isn't terrible - because it's part of Meteor's public api it probably won't change drastically (not often anyway). But it's still risky.
Here is how I add credentials to existing user account: .../meteor-how-to-login-with-github-account.html
Yes, a user account can be associated with multiple services and have a password-based login at the same time. In the Meteor docs, you can see the structure of such a user account:
{
_id: "bbca5d6a-2156-41c4-89da-0329e8c99a4f", // Meteor.userId()
username: "cool_kid_13", // unique name
emails: [
// each email address can only belong to one user.
{ address: "cool#example.com", verified: true },
{ address: "another#different.com", verified: false }
],
createdAt: 1349761684042,
profile: {
// The profile is writable by the user by default.
name: "Joe Schmoe"
},
services: {
facebook: {
id: "709050", // facebook id
accessToken: "AAACCgdX7G2...AbV9AZDZD"
},
resume: {
loginTokens: [
{ token: "97e8c205-c7e4-47c9-9bea-8e2ccc0694cd",
when: 1349761684048 }
]
}
}
}
For adding a username/password login to an existing account, you can use Accounts.sendResetPasswordEmail on the server side. This also ensures the change happens authenticated and authorized.
Of course you can also just update the user record on the server side with a new password yourself, but this might create a security hole in your app. I would also advise against implementing your own crypto protocol for this if possible, as it is hard.
If you want to add other services than email, you could for example
call a server method that saves a random, long token in the current user's MongoDB document and returns it to the client.
re-login the user with another service using Accounts.loginWith[OtherService]. This logs the user out and in again, using a new account on the other service.
call a second server method with the returned token from the first method as parameter. This second method searches for the user account with the given token and merges its data into the current (new) account.
Check out the example and answer in this posting. It pretty much gives you the code to integrate multiple external and internal accounts. With minor tweaks, you can add the password fields for each account as you desire.
How to use Meteor.loginWithGoogle with mrt:accounts-ui-bootstrap-dropdown
Code:
isProdEnv = function () {
if (process.env.ROOT_URL == "http://localhost:3000") {
return false;
} else {
return true;
}
}
Accounts.loginServiceConfiguration.remove({
service: 'google'
});
Accounts.loginServiceConfiguration.remove({
service: 'facebook'
});
Accounts.loginServiceConfiguration.remove({
service: 'twitter'
});
Accounts.loginServiceConfiguration.remove({
service: 'github'
});
if (isProdEnv()) {
Accounts.loginServiceConfiguration.insert({
service: 'github',
clientId: '00000',
secret: '00000'
});
Accounts.loginServiceConfiguration.insert({
service: 'twitter',
consumerKey: '00000',
secret: '00000'
});
Accounts.loginServiceConfiguration.insert({
service: 'google',
appId: '00000',
secret: '00000'
});
Accounts.loginServiceConfiguration.insert({
service: 'facebook',
appId: '00000',
secret: '00000'
});
} else {
// dev environment
Accounts.loginServiceConfiguration.insert({
service: 'github',
clientId: '11111',
secret: '11111'
});
Accounts.loginServiceConfiguration.insert({
service: 'twitter',
consumerKey: '11111',
secret: '11111'
});
Accounts.loginServiceConfiguration.insert({
service: 'google',
clientId: '11111',
secret: '11111'
});
Accounts.loginServiceConfiguration.insert({
service: 'facebook',
appId: '11111',
secret: '11111'
});
}
Accounts.onCreateUser(function (options, user) {
if (user.services) {
if (options.profile) {
user.profile = options.profile
}
var service = _.keys(user.services)[0];
var email = user.services[service].email;
if (!email) {
if (user.emails) {
email = user.emails.address;
}
}
if (!email) {
email = options.email;
}
if (!email) {
// if email is not set, there is no way to link it with other accounts
return user;
}
// see if any existing user has this email address, otherwise create new
var existingUser = Meteor.users.findOne({'emails.address': email});
if (!existingUser) {
// check for email also in other services
var existingGitHubUser = Meteor.users.findOne({'services.github.email': email});
var existingGoogleUser = Meteor.users.findOne({'services.google.email': email});
var existingTwitterUser = Meteor.users.findOne({'services.twitter.email': email});
var existingFacebookUser = Meteor.users.findOne({'services.facebook.email': email});
var doesntExist = !existingGitHubUser && !existingGoogleUser && !existingTwitterUser && !existingFacebookUser;
if (doesntExist) {
// return the user as it came, because there he doesn't exist in the DB yet
return user;
} else {
existingUser = existingGitHubUser || existingGoogleUser || existingTwitterUser || existingFacebookUser;
if (existingUser) {
if (user.emails) {
// user is signing in by email, we need to set it to the existing user
existingUser.emails = user.emails;
}
}
}
}
// precaution, these will exist from accounts-password if used
if (!existingUser.services) {
existingUser.services = { resume: { loginTokens: [] }};
}
// copy accross new service info
existingUser.services[service] = user.services[service];
existingUser.services.resume.loginTokens.push(
user.services.resume.loginTokens[0]
);
// even worse hackery
Meteor.users.remove({_id: existingUser._id}); // remove existing record
return existingUser; // record is re-inserted
}
});

Resources