I've built a Silverlight website where users can create an account and login. Right now, users just create an account through a form and can directly login. I want to incorporate a email verification feature, where the user will receive an email with a verification URL and only then can he login. I also wish to incorporate a forgot password feature that sends an email to the users registered email address to recover password.
How can I do this in silverlight. I'm using Windows SQL Azure as the back-end database. Will I have to create a separate Application for creating user accounts and recovering passwords?
Hope this helps you out on part A of your problem.
I noticed the post might throw you off a bit, so I decided to write a method that will do this for you in the quickest amount of time.
public bool Send(string fromEmail, string toEmail, string subject, string body)
{
try
{
MailMessage message = new MailMessage();
message.From = new MailAddress(fromEmail);
message.To.Add(new MailAddress(toEmail));
message.Subject = subject;
message.Body = body;
message.IsBodyHtml = false;
SmtpClient smtp = new SmtpClient();
smtp.EnableSsl = true;
smtp.Send(message);
return true;
}
catch (Exception ex)
{
return false;
}
}
Essentially, once they create their account you would want to call this filling out all variables. Make sure in your body of text you have a link that sends them to a page where they can submit "activate" their account.
This will essentially be a bit value in the database that is set to false by default and won't be set to true until they click on the "submit" or "activate" button from the link that would be in the body of text.
For password recovery you would do the same. Except instead of sending them to a page to activate their account you'd send them to a page where they could just re-create their password. Since the database doesn't care if the password is old or new you could just send them to a page where they create a new password. You wouldn't even need to create a temp password for them (Unless you wanted to for experience and for a extra caution).
Happy Coding! ;)
Related
I using ASP.Net Core 3 Identity with Identity Server 4 for authentication ...
On the AspNetIdentity template the External Authentication Controller Callback method calls the AutoProvisionUserAsync method which has the following code:
var email = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Email)?.Value ??
claims.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value;
if (email != null) {
filtered.Add(new Claim(JwtClaimTypes.Email, email));
}
var user = new User {
UserName = Guid.NewGuid().ToString(),
};
var identityResult = await _userManager.CreateAsync(user);
Basically it creates a user with a Guid as Username ...
In my database I am using Email as Username ... Is there any reason to use a Guid?
I suppose most External authentication services (Google, Facebook, etc) provides an Email.
So my idea would be:
Check if there is an User in the database already with that email.
If no User exists create one with the email obtained from the External authentication service.
Also add the external authentication to the User in the database;
If there is a User with the email in the database check if it has that External Login.
If the user does not have the external login register and add it.
Does this make sense?
Check if there is an User in the database already with that email.
On callback, first call is to FindUserFromExternalProviderAsync, it search users using nameIdentifier, then if not found there is call to AutoProvisionUserAsync
Basically it creates a user with a Guid as Username ...
In my database I am using Email as Username ... Is there any reason to use a Guid?
The ApplicationUser's base class is IdentityUser, IdentityUser has a prop for ID and one for email by design. thats why most of libraries take advantage of having GUID as ID in addition of email for extensibility. You can use the email for ID if you like to.
I have written code using JNDI for creating users using DirContext in AD.
After I create the user I am not able to login with those credentials. When I manually reset the password for that user in AD, I am able to login.
Here I have placed my code for your reference,
Hashtable<String, String> ldapenv = new Hashtable<>();
ldapenv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
ldapenv.put(Context.PROVIDER_URL, "ldap://10.95.144.139:389");
ldapenv.put(Context.SECURITY_AUTHENTICATION, "simple");
ldapenv.put(Context.SECURITY_PRINCIPAL, "CN=Administrator,CN=Users,dc=Merck,dc=local");
ldapenv.put(Context.SECURITY_CREDENTIALS, "Merck2017");
DirContext context = new InitialDirContext(ldapenv);
Attributes attributes = new BasicAttributes();
// Create the objectclass to add
Attribute objClasses = new BasicAttribute("objectClass");
objClasses.add("top");
objClasses.add("person");
objClasses.add("organizationalPerson");
objClasses.add("user");
// Assign the username, first name, and last name
String cnValue = new StringBuffer(user.getFirstName()).append(" ").append(user.getLastName()).toString();
Attribute cn = new BasicAttribute("cn", cnValue);
Attribute sAMAccountName = new BasicAttribute("sAMAccountName", user.getUserName());
Attribute principalName = new BasicAttribute("userPrincipalName", user.getUserName()
+ "#" + "merck.local");
Attribute givenName = new BasicAttribute("givenName", user.getFirstName());
Attribute sn = new BasicAttribute("sn", user.getLastName());
Attribute uid = new BasicAttribute("uid", user.getUserName());
// Add password
Attribute userPassword = new BasicAttribute("userPassword", user.getPassword());
Attribute pwdAge = new BasicAttribute("pwdLastSet","-1");
Attribute userAccountControl = new BasicAttribute("userAccountControl", "544");
// Add these to the container
attributes.put(objClasses);
attributes.put(sAMAccountName);
attributes.put(principalName);
attributes.put(cn);
attributes.put(sn);
attributes.put(givenName);
attributes.put(uid);
attributes.put(userPassword);
attributes.put(userAccountControl);
attributes.put(pwdAge);
// Create the entry
try {
context.createSubcontext(getUserDN(cnValue,"Merck-Users"), attributes);
System.out.println("success === ");
} catch (Exception e) {
System.out.println("Error --- "+e.getMessage());
}
Please help me resolve the following issues:
How do I set AD user password while creating the user using the above code?
How do I set userAccountControl to 66048 in the above code?
How do I create the user enabled while using the above code?
How do I disable the option "user must change the password in next login" while creating the user in the above code?
Thanks in advance.
I don't have all the answers, but this should get you started:
Passwords can only be set over a secure channel, like LDAPS (LDAP over SSL). Since you are connecting to port 389, that is not SSL and AD won't let you set the password. You must connect to the LDAPS port: 636. You may run into issues trusting the SSL certificate. I can't help much here since I'm not a Java developer, but there is an example here.
The answer to your second and third questions is the same: Accounts with no passwords are always disabled. Since you haven't set the password properly, the account will be disabled. Once you figure out how to set the password, you can also set userAccountControl to whatever you need.
You are disabling the "user must change password" option correctly: by setting pwdLastSet to -1. That's the right way to do it. But you may have to fix the other issues first.
Another important thing: I have created AD accounts in .NET, and I have found that I had to create the account first, then go back and set the password and set the userAccountControl attribute after. You may have to do the same.
I have a below code to reset password which uses PUMA API of IBM Portal:
Below code checks whether user entered old passoword correct or not:
loginService.checkPassword(userName, oldpswd.toCharArray());
Below code update the new password:
ibmPumaUtility.updateUserPassword(userName,resetPasswordForm.getNewPassword());
PumaController pController = pumaHome.getController();
PumaLocator locator = pumaHome.getLocator();
String defaultRealm = "xyz";
User user = locator.findUserByIdentifier("uid=" + username + ",cn=users,o=" + defaultRealm);
HashMap<String, String> userAttrs = new HashMap<String, String>();
userAttrs.put("password", updatedPassword);
pController.setAttributes(user, userAttrs);
The issue is, when user again logs in with old password, he is able to log in but only for some time 5-10 mins and after that he is able to login with the new password.
Can someone please suggest me how to resolve this.
the API call you use to validate if the "old password" is still okay:
loginService.checkPassword(userName, oldpswd.toCharArray());
Does in fact use a performance optimized validation on WAS level in default. This is matching to the most use-cases.
The "real login" won't let you in - that really checks the current password.
So if you open up a 2nd browser and try to login to portal at that time with "old password" you won't get a valid session.
(there is an exception for some LDAP servers as they still allow login with the old password for about 60min).
But if you require the API to return the correct value immediately there is a config option for this.
You switch the "basic login" to a "full login" by:
• Click WP AuthenticationService. Under Additional Properties select Custom Properties.
• Click New to create new custom properties.
• In the Name field, type authentication.basic.login.target
• In the Value field, type Portal_LTPA
• Click OK to confirm the changes.
• Save the configuration.
• Restart the server.
After this change the validation will leverage the complete Portal_LTPA login stack and return with an error if the "old password" is used.
I want to create the contact & user related to account by importing csv file.After creating user, generated username & password should be send to the respective user's email address.
I am planning to use Vf page for accepting the csv file & the Contact & User API for adding contacts & Users. But I am not sure regarding the email notification to user through API.
So can anyone please provide me the best solution for this?
You'll need to use Database.insert() flavor instead of straightforward insert users;
Check out the DML options help topic, especially the "emailHeader" property
Something like this should do the trick:
List<User> users = new List<User>(); // fill in with data from your CSV
Database.DMLOptions dlo = new Database.DMLOptions();
dlo.EmailHeader.triggerUserEmail = true;
database.insert(users, dlo);
Be aware though that you can't insert an inactive user. You can deactivate them straight after the insert but then they can't login so you'll probably want to suppress the sending of email, not enforce it. Make sure you have sufficient amount of licenses before you start!
Last but not least - you can cheat by setting the same password for them with System.setPassword('user id', 'new password') :) It's not recommended to expose this functionality to your end users though, can process only 1 user at a time and wastes 1 DML statement...
I am developing a site in Visualforce and would like to offer user a simple form to send me feedback via email. There would be 3-4 fields like name, user's email, reason and feedback and "send" button. Clicking the send button should automatically send that message to my email address.
I do not want to store the form data in salesforce at least for now...All the stuff I found online about visualforce/apex and email is about saving that data to salesforce too.
Can I just make use of apex's email capabilities and send out email without storing that data anywhere in salesforce?
Thanks,
Calvin
It's not required to insert/update/delete any records in the database when executing an action on a VisualForce page. You can leverage the Outbound Email functionality to send out your notification. For something like this, you will probably want to familiarize yourself with the SingleEmailMessage methods.
A simple example to get you going:
public PageReference actionSend() {
String[] recipients = new String[]{'myemailaddress#somedomain.com'};
Messaging.reserveSingleEmailCapacity(recipients.size());
Messaging.SingleEmailMessage msg = new Messaging.SingleEmailMessage();
msg.setToAddresses(recipients);
msg.setSubject('Test Email Subject');
msg.setHtmlBody('Test body including HTML markup');
msg.setPlainTextBody('Test body excluding HTML markup');
msg.setSaveAsActivity(false);
msg.setUseSignature(false);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {msg}, false);
return null;
}
If you are interested in sending these outbound messages from a dedicated email address (something like noreply#somecompany.com), you can set these up through the Setup -> Administration Setup -> Email Administration -> Organization-Wide Addresses menu. Once you have created an org-wide address, grab the Id from the URL and use the setOrgWideEmailAddressId(Id) method on your instance of Messaging.SingleEmailMessage.