Adding facebook login to Flask-security - facebook-oauth

I am having a trouble adding a "login with Facebook" feature to my Flask application which already using Flask-Security for the User authentication. What I really want is a Facebook button besides the login form, so that one can use Facebook instead of mail/password.
I have tried to do this with Facebook-social but failed, I don't really understand the docs. It seems to me that the user would have to be registered before connecting the account to Facebook, which is not the way I want it.
Is there anyone out there who have accomplished this? It seems to me that this would be a common case, but I can't find anything useful about it when googling.

I've done something similar, though with our own SSO instead of Facebook, but the principles are the same. In our case, we're using CAS, so #login_required redirects to our CAS login. On successful login, I use the CAS username attribute to dynamically add the user, then login via Flask-Security. Note that my example makes assumptions about your setup based on https://pythonhosted.org/Flask-Security/quickstart.html
def add_user(username):
if not user_datastore.find_user(username=username):
user_datastore.create_user(**get_user_data(username))
user_datastore.commit()
db.session.commit()
def get_user_data(username):
<Return dict mapping Facebook data to your user model>
def set_current_login(username):
try:
add_user(username)
security.current_user = user_datastore.find_user(username=username)
except Exception as e:
print str(e)
return False
return True
#app.route('/')
#login_required
def index():
set_current_login(<facebook username var>)
Note that you can also use the flask_security.utils.login_user() routine instead of setting the current_user object, which will also set a Flask-Security session cookie.
See the API documentation at https://pythonhosted.org/Flask-Security/api.html

Related

Entering wrong username and password still django authenticate it as correct

I am trying to create a login page in Django when the login details are filled in correctly it redirect to a certain page the problem I am facing is that when I enter wrong username or password Django authenticate them as correct and redirect it to another page my login code is as follows
def loginpage(request):
if request.method=='POST':
use=request.POST.get('username')
pas=request.POST.get('password')
user=authenticate(request,username=use,password=pas)
if user is not NONE:
login(request,user)
return redirect('data')
else:
messages.info(request,'Username or Password is incorrect')
return render(request,'login.html')
Even after entering the username that doesn't even exist in the database Django authenticate as right and doesn't show the error that I am expecting
You have uppercase NONE instead of None. You must have accidentally imported NONE from pickle or some other library, and that's why it's validating instead of raising an error. Check your imports at the top of the file and change to if user is not None.

Django's permission management using native sql

My Django program uses native mysql to do the query. There is no ORM. The back-end management system has sales staff and management staff. They see different interfaces. The administrator can see all the interfaces, while the sales staff can only see some of the interfaces What should I do? I am a newbie to python and have not been exposed to such problems. I need help very much, thanks!
in Django docs you will find few ways to do what you need.
The easy method is with decorators. Suppose a simple def view:
from from django.contrib.auth.decorators import staff_member_required
#staff_member_required
def view_page(request, *args, **kargs):
return render(request, "view.html", {})
Now, both admin (which has all the perms) and staff got access to view.html. A normal or anonymous user will get the "access denied page"
You can get the same goal in class views, with the PermissionRequiredMixin:
from django.contrib.auth.mixins import PermissionRequiredMixin
class MyView(PermissionRequiredMixin, View):
permission_required = 'is_staff'
or with some particular perm:
permission_required = 'AppLabel.can_dosomething'
Note that in this case, the user need the 'can_dosomething' perms for AppLabel.
But beware, the is_staff flag in User Django model give few perms like view the admin site, and another ones. If what you want is just give some perms but not a lots, you'll probably feel more confortable creating a group with that perms, and add your "staff users" there.
There are some more info in the link above

Add additional validation for logins using LexikJWTAuthenticationBundle

I want to add additional validation to allow the login, ie, not just check that the username and password match but do other validations on the user before allowing him to login.
I tried extending JWTTokenAuthenticator but it seems none of its methods are called during the login.
I thought of using a custom "AuthenticationSuccessHandler" but I'm not sure if this is the place I should do this and how could I report from there that the "login" is actually invalid.
Where should I put this logic?
I end up replacing the "login_form" authentication shown on the LexikJWTAuthenticationBundle bundle documentation for a custom guard authentication just for the login, i.e. different than the guard authentication used to validate the JWT tokens.
In the past, I had a similar requirement. Within the alternatives I chose to implement a custom user provider. Symfony documentation on custom user provider creation is more than enough to accomplish the task. Moreover, "Configuring the user provider" section of the LexikJwt documentation explains how to configure lexik_jwt accordingly.

Problems with WebSession when executing a WebService (GeneXus)

Here is the problem: I have a KB Called APP1 that will execute an WebService of an Identity Provider (centralizes all the logins/sessions for different applications) that will return true if there is a logged user in current WebSession that has been granted to access the Application or false otherwise. When I create an web panel at the same KB as the Identity Provider, it works just fine, I get TRUE when there's a logged user, and FALSE when there's not. But when I call it from APP1 it always returns false, I believe that the problem is because the WebSession won't work properly when called through an WS. Any ideas of how to solve it?
My first advice is to try using GAM Single Sign on (X Evolution 3)
WebServices should be Stateless. I think that using the Database instead of WebSession could do the job.
Nonetheless, in order to call a restful WebService you will have to do something more complex as dealing with CookieContainers as stated in the following link.
Consider this solution:
User tries to access App1
There's no web session (App1 doesn't know who is connecting)
App1 redirects User to an IdentityProvider's special login page
If User is not logged, it provides credentials and logs in
IdentityProvider has a session for the user (it knows who is connecting), then it redirects to the referer, appending to the url an encrypted userid parameter.
App1 decodes the parameter, now it knows who is connecting.
App1 saves the userid to the web session, now the user is authenticated
App1 and IdentityProvider must share an encryption key.
Consider that if the encryption key gets compromised or cracked anyone can impersonate another user.
Depending in how secure you want your system to be, you should study other security issues:
every time the user connects it's encrypted login is the same an it shows in the url, it can be easily solved adding a nonce or salt.
The system could be abused generating multiple requests until it gets a valid encrypted userid. It can be mitigated using a large Salt and/or blocking multiple attempts from the same source.
Note that this isn't a tested protocol and I didn't study the security in depth. I got some inspiration from OpenId, but this is a simplified protocol and I could be missing security holes.

Login via email + set_own_login_name + pas.plugins.sqlalchemy = change address fail

I'm using pas.plugins.sqlalchemy on a fresh new Plone 4.1 installation.
I set Plone to have the email address as login name.
It's all ok, but If I want to change the email address via personal-information panel I obtain an error:
You are not a Plone member. You are probably registered on the root user folder. Please notify an administrator if this is unexpected.
In case I would change another personal data field I don't obtain errors.
The problem seems to be the set_own_login_name function of Products.CMFPlone (utils.py).
Details here http://pastie.org/3780218
Thank's
Vito
Are you logged in as an admin user defined in the Zope root?
If that is the case, then see if you can change the login name by going to the acl_users in the Zope root and changing it there.
Otherwise, temporarily switch off emaillogin, change your email, and switch emaillogin back on.
Note that there is a comment (by me) in the utils.py code right before this KeyError is raised, which points to a possible solution that I don't really like:
# PLIP9214: For a user in the zope root we could do something like this:
# userfolder = member.getUser().__parent__.users
# userfolder.updateUser(member.id, loginname)
# But it is probably best not to touch root zope users.