As user logged in, he had provided his name and raw password which was hashed and compared with db's value.
def login(request):
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None and user.is_active:
# user is active
auth.login(request, user)
# relink to right page
return HttpResponseRedirect("/account/loggedin/")
else:
# error page
return HttpResponseRedirect("/account/invalid/")
or I could just use:
#login_required
def index(request):
if request.user.is_authenticated():
return render_to_response('polls/index.html', {'sessionDic' : request.session})
else:
#some stuff
The problem is: once user logged in, the following requests comprises only cookies which are checked and user have no need to put his credentials again.
But, I need to have raw user's password in View in every method to log in to linux user and execute some linux program as this user. For exmaple the su program is used to switch the ritgh linux user:
def ssh_command (user, password, command):
child = pexpect.spawn('su -l %s -c \'%s\'' % (user, command))
i = child.expect([pexpect.TIMEOUT, pexpect.EOF, 'Password: '])
if i == 0: # Timeout
print 'ERROR!'
print 'su can\'t be executed:'
print child.before, child.after
return None
if i == 1: # EOF
print 'ERROR'
print 'EOF error'
print child.before, child.after
return None
child.sendline(password)
return child
def main ():
user = 'test'
password = 'test'
child = ssh_command (user, password, 'curl habrahabr.ru | wc -c')
child.expect(pexpect.EOF)
print child.before
print child.after
print child.match
How can I store raw user's password and substitute it to required functions?
You could store it in the session data from the login view function. At least then it would die with the session. The other option, stashing it in a database field, would be horrendous if some hacker got DB access. At least if a hacker gets DB access with passwords in sessions they'd only get the plain text passwords of current sessions. Make sure you timeout sessions appropriately, or encourage your users to logout and remove session data on logout.
Here's another idea. Don't require password authentication for su. Instead use /etc/sudoers to allow your web server user to run things as other users. This way you can also restrict which commands can be run - does your current view protect against injecting stuff into the command line?
This way you don't need to keep users passwords, you just give one username (wwwuser) the privs it needs. Django has already decided who the user is from the login, so I don't think there's a problem in giving it enough privs to do something as that user.
You need access to the cleartext password. Ideally you would store that and regenerate the hash for authentication. You should store it encrypted with a site password, as well, for security. I have implemented this myself, but not for Django. You would have to re-write Django's authentication code to achieve that.
Related
I want to connect two python scripts together, Let me show what I want to do, there is one login.py file and another main.py file, now when someone run login.py script, It will ask password and if password is correct then it will run main.py. The problem is if someone directly run main.py then there should be a condition if he logged in or not, If not then it will run login.py, and one more thing that I don't want to combine both files.
login.py
import os
enterPass = input('Please enter password')
if enterPass == "admin":
os.system('python main.py')
else:
print('Password Wrong')
main.py
print("Logged in successfully")
#my code that I want to run
This doesn't work. At least not securely. You're trying to replicate the authentication process of a website, but that's not how it works locally on a machine.
When you successfully log in to a website, it'll put an authentication token in your browser. This will be sent every time you visit the site the next time and act like your password. For it to work locally, you'd have to ask the user for the password every time (as in Tomerikoo's answer).
A hack to make it work is to store the some state on the user that tells them that they've logged in. A simple example would be:
login.py
import os
password = input('Please enter password')
if password == "admin":
os.environ['USER_PASSWORD'] = "Logged in"
else:
os.environ['USER_PASSWORD'] = "Not logged in"
main.py
import os
if os.environ.get('USER_PASSWORD', 'Not logged in') == "Logged in":
print('Running code...')
else:
print('Please log in')
This will work but doesn't provide any security at all. The problem is that all code and all data is already in the hand of the user. So they can just set USER_PASSWORD manually, change the source code, or whatever, and they'll circumvent this security check.
Even checking password == "admin" isn't secure. It could be more secure if you hashed it by downloading something like passlib and stored the encrypted password as an environment variable SECRET_PASSWORD:
from passlib.hash import sha256_crypt
encrypted_password = os.environ.get('SECRET_PASSWORD', '')
password = input('Please enter password')
if sha256_crypt.verify(password, encrypted_password):
# Do something on success.
But even then it's not secure, because you must set USER_PASSWORD to something which the user can always introspect and figure out.
You might want to run the main.py from the longin.py via the shell
import os
os.system('python3 main.py')
I need to validate if servicenow login credentials are correct or not.
I am using pysnow
def validate_conn(self, data):
instance = data['url']
user = data['uname']
password = data['pwd']
try:
pysnow.client.Client(instance=instance, host=None, user=user, password='xfgdfgdf', raise_on_empty=None,
request_params=None, session=None)
print("valid")
except:
print("invalid")
return data['pwd']
In the above code I gave the invalid password so it have to come to the except block but i am getting valid as output. I need to validate if credentials are valid or not
The ServiceNow Web Services API does not provide a mechanism to validate credentials. One way to validate credentials from a Web Services client is to attempt to read a record that you know exists. One record that must exist is your own user record from sys_user.
The following code attempts to read your own user record from sys_user. If you are unable to read this record, then something must be wrong.
try:
client = pysnow.Client(instance=instance, user=user, password=password)
response = (client
.resource(api_path='/table/sys_user')
.get(query={'user_name': user})
.one())
print('credentials are valid')
except:
print('credentials are not valid')
I have an API request to a third-party website that works great in the command line (from https://github.com/haochi/personalcapital):
pc = PersonalCapital()
try:
pc.login(email, password)
except RequireTwoFactorException:
pc.two_factor_challenge(TwoFactorVerificationModeEnum.SMS)
pc.two_factor_authenticate(TwoFactorVerificationModeEnum.SMS, input('code: '))
pc.authenticate_password(password)
accounts_response = pc.fetch('/newaccount/getAccounts')
accounts = accounts_response.json()['spData']
When I run the above in the command line, I get back a JSON just as intended.
However, I'd like to use it in a web app on a Flask server. So, I need to remove the command line input('code: ') for SMS confirmation. I'm thinking I'll use a form via 'POST' to get the user input.
However, if I redirect() or render_template() to send the user to the form, it interrupts my API session, and I get back a "session not authenticated" response from the API.
Server logic. Routes in question are /update (email and password first) and /authenticate (SMS confirmation form):
#app.route("/update", methods=["GET", "POST"])
#login_required
def update():
# Via post:
if request.method == "POST":
# Ensure userentered email
if not request.form.get("pc_email"):
return apology("Please enter username", 400)
# Ensure user entered password
elif not request.form.get("pc_password"):
return apology("Please enter password", 400)
# Save email & password
email = request.form.get("pc_email")
password = request.form.get("pc_password")
# Try to log in
try:
pc.login(email, password)
# If 2-factor is required, send sms & redirect
except RequireTwoFactorException:
pc.two_factor_challenge(TwoFactorVerificationModeEnum.SMS)
return redirect("/authenticate")
# Get data:
else:
# Get accounts data
accounts_response = pc.fetch('/newaccount/getAccounts')
accounts = accounts_response.json()['spData']
# TODO - update database w/ data from accounts & transactions
return redirect("/")
#app.route("/authenticate", methods=["GET","POST"])
#login_required
def authenticate():
# Via POST:
if request.method == "POST":
# SMS authentication
pc.two_factor_authenticate(TwoFactorVerificationModeEnum.SMS, \
request.form.get(sms))
pc.authenticate_password(password)
# Get accounts data
accounts_response = pc.fetch('/newaccount/getAccounts')
accounts = accounts_response.json()
# TODO - update database w/ data from accounts & transactions
# Redirect to "/"
return render_template("test.html", accounts=accounts)
# Via GET:
else:
return render_template("authenticate.html")
Source code for project is here: https://github.com/bennett39/budget/blob/stackoverflow/01/application.py
How do I block the code from executing while waiting for the user to respond with their SMS code? Or, should I be going about this problem a different way?
The error you are experiencing is actually due to the way you try to use global variables to persist state between requests. You initially define password as a module level variable and then set password = request.form.get("pc_password") within your update function. Due to pythons rules regarding global and local variables https://docs.python.org/3/faq/programming.html#id9 this creates a new local variable containing the password value and leaves the module level variable untouched. You then access the original global password variable within your authenticate function which fails as this password variable is still set to its original value of ''. The quick fix would be to add global password at the start of your update function but this ignores the other problems with this method of persisting state. All of your global variables are shared between everyone using your site, so that if multiple people are logged in then they will all be logged into the same personal capital account. It would be preferable to use the session object to persist this data as each user will then only be able to access their own session object and there will be no risk of people accessing each others accounts. Your use of the PersonalCapital object complicates things a little as this uses instance variables to persist state, which is appropriate for a command line application but less so for a web application. It is a very simple object however, with only 2 instance variables. It should therefore be fairly straightforward to extract these and store them in the session at the end of your update function and use these values to rebuild the object at the start of your authenticate function.
I'm developing an application that requires the user to login. It's a terminal browser to navigate, and use, a popular email client.
I am struggling with the logic flow of actually logging the user in without things getting messy. I will try to explain what I'm trying to achieve in psedueo code, and then demonstrate what I've currently done.
username = 'joe#example.com'
password = 'itsasecret'
# User has logged in before using our application. Instead of
# logging in via HTTP, just inject the cookies into the session.
if userExistsInDatabase:
session.addCookies(db.getCookies(username))
# Check the session is still valid. Just because we load
# the cookie from the database doesn't mean it's valid as
# the account could be blocked, or session could have expired
if session.checkIfSessionIsValid():
print 'Logged In'
else:
# Login failed, now we need to do a HTTP request
# incase the session has died
if session.login(username, password):
# Login success
else:
# Login Failed
else:
# No session exists in DB, try to log in and add user to db
if session.login(username, password):
# Login success
else:
# Login Failed
I hope that code explains it better than I could in words. But, the problem I am having is everything is getting messy and fast, and it's a pain to have to repeat this code whenever I need to use it.
This is something I do regular on a lot of my projects, because most HTTP sites, at least the large ones, have a similar sort of login flow.
Any advice? If you need more info, please ask.
Assuming the supporting code make proper use of exceptions, you can solve this with less code duplication:
class Session():
def reconnect(self, username):
try:
cookie = db.getCookies(username)
except LookupError:
raise UserDoesNotExist
else:
self.addCookies(cookie)
if not self.checkIfSessionIsValid():
raise InvalidSession
def login(self, ...):
if not do_the_login(...):
raise LoginError
try:
try:
session.reconnect(...)
except (InvalidSession, UserDoesNotExist):
session.login(...)
except LoginError:
# failed
# at this point, either an unhandled exception terminated
# this code path or we are logged in.
I'm trying to create a user account on a remote Ubuntu system using Fabric. I want the account to have a strong password. I can use the following to create the account:
sudo('useradd -m test -s /bin/bash')
The problem is I'm not sure how to set the password. The useradd -p options requires an encrypted password. How do I set the password? How does the salt get passed to the remote system?
Example code would be appreciated.
Thanks
Try chpasswd. Unlike passwd, you can pass the username and password in the command's standard input. So you can for example upload a file containing the password and put this line in your fabfile:
sudo('chpasswd < my_password_file')
From man chpasswd:
The chpasswd command reads a list of user name and password pairs from standard input and uses this information to update a group of existing
users. Each line is of the format:
user_name:password
The supplied passwords must be in clear-text.
I do it like this:
sudo('useradd %s' % username)
sudo('echo %s | passwd %s --stdin' % (username, username))
sudo('chage -d 0 %s' % username)
The password will match the username and the user will be prompted to change their password at first login.