How can l implement a hash function (SHA512) that encrypt the username and check if this username and password is correct in the SQL server?
Working login right now if you set a cleartext username
user = User.find_by(username: params[:session][:username].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
redirect_to :root
else
flash.now[:warning] = 'Wrong username/password'
render 'new'
end
I have tried encrypt the username before it runs the if statement but I can get it to work.
The way I hash the username is:
username = params[:session][:username].downcase
username_encrypted = Digest::SHA2.new(512).hexdigest(username)
any ideas how this can be made?
What i am trying to achieve with this is. Too have one column in SQL with encrypted usernames and another column with "public" usernames. Where public usernames is visible for everybody on the site and encrypted usernames is stored in SQL only for authentication.
Related
I'm tryig to get the user address from facebook with Omniauth but did not work.
i added their address on update callback after login.
If i removed their address from omniauth the app did not update their address.
Someone have any idea how to get their address and why the app did not edit and update their address after the login?
thank's
def omniauth_callback
auth_hash = request.env['omniauth.auth']
user = User.find_by_uid(auth_hash[:uid])
if user.nil? && auth_hash[:info][:email]
user = User.find_by_email(auth_hash[:info][:email])
end
if user.nil?
email_domain = ''
email_domain = '#facebook.com' if auth_hash[:provider] == 'facebook'
user = User.new(email: auth_hash[:info][:email] || auth_hash[:info][:nickname] + email_domain, name: auth_hash[:info][:first_name] || '', surname: auth_hash[:info][:last_name] || '', gender: 'I')
user.password_digest = ''
user.save!(validate: false)
end
user.update_attribute(:login_at, Time.zone.now)
user.update_attribute(:address)
user.update_attribute(:neighborhood)
user.update_attribute(:postal_code)
user.update_attribute(:ip_address, request.remote_ip)
user.update_attribute(:provider, auth_hash[:provider])
user.update_attribute(:uid, auth_hash[:uid])
user.update_attribute(:oauth_token, auth_hash[:credentials][:token])
user.update_attribute(:oauth_expires_at, Time.at(auth_hash[:credentials][:expires_at]))
cookies[:auth_token] = { value: user.oauth_token, expires: user.oauth_expires_at}
redirect_to root_url
end
One reason your code will not work is because this
user.update_attribute(:address)
Doesn't do anything - except raise an error. You have to pass a value into update_attribute as well as specify the field.
Also as #mysmallidea points out, you'd be better advised to use update as that will allow you to update multiple fields in one database action.
If present, the address data will be within the auth_hash. So I suggest that you first work out the structure of that hash. In your development environment, add the following:
Rails.logger.info auth_hash.inspect
That will output the current auth_hash to logs/development.log. Use that to determine where in the hash the address data is. You'll then be able to do something like:
user.update address: auth_hash[:info][:address]
However, you may find that the address is not included in the data returned by the facebook oauth system. In which case you will need to return to their documentation to see if this is possible.
I am building a small API that uses basic authentication. What I have done, is that a user can generate a username and password, that could be used to authenticate to the API.
However I have discovered that it is not working 100% as intended. It appears that a request will slip through even though the username is not matching the password. However it will be blocked if the password is incorrect.
Example:
Username: foo
Password: bar
Works:
curl -u foo:bar http://api/protected
Works - But should not:
curl -u f:bar http://api/protected
Does not work - As intended:
curl -u foo:b http://api/protected
To me it appears that it only validates the password, and ignores the username. Here are some code.
# Authentication
protected
def authenticate
authenticate_or_request_with_http_basic do |username, password|
#user = User.includes(:keys).find_by( :keys => { :api_key => password } )
#user.keys.each do |key|
username == key.api_id && password == key.api_key
end
end
end
#user.keys.each do |key|
username == key.api_id && password == key.api_key
end
This piece of code returns a value of .each, which is the collection it's called on (#user.keys in this case). As it is a truthy value, the check will pass always, regardless of what are the results of evaluating your conditional in the block.
What you intended to ask is "Do any of user's keys match these credentials?". Use the appropriate method, Enumerable#any?
#user.keys.any? do |key|
username == key.api_id && password == key.api_key
end
Documentation: Enumerable#any?
Try this
#user = User.includes(:keys).find_by( :keys => { :api_key => password, :api_id => username } )
This way you'll make sure to find a user with valid both username and password, and you won't need the second line (iterating over keys).
The reason for that is: iterating over a block returns this block, not the value/values inside. So your authenticator found a user with a good password, iterated over his keys (which changed nothing) and returned #user.keys, which evaluates to true. Thus the authentication passed.
I'm using django-1.4.3 and the superuser can create users and assign password to them. Here I'm using django-email-as-username to enable users to login with their email as username. When the superuser adds a new user, the newly added user should be notified through email with his username and password.
I'm able to send email after user creation using post_save signal. But I couldn't get the password as it will be encrypted and stored. I want to email the user, the raw password. How can I achieve this?
I have achieved it using the code below:
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
#receiver(post_save, sender = User)
def my_callback(sender, **kwargs):
import inspect
records =[]
for frame_record in inspect.stack():
records.append(frame_record[3])
if frame_record[3]=='get_response':
request = frame_record[0].f_locals['request']
email = request.POST.get('email')
password1 = request.POST.get('password1')
password2 = request.POST.get('password2')
if email != None and password1 != None and password2 != None and password1 == password2:
html_content ="Hi,<br> Your username: %s <br> Password: %s"
from_email = settings.DEFAULT_FROM_EMAIL
message = EmailMessage('Welcome', html_content %(email, password1), from_email, [email])
message.content_subtype = "html" # Main content is now text/html
message.send()
break
in the callback of the authentication process I do:
auth_hash = request.env['omniauth.auth']
and then, I'm extracting the user id, but is it possible in the same time getting the user's name and email address?
You need to first get the raw data from request.env["omniauth.auth"]
data = request.env["omniauth.auth"].extra.raw_info
username = data.first_name
email = data.email
yesss
u can get it by doing
auth_hash[:info][:name] for name and auth_hash[:info][:email] for email
I would like to create rake task to set the username of all users' without a username to the part before the '#' in their email address. So if my email is test#email.eu, my username should become test. If it's not available, prepend it by a number (1).
So i have problem witch checking uniqness of username. Code below isn`t working after second loop ex: when i have three emails: test#smt.com, test#smt.pl, test#oo.com username for test#oo.com will be empty.
I have of course uniqness validation for username in User model.
desc "Set username of all users wihout a username"
task set_username_of_all_users: :environment do
users_without_username = User.where(:username => ["", nil])
users_without_username.each do |user|
username = user.email.split('#').first
users = User.where(:username => username)
if users.blank?
user.username = username
user.save
else
users.each_with_index do |u, index|
pre = (index + 1).to_s
u.username = username.insert(0, pre)
u.save
end
end
end
end
Other ideas are in Gist: https://gist.github.com/3067635#comments
You could use a simple while loop for checking the username:
users_without_username = User.where{ :username => nil }
users_without_username.each do |user|
email_part = user.email.split('#').first
user.username = email_part
prefix = 1
while user.invalid?
# add and increment prefix until a valid name is found
user.username = prefix.to_s + email_part
prefix += 1
end
user.save
end
However, it might be a better approach to ask the user to enter a username upon next login.
if i understand your code correct, you are changing the username of existing users in the else branch? that does not look as if it's a good idea.
you should also use a real finder to select your users that don't have a username. otherwise you will load all the users before selecting on them.
i don't know if it "matches your requirements" but you could just put a random number to the username so that you do not have the problem of duplicates.
another thing that you can use is rubys retry mechanism. just let active-record raise an error and retry with a changed username.
begin
do_something # exception raised
rescue
# handles error
retry # restart from beginning
end
In your query User.find_by_username(username), you only expect 1 record to be provided. So you don't need any each. You should add your index in another way.