I'm using the sfDoctrineApplyPlugin and the registration form requires a username - what's the best way of removing this field?
As the sfDoctrineGuardPlugin allows login via username or email address I'd like my application to use the email address only to identify users. Making specifying a username in registration surplus to requirements.
Would I need to hide this field from the view and then on submit generate a username that's stored to satisfy the plugins but the user never needs to see or use? What's the best way of generating this? The bit before the # in the email address?
Many thanks for any help in advance.
I think you could start here Symfony: how would you reverse the "notnull:true" in a schema of a plugin?.
And you could do this:
class sfGuardUserForm extends PluginsfGuardUserForm
{
protected function doUpdateObject($values)
{
$email_array = explode($values['email']);
$this->getObject()->set('username', $email_array[0]);
parent::doUpdateObject($values);
}
}
Related
I'm using Cognito User Pool for my iOS App User Registration. In general, when Registering a user with Cognito I'm using the email as userID. And also I'm collecting other info like Phone number, Business Name and etc. In this case when I try to register with the same email id with a Different Business name it will show an alert like User already Exist.
In my new Work case, I want to save/register the same email with a different Business name. How can I achieve it?
for example, if we are using a DynamoDB table we have the Partition key and Sort key. By using those we set the email as the Partition key and the Business Name as the Sort key and we can achieve uniqueness.
can we implement the same using Cognito? Does Cognito support the Partition key and Sort key concept?
Is there any way to achieve this by using Cognito?
Please help me with this issue.
Let start from this link :
Configuring User Pool Attributes
You can have changeable standard attributes as far as they are not required. You can add custom attributes as well but they are un-changeable.
Well, let's move on another case on some projects I have a need to storing a user federated identity id (i.e ap-northeast-1:3c2f5c30-0dc8-4d74-91a8-bf5c688abcde) into a cognito user pool attribute. I should store it on a custom attribute (i.e custom:identity_id) because of it will never change in the future.
Back to your case, as it will be dynamic values where users has ability to change their organization list so you can utilize an unused standard attributes for. For example, I will use "zoneinfo" although it looks strange to use unassociated attribute because there is no one with the name "organization". However at least users can pull their organization from their token once logged-in as like :
"zoneinfo": "[org1, org2, org3, etc]"
But it can't full accomodate your case as it should be stored after user registration. While if you set the "zoneinfo" on required registration, it must be unchangeable then. To solve this problem, you can utilize the cognito user pool Post-Confirmation trigger to run some logic to init a standard attribute with empty organization list (i.e "zoneinfo": "[]") adminUpdateUserAttributes. That so users can modify this attribute then because of it is not required attribute.
Sample of adminUpdateUserAttributes :
async function updateOrgAttr() {
try {
var params = {
UserAttributes: [ /* required */
{
Name: 'zoneinfo', /* required */
Value: '[]'
}
],
UserPoolId: 'ap-northeast-1_xxxxxxxx', /* required */
Username: event.userName /* event.userName is an item of post-confirmation trigger event source */
};
let cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
await cognitoidentityserviceprovider.adminUpdateUserAttributes(params).promise()
} catch(e) {
throw e
}
}
I have a Grails application using Spring Security.
This application is basically a content management system, so it is a CRUD.
My URL's access are basically formatted as follows:
/$controller/$action/$id
This is where encounters problems. That occurs in a controller, for example, to change a user I have the following URL:
/user/update/1
And into the controller I have the following code:
def update(Long id) {
def user = User.get(id);
[user: user]
}
That's the problem. If the user change the (id) directly without checking if the user id in request is correct, anyone can surf the users of my system. Now i have a big problem.
The solution that I thought would be to create a unique hash for each registration system, which would hinder the user to understand that, for example, the ID 1 has the hash 123aabbCCDD, for example.
But i have a lot of registers and many domains in the system, and i don't know if this is the best solution.
I need help to know, for example, using the spring security, I can do this kind of thing.
I tried to find solutions to the issue but I'm not sure by what words to search, so if there is already a question like mine, put the link in comments please.
Thanks.
As Joshua points out, if this is a general problem where you need to limit which users (or which roles) can perform particular actions, the spring-security-acl plugin will help. But that can be tedious to work with because you typically need to model things in a fine-grained way, and you end up with a lot of ACL data in the db.
But if you only want to restrict users to being able to edit themselves, just don't pass the user id. You already know who the user is if the action requires authentication. If that's the case, change the action to something like
def springSecurityService
def update() {
[user: springSecurityService.currentUser]
}
A related workflow that can often avoid using ACLs is allowing a user to edit something that they own, e.g. a CreditCard. Assuming you have static hasMany = [creditCards: CreditCard] in the User class and static belongsTo = [user: User] (or just User user), then you can allow the form to send the credit card id, but you just need to use a modified query, e.g.
def springSecurityService
def update(Long id) {
def user = springSecurityService.currentUser
def card = CreditCard.findByIdAndUser(id, user)
[creditCard: card]
}
The final SQL query will look something like select ... from credit_card where id=? and user_id=?, which has a big security advantage over the SQL for a get() call which would be select ... from credit_card where id=?. A malicious user can still try to send any id they want, but since the where clause checks both the id and the user foreign key, if they're not logged in as the card owner, the finder will return null and you can treat that as a mistake or a hack and not allow access.
Note that the hash approach you described isn't very secure - it's just "security by obscurity". If each user's hash is constant, it's not difficult to find out what a user's hash is and forge a request (e.g. a coworker can just look at another's monitor and see the url in their browser).
Using MVC when registering a new user a record gets created in webpages_Membership and UserProfile
The UserId by default gets created as sequential number 1, 2, 3...
my model
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
}
When I go to edit the record in the URL it shows /profile/1
I want to change the id's value to something random e.g. profile/f8934hre987f8987f9f8 for security reasons.
Same thing I want to generate random number when details gets viewed by members so instead
/details/1 want it to be /details/783787483743874873
The ViewModel for displaying the details contains Id field as a primary key which is also gets generated sequentially.
I read using [GUID] is not great for performance.
Advice how to change it without affecting the performance? Suggestions. Thank you.
EDIT
Have similar like groupon site, when user attempts to edit his/her profile instead of showing /edit/1 have something like:
So user doesnt know how many records in the database or what record number the user is.
I am not 100% sure what you mean by something random. I am assuming that you mean encryption. Please take a look at this MSDN link for the details on encryption.
After that ,you can have your action method like /detail/{encrypteduserId}
Then you can have action method like below
public class Detail(string id)
{
var decryptedUserId = GetDecryptedId(id);
// GetDecryptedId gives the decrypted information.
// You can implement it based on the MSDN link
// You can use decryptedUserId to run queries on the database.
}
This way you can achieve your goals without making schema changes. This seems like a minimum possible friction approach.
There is no security benefit to having a random user id, so long as your site implements proper controlled access. That is, nobody should be able to access /profile/1 except the user with a user id of 1 (or another user who is authorized to do so, such as an administrator). All other users should get an error.
An even better approach is to not use an id at all. Simply get the current users ID and show the profile of the currently logged in user. Then user with userid 1 just goes to /profile and they see their profile, and user with an id of 2 goes to /profile and they see their profile and there is no way for one user to see the others.
That's not always possible however, for instance in maintenance screens where an admin is viewing other users profiles, but in that case only the authorized admin should be able to do that.
Obscuring the userid is a false sense of security, since the id will be visible anyways. You are simply fooling yourself if you think this adds any security value, unless you haven't implement proper security in the first place, in which case it's just hiding your real problem.
It also adds needless complexity, and confusion. It's equivalent to saying "I want to change the address of my house to a random number for security reasons". Think of all the problems that would cause, for dubious results.
Having the User ID displayed in the URL is a genuine security concern, be it a simple integer user id or some GUID (if that GUID can be used to identify a user). This is especially true in cases of Transport layer security (HTTPS) where the URL is not encrypted like the content is.
Here are a couple of ways I can think of going around this:-
1.) As suggested by Erik above, use User.Identity.Name to identify the currently logged in user. This wouldn't however work for the administrator accessing another member's profile. It would also not work for unauthenticated scenarios.
2.) Instead of creating a direct hyperlink, create a form which posts the user id as part of a custom type (model). Then use model binding to access the User ID as a property of the custom model object in the Action method. In this case, the user ID is submitted as part of the form and hence is transported over the wire encrypted (if HTTPS) and not visible in the URL. This would work in both cases where a member is trying to access his/her own profile, or when an administrator chooses a profile to access on screen.
An example of scenario 2::
public ActionResult EditProfile(UserProfile userProfile)
{
bool success = false;
if (User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
if (WebSecurity.UserExists(userProfile.UserName))
{
// your code to update profile here.
}
}
}
if (success)
{
ViewBag.Message = "Profile updated successfully.";
}
else
{
ViewBag.Message = "Profile not updated:";
}
return View();
}
I've got a domain-class with a user reference:
class MyThing {
MyUser createdBy
//...
And with using the Spring Security plugin, I have a fairly basic Person class setup except I'm trying to obtain the user's email address from reference. Using springSecurityService.principal works great but only for the currently logged in user.
How can I get the user's email address?
If I can't simply "lookup" by username reference, then is it possible to extend my Person class to acquire email address from the LDAP plugin and save to the database?
I solved my problem by first adding an email property to my Person class.
class MyUser {
String username
String email
Then by using a ldap template attributes map, I was able to pull the email as well as the username.
tokens.add(attributes.get("sAMAccountName").get().toString());
tokens.add(attributes.get("mail").get().toString());
From there it was just getting the property createdBy.email
I am developing a site that uses the built in account model / controller that comes with the new MVC site template. I want to be able to only allow people to register if they use one of two specific domains in their email address.
So for example they can register if they use #domain1.co.uk or #domain2.co.uk, but no other domains (for example Gmail, Yahoo etc) can be used.
If anyone could point me in the right direction that would be great.
If using the MVC3 default site, you'll have a /Models/AccountModels.cs file. You can add a regular expression there to cause client-side* and server-side validation.
public class RegisterModel
{
...
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
[RegularExpression(#"^[a-zA-Z0-9._%+-]+(#domain1\.co\.uk|#domain2\.co\.uk)$", ErrorMessage = "Registration limited to domain1 and domain2.")]
public string Email { get; set; }
...
}
You will need to work out the expression that works out best for your requirements.
*client-side validation assumes your view references the jquery.validate script and has Html.ValidationMessageFor(m => m.Email) and/or Html.ValidationSummary(), which it should by default.
What more do you need than:
if( email.Contains("#domain1.co.uk") || email.Contains("#domain2.co.uk") )
Register(email);
else
throw, return false, whatever()
When it comes time to do your validation, i.e. is the email field populated, use a regex to make sure it is in the domain. As for what the actual regex should be, there is a lot of discussion online about validating email addresses with them. It even comes down to what a valid email address should contain. I found this example online, but it likely by no means the best solution, as I am not a regex expert. I have tried it with a few examples but I'm sure you can come up with some that will pass when they shouldn't:
^\w+([-+.']\w+)*#mail.com$
Where mail.com is the domain you want to check against. If you have multiple domains, you can either extend the regex or do multiple checks replacing mail.com in the regex with whatever else you want to use.
BTW I found that regex on this forums.asp.net post which touches on an issue like yours.
Validate that on both the frontend (the reg form) and the backend.
Here I recommend jquery validation plugin for client side validation.