Python Flask LDAP connect user with sAMAccountname - python

I am developing a web app and trying to connect our company users through our AD using there sAMAccountname as they are used to. So far, I can connect users with their DistinguishedName but I can't find the way to do it with the sAMAccountname, any clue ?
in my init.py I have :
app.config['SQLALCHEMY_DATABASE_URI'] = 'connection_to_db'
app.config['SECRET_KEY'] = 'secret_key'
# The Attribute you want users to authenticate to LDAP with.
app.config['LDAP_USER_LOGIN_ATTR'] = 'sAMAccountName'
app.config['LDAP_PROVIDER_URL'] = 'connection_to_ldap'
app.config['LDAP_PROTOCOL_VERSION'] = 3
db = SQLAlchemy(app)
and in my models.py I have :
def get_ldap_connection():
conn = ldap.initialize(app.config['LDAP_PROVIDER_URL'])
return conn
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100))
def __init__(self, username, password):
self.username = username
#staticmethod
def try_login(username, password):
conn = get_ldap_connection()
res = conn.simple_bind_s(
'CN=%s,DC=example,DC=com' % username,
password
)
# conn.unbind()
print(res)
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return str(self.id)
Thanks in advance

Related

python flask simple resetful api not just add 1 record user in sqlite database

i create a simple resetful api with flask and work corrent , but after add 1 record user details , don't add next user or second user in database and give error 500.
my server is: centos 7
python: 3.7.5
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
import os
app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'crud.sqlite')
db = SQLAlchemy(app)
ma = Marshmallow(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(150), unique=True)
userid = db.Column(db.String(120), unique=True)
product = db.Column(db.String(20), unique=True)
licenses = db.Column(db.String(1000), unique=True)
def __init__(self, username, userid , product , licenses):
self.username = username
self.userid = userid
self.product = product
self.licenses = licenses
class UserSchema(ma.Schema):
class Meta:
# Fields to expose
fields = ('username', 'userid', 'product', 'licenses')
user_schema = UserSchema()
users_schema = UserSchema(many=True)
'''
Message list:
- 1x0001 = user created
- 1x0002 = user deleted
- 1x0003 = user updated
- 0x0000 = Error not found customer
- 0x0001 = Error can't add customer
- 0x0003 = Error not found customer for delete
- 0x0004 = Error can't update customer
product list:
- 2x0001 = MoeinWeb
- 2x0002 = MoeinBackup
'''
# endpoint to create new user
#app.route("/api/LicenseService/newcustomer", methods=["POST"])
def add_user():
try:
data = request.get_json()
new_user = User(username=data['username'], userid=data['userid'], product=data['product'], licenses=data['licenses'])
db.session.add(new_user)
db.session.commit()
return jsonify({'Message': '1x0001'})
except:
return jsonify({'Message': '0x0001'})
# endpoint to get user detail by id
#app.route("/api/LicenseService/customer/<userid>", methods=["GET"])
def user_detail(userid):
user = User.query.filter_by(userid=userid).first()
try:
user_data = {}
user_data['username'] = user.username
user_data['userid'] = user.userid
user_data['product'] = user.product
user_data['licenses'] = user.licenses
return jsonify(user_data)
except:
return jsonify({'Message': '0x0000'})
# endpoint to update user
#app.route("/api/LicenseService/customer/<userid>", methods=["PUT"])
def user_update(userid):
try:
user = User.query.filter_by(userid=userid).first()
username = request.json['username']
userid = request.json['userid']
product = request.json['product']
licenses = request.json['licenses']
user.username = username
user.userid = userid
user.product = product
user.licenses = licenses
db.session.commit()
return jsonify({'Message': '1x0003'})
except:
return jsonify({'Message': '0x0004'})
# endpoint to delete user
#app.route("/api/LicenseService/customer/<userid>", methods=["DELETE"])
def user_delete(userid):
try:
user = User.query.filter_by(userid=userid).first()
db.session.delete(user)
db.session.commit()
return jsonify({'Message': '1x0002'})
except:
return jsonify({'Message': '0x0003'})
if __name__ == '__main__':
app.run(host='0.0.0.0',port=7273)
just record 1 can update , delete and show with userid , but can't create record 2 on database ,
add_user()

Getting Logged in User Info in Flask using LDAP

I am trying to find a way to retrieve information such as 'mail', 'displayName', 'telephoneNumber' from an LDAP authenticated/logged in user in Flask.
My user can successfully authenticate and log in using LDAP. However how would I be able to get additional information about the user?
I am using standard python-ldap and flask-login modules and I'm trying to create a string variable for these attributes so I can call on them later in the session. When trying to run the query I am getting ldap.FILTER_ERROR: {'desc': u'Bad search filter'} . Any ideas on how to get this working?
class UserInfo():
def whoami(username, password):
conn = get_ldap_connection()
conn.simple_bind_s(username,password)
basedn = 'OU=...,OU=...,DC=...,DC=...'
userfilter = "(|(SamAccountName=\*" + username + "\*)"
userattribute = ['displayName']
userresults = conn.search_s(basedn,ldap.SCOPE_SUBTREE,userfilter, userattribute)
userinfos = UserInfo()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100))
def __init__(self, username, password):
self.username = username
#staticmethod
def try_login(username, password):
conn = get_ldap_connection()
conn.simple_bind_s(domain+username, password)
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return unicode(self.id)
#login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
#app.before_request
def get_current_user():
g.user = current_user
I needed to use ldap.filter.filter_format for proper character escaping.
import ldap.filter
criteria= ldap.filter.filter_format('(&(objectClass=user)(sAMAccountName=%s))', [username])

flask can't connect sqlalchemy

I want to connect sql using sqlalchemy on flask
but it can't
there is a error
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (1049, "Unknown database 'alchemy_new'")
I can't solve this problem.
# -*- coding:utf-8 -*-
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_restful import reqparse, abort, Api, Resource
app = Flask(__name__)
api = Api(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:12345#localhost/catchat'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
password = db.Column(db.String(120), unique=True)
def __init__(self, username, email, password):
self.username = username
self.email = email
self.password = password
def __repr__(self):
return '<User %r>' % self.username
user_inf = {'user1' : {'username':'jaeyeonkim','email':'jaeyeon93#naver.com', 'password':'12345'}}
def not_exist(user_id):
if user_id not in user_inf:
abort(404, message="{} does not exist".format(user_id))
parser = reqparse.RequestParser()
parser.add_argument('username')
parser.add_argument('email')
parser.add_argument('password')
class user(Resource):
def get(self, user_id):
not_exist(user_id)
return user_inf[user_id]
def delete(self,user_id):
not_exist(user_id)
del user_inf[user_id]
return '', 200
def put(self,user_id):
args = parser.parse_args()
not_exist(user_id)
a = {}
a['username'] = args['username']
a['email'] = args['email']
a['password'] = args['password']
user_inf[user_id] = a
return a, 200
class userlist(Resource):
def get(self):
return user_inf
def post(self):
args = parser.parse_args()
new_user = user_inf(args['username'], args['email'], args['password'])
new_user_id = db.session.add(new_user)
db.session.commit()
return new_user_id, 200
api.add_resource(userlist, '/users')
api.add_resource(user,'/api/v1/users/<user_id>')
if __name__ == '__main__':
app.run(debug=True)
First of all I have no idea why password shall be unique ;)
Secondly it looks like sqlalchemy doesn't recognize you connection string.
Try:
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql:////root:12345#localhost/catchat'
According to the following codeļ¼š
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:12345#localhost/catchat'
Your database is 'catchat'.Please create it.
mysql -u root -p12345
create database catchat;
And create table before use it.
db.create_all()
Finally, just a suggestion: don't use flask-restful to define api, please choose
#app.route("/user", methods=["GET"]), it is simple, easy and useful.
Trust me. Two weeks ago, I just rewrite my code from flask-restful to app.route.

Why is check_password_hash always returning False in this login view?

I have a user model with functions to set and check a password using Werkzeug's set_password_hash and check_password_hash functions.
models.py
class User(db.Model):
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(15), unique = True)
password = db.Column(db.String(15))
tasks = db.relationship('Task', backref='author', lazy='dynamic')
def __init__(self, username, password):
self.username = username
self.set_password(password)
def set_password(self, password):
self.password = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password, password)
login.py
def post(self):
username = flask.request.form['username']
passwd = flask.request.form['passwd']
user = User.query.filter_by(username = username).first()
flask.flash(user.check_password(user.password))
if user and user.check_password(user.password):
flask.session['username'] = username
else:
flask.flash("User doesn't exist or password is inccorect.")
return flask.render_template('login.html')
return flask.render_template('index.html')
The flashed result of check_password is always "False". What am I doing wrong?
You've defined User.password to have a length of 15, but the password hash is longer than 15 characters. So when you go to compare it later, it will not be the same value, it will be truncated.
The solution is to either define a longer length to accommodate the length of the hash, or use a database that doesn't care about length (PostgreSQL, SQLite) and don't set a length for the column at all (this is preferable).
password = db.Column(db.String) # no length
# or
password = db.Column(db.String(255)) # some longer length
There's also a second problem: you're calling check_password with the stored hash, not with the user input.
# wrong
user.check_password(user.password)
# should be
user.check_password(passwd)
The following is a small example that demonstrates the password working correctly.
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from werkzeug.security import generate_password_hash, check_password_hash
engine = sa.create_engine('sqlite://', echo=True)
session = Session(engine)
Base = declarative_base(engine)
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
username = sa.Column(sa.String, nullable=False, unique=True)
password = sa.Column('password', sa.String)
def set_password(self, secret):
self.password = generate_password_hash(secret)
def check_password(self, secret):
return check_password_hash(self.password, secret)
Base.metadata.create_all()
u = User(username='davidism')
u.set_password('cabbage')
session.add(u)
session.commit()
u = session.query(User).filter_by(username='davidism').one()
print(u.password)
# pbkdf2:sha1:1000$w9jx4Egp$b420d784ac6ad0575e4a9a908bb4679826e56f5f
print(u.check_password('cabbage'))
# True

flask-login not sure how to make it work using sqlite3

So far I made my user object and my login function, but I don't understand the user_loader part at all. I am very confused, but here is my code, please point me in the right direction.
#app.route('/login', methods=['GET','POST'])
def login():
form = Login()
if form.validate():
user=request.form['name']
passw=request.form['password']
c = g.db.execute("SELECT username from users where username = (?)", [user])
userexists = c.fetchone()
if userexists:
c = g.db.execute("SELECT password from users where password = (?)", [passw])
passwcorrect = c.fetchone()
if passwcorrect:
#session['logged_in']=True
#login_user(user)
flash("logged in")
return redirect(url_for('home'))
else:
return 'incorrecg pw'
else:
return 'fail'
return render_template('login.html', form=form)
#app.route('/logout')
def logout():
logout_user()
return redirect(url_for('home'))
my user
class User():
def __init__(self,name,email,password, active = True):
self.name = name
self.email = email
self.password = password
self.active = active
def is_authenticated():
return True
#return true if user is authenticated, provided credentials
def is_active():
return True
#return true if user is activte and authenticated
def is_annonymous():
return False
#return true if annon, actual user return false
def get_id():
return unicode(self.id)
#return unicode id for user, and used to load user from user_loader callback
def __repr__(self):
return '<User %r>' % (self.email)
def add(self):
c = g.db.execute('INSERT INTO users(username,email,password)VALUES(?,?,?)',[self.name,self.email,self.password])
g.db.commit()
my database
import sqlite3
import sys
import datetime
conn = sqlite3.connect('data.db')#create db
with conn:
cur = conn.cursor()
cur.execute('PRAGMA foreign_keys = ON')
cur.execute("DROP TABLE IF EXISTS posts")
cur.execute("DROP TABLE IF EXISTS users")
cur.execute("CREATE TABLE users(id integer PRIMARY KEY, username TEXT, password TEXT, email TEXT)")
cur.execute("CREATE TABLE posts(id integer PRIMARY KEY, body TEXT, user_id int, FOREIGN KEY(user_id) REFERENCES users(id))")
I also set up the LoginManager in my init. I am not sure what to do next, but I know I have to some how set up this
#login_manager.user_loader
def load_user(id):
return User.query.get(id)
how do I adjust this portion code to work for my database?
EDIT: please let me know if this looks correct or can be improved :)
#login_manager.user_loader
def load_user(id):
c = g.db.execute("SELECT id from users where username = (?)", [id])
userid = c.fetchone()
return userid
#app.route('/login', methods=['GET','POST'])
def login():
form = Login()
if form.validate():
g.user=request.form['name']
g.passw=request.form['password']
c = g.db.execute("SELECT username from users where username = (?)", [g.user])
userexists = c.fetchone()
if userexists:
c = g.db.execute("SELECT password from users where password = (?)", [g.passw])
passwcorrect = c.fetchone()
if passwcorrect:
user = User(g.user, 'email', g.passw)
login_user(user)
flash("logged in")
return redirect(url_for('home'))
else:
return 'incorrecg pw'
else:
return 'fail'
return render_template('login.html', form=form)
#app.route('/logout')
def logout():
logout_user()
return redirect(url_for('home'))
import sqlite3
from flask import g
class User():
def __init__(self,name,email,password, active = True):
self.name = name
self.email = email
self.password = password
self.active = active
def is_authenticated(self):
return True
#return true if user is authenticated, provided credentials
def is_active(self):
return True
#return true if user is activte and authenticated
def is_annonymous(self):
return False
#return true if annon, actual user return false
def get_id(self):
c = g.db.execute('SELECT id from users where username = (?)', [g.user])
id = c.fetchone()
return unicode(id)
#return unicode id for user, and used to load user from user_loader callback
def __repr__(self):
return '<User %r>' % (self.email)
def add(self):
c = g.db.execute('INSERT INTO users(username,email,password)VALUES(?,?,?)',[self.name,self.email,self.password])
g.db.commit()
user_loader callback function is a way to tell Flask-Login on "how" to look for the user id from the database ? Since you are using sqllite3, you need to implement the user_loader function to query your sqllite database and fetch/return the userid/username that you have stored. Something like:
#login_manager.user_loader
def load_user(id):
c = g.db.execute("SELECT username from users where username = (?)", [id])
userrow = c.fetchone()
userid = userrow[0] # or whatever the index position is
return userid
When you call login_user(user), it calls the load_user function to figure out the user id.
This is how the process flow works:
You verify that user has entered correct username and password by checking against database.
If username/password matches, then you need to retrieve the user "object" from the user id. your user object could be userobj = User(userid,email..etc.). Just instantiate it.
Login the user by calling login_user(userobj).
Redirect wherever, flash etc.
Are you using SQLAlchemy by any chance?
Here is an example of my model.py for a project I had a while back that used Sqlite3 & Flask log-ins.
USER_COLS = ["id", "email", "password", "age"]
Did you create an engine?
engine = create_engine("sqlite:///ratings.db", echo=True)
session = scoped_session(sessionmaker(bind=engine, autocommit=False, autoflush=False))
Base = declarative_base()
Base.query = session.query_property()
Base.metadata.create_all(engine)
Here is an example of User Class:
class User(Base):
__tablename__ = "Users"
id = Column(Integer, primary_key = True)
email = Column(String(64), nullable=True)
password = Column(String(64), nullable=True)
age = Column(Integer, nullable=True)
def __init__(self, email = None, password = None, age=None):
self.email = email
self.password = password
self.age = age
Hope that helps give you a little bit of a clue.
Use SQLAlchemy it completely handles all the queries for you, so you don't have to write it all out.
But if you continue using it this way, then your user_loader function should create a "User" class object. Like:
userrow = c.fetchone()
username = userrow[0]
u = User(username=username)
return u

Categories

Resources