login by ajax

348 views
Skip to first unread message

yashar

unread,
Feb 17, 2013, 2:25:57 PM2/17/13
to web...@googlegroups.com
login form is modal form inside index, and send login form via ajax to login() function, but i can not login.

def login():
    form=auth.login()
    if form.accepts(request,session=None):
        return 'logged'
    else: return 'failed'

below section is in index page view:
  <form action=''>
    <fieldset>
        <div id='login_result'></div>
    <label>Email</label>
    <input name='email' id='email' type="text" placeholder="Email Address">
    <label>Password</label>
    <input name='password' id='password' type="password" placeholder="*********"><br/>   
    <button id='loginbtn' class="btn" Onclick='login();return false;'>Submit</button>
    </fieldset>
    </form>

<script>
    function login(){
    $.ajax({ 
  type: "POST", 
        url: '{{=URL('default','login')}}', 
          data: 'email='+$('#email').val()+'&password='+$('#password').val(),
        success : function(data){
            if (data != 'logged){
                $('#login_result').addClass('alert alert-error').text('Email Or password were wrong! Please try again.');
    } else {
           alert('logged');
           }
        }
}); 
   
    }
</script>


i also tried auth.login_bare in login() function , but it doesnt update session. any idea to what should i do to correct this?

Anthony

unread,
Feb 17, 2013, 10:37:59 PM2/17/13
to web...@googlegroups.com
def login():
    form=auth.login()
    if form.accepts(request,session=None):

auth.login() already handles form processing, so you should not call form.accepts(), as that will not work.
 
  <form action=''>
    <fieldset>
        <div id='login_result'></div>
    <label>Email</label>
    <input name='email' id='email' type="text" placeholder="Email Address">
    <label>Password</label>
    <input name='password' id='password' type="password" placeholder="*********"><br/>   
    <button id='loginbtn' class="btn" Onclick='login();return false;'>Submit</button>
    </fieldset>
    </form>

web2py SQLFORM's (including the auth forms) include hidden _formname and _formkey fields -- if you're creating a custom form, you need to include those, or the form will not pass validation when submitted. If you want to create a custom form based on a SQLFORM, you should follow http://web2py.com/books/default/chapter/29/07#Custom-forms.

Also, rather than manually submitting the form via Ajax, you might consider putting the login form in an Ajax component (or even a non-Ajax component with ajax_trap set to True). In that case, web2py.js will handle the Ajax submission for you. In that case, you may want to create a login_onaccept function to avoid the usual post-login redirect (which wouldn't be useful for an Ajax login).

Anthony

Massimo Di Pierro

unread,
Feb 17, 2013, 10:50:20 PM2/17/13
to web...@googlegroups.com
Should we offer something like {{=auth.ajax_login()}} helper which submits to /user/login? If would not be difficult to write. 
How should it work?

yashar

unread,
Feb 18, 2013, 12:43:29 AM2/18/13
to
thank you, i solve the problem like this:

def index():
    form = auth.login()
    form.elements('input',_type='submit')[0]['_Onclick']='login();return false;'
    return dict(form=form)

def login():
    if not auth.login_bare(request.vars.email,request.vars.password):
        return 'login failed'
    form=auth.login()
    if auth.user : return 'logged'

and in the index view:

        <div id='login_result'></div>   
        {{=form}}

       
<script>
    function login(){
    $.ajax({ 
  type: "POST", 
        url: '{{=URL('default','login')}}', 
          data: $('form').serialize(),
        success : function(data){
            if (data != 'logged'){

                $('#login_result').addClass('alert alert-error').text('Email Or password were wrong! Please try again.');
    } else {
      
           }
        }
});     
        return false;
    }

</script>


yashar

unread,
Feb 18, 2013, 12:46:43 AM2/18/13
to
is there any way that i log in user by code?
for example after checking username and password with login_bare, i push the user into the session as logged-in user? in this case there is no need to write ajax/login directly, and the programmer has a better control.as you can see in my code i check user two times one in bare_login and one in auth.login, because i can not return 'login failed' value from code if i use just form=auth.login().

when the formkey is changing? during form creation or after each submit? because i create two auth.login() forms one in the index for view and one in login function, and this is working so the formkey must be same, but could you help me to write a cleaner code? in that code after success login page automaticly redirected as i dont understand why?

Paolo valleri

unread,
Feb 18, 2013, 3:13:13 AM2/18/13
to web...@googlegroups.com
+1 for auth,ajax_login()

paolo

Massimo Di Pierro

unread,
Feb 18, 2013, 12:34:48 PM2/18/13
to web...@googlegroups.com
self.login_bare(....) calls self.login_user(...) and it automatically logs in the user and stores user in session.auth.user

yashar

unread,
Feb 20, 2013, 3:44:18 AM2/20/13
to
i think login_bare needs to write again, in login() function, it first checks the login_methods and then local database and also create_or_get_user and update session.auth, but in login_bare it just check the database if user is there add it to session but not doing any of the login() steps which brings many problems like if user changed his gmail password or updating session when using other login methods.

yashar

unread,
Feb 20, 2013, 9:00:50 AM2/20/13
to web...@googlegroups.com

this is what i added in tools.py inside auth class, this is just modification of login() function and difference from main login_bare is this one also check, creates and logs in users which authenticated with other authentication methods.


    def ajax_login_bare(self, username, password):
        """
        check user login and
        return tuple of (boolean,msg) which first field is successfull login or not
        and second is failure massage
        """

        request = current.request
        session = current.session
        table_user = self.settings.table_user
        if self.settings.login_userfield:
            userfield = self.settings.login_userfield
        elif 'username' in table_user.fields:
            userfield = 'username'
        else:
            userfield = 'email'
        passfield = self.settings.password_field
        key = {userfield:request.vars[userfield],passfield:request.vars[passfield]}
        user = self.db(table_user[userfield] == request.vars[userfield]).select().first()
        if user:
            # user in db, check if registration pending or disabled
            temp_user = user
            if temp_user.registration_key == 'pending':
                return (False,self.messages.registration_pending)
            elif temp_user.registration_key in ('disabled', 'blocked'):
                return (False,self.messages.login_disabled)
            elif not temp_user.registration_key is None and temp_user.registration_key.strip():
                return (False,self.messages.registration_verifying)
        # try alternate logins 1st as these have the
        # current version of the password
            user = None
            for login_method in self.settings.login_methods:
                if login_method != self and login_method(request.vars[userfield],request.vars[passfield]):
                    if not self in self.settings.login_methods:
                        # do not store password in db
                        request.vars[passfield] = None
                    user = self.get_or_create_user(key)
                    break
            if not user:
                # alternates have failed, maybe because service inaccessible
                if self.settings.login_methods[0] == self:
                    # try logging in locally using cached credentials
                    if request.vars.get(passfield, '') == temp_user[passfield]:
                        # success
                        user = temp_user
        else:
            # user not in db
            if not self.settings.alternate_requires_registration:
                # we're allowed to auto-register users from external systems
                for login_method in self.settings.login_methods:
                    if login_method != self and login_method(request.vars[userfield],request.vars[passfield]):
                        if not self in self.settings.login_methods:
                            # do not store password in db
                            key[passfield] = None
                        user = self.get_or_create_user(key)
                        break
        if not user:
            self.log_event(self.messages.login_failed_log,request.post_vars)
            return (False,self.messages.invalid_login)
        else:
            user = Row(table_user._filter_fields(user, id=True))
            # process authenticated users
            # user wants to be logged in for longer
            self.login_user(user)
            session.auth.expiration = \
                request.vars.get('remember', False) and \
                self.settings.long_expiration or \
                self.settings.expiration
            session.auth.remember = 'remember' in request.vars
            self.log_event(self.messages.login_log, user)
            return (True,self.messages.logged_in)


Massimo Di Pierro

unread,
Feb 27, 2013, 10:56:27 AM2/27/13
to web...@googlegroups.com
Can you show an example of how to use it. I see it is not an action.

yashar

unread,
Feb 27, 2013, 3:49:04 PM2/27/13
to web...@googlegroups.com
    def ajax_login_bare(self, username, password):
        """
        check user login and
return tuple of (boolean,msg) which first field is successfull login or not
and second is failure massage 
        """

        request = current.request
        session = current.session
        table_user = self.settings.table_user
        if self.settings.login_userfield:
            userfield = self.settings.login_userfield
        elif 'username' in table_user.fields:
            userfield = 'username'
        else:
            userfield = 'email'
        passfield = self.settings.password_field
        key = {userfield:username,passfield:password}
        user = self.db(table_user[userfield] == username).select().first()
        if user:
# user in db, check if registration pending or disabled
            temp_user = user
            if temp_user.registration_key == 'pending':
                return (False,self.messages.registration_pending)
            elif temp_user.registration_key in ('disabled', 'blocked'):
                return (False,self.messages.login_disabled)
            elif not temp_user.registration_key is None and temp_user.registration_key.strip():
                return (False,self.messages.registration_verifying)
# try alternate logins 1st as these have the
        # current version of the password
            user = None
            for login_method in self.settings.login_methods:
                if login_method != self and login_method(username,password):
                    if not self in self.settings.login_methods:
   # do not store password in db
                        password = None
                    user = self.get_or_create_user(key)
                    break
            if not user:
   # alternates have failed, maybe because service inaccessible
                if self.settings.login_methods[0] == self:
               # try logging in locally using cached credentials
                    if password == temp_user[passfield]:
                   # success
                        user = temp_user
        else:
# user not in db
            if not self.settings.alternate_requires_registration:
            # we're allowed to auto-register users from external systems
                for login_method in self.settings.login_methods:
                    if login_method != self and login_method(username,password):
                        if not self in self.settings.login_methods:
                        # do not store password in db
                            key[passfield] = None
                        user = self.get_or_create_user(key)
                        break
        if not user:
            self.log_event(self.messages.login_failed_log,request.post_vars)
            return (False,self.messages.invalid_login)
        else:
            user = Row(table_user._filter_fields(user, id=True))
            # process authenticated users
            # user wants to be logged in for longer
            self.login_user(user)
            session.auth.expiration = \
                request.vars.get('remember', False) and \
                self.settings.long_expiration or \
                self.settings.expiration
            session.auth.remember = 'remember' in request.vars
            self.log_event(self.messages.login_log, user)
            return (True,self.messages.logged_in)



def index():
if request.post_vars:
from gluon.serializers import json
logged,msg = auth.ajax_login_bare(request.vars.email,request.vars.password)
if logged:
return json(dict(redirect=get_user_info(),logged=logged,msg=msg))
else:
return json(dict(logged=logged,msg=msg))

form = auth.login()

return dict(form=form) 

Massimo Di Pierro

unread,
Feb 27, 2013, 7:45:50 PM2/27/13
to web...@googlegroups.com
I still do not understand. Why index() is under returning some times json and some times dict with a form? Who makes the ajax callback? If this to be embedded in a large page? What is the JS?

yashar

unread,
Mar 1, 2013, 5:12:26 PM3/1/13
to web...@googlegroups.com
sorry for delay:


<!-- Modal -->
<div id="Modallogin" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Log in </h3>
    </div>
    <div class="modal-body">
    <p>You could login by your yahoo or gmail account.
    </p>
        <div id='login_result'></div>    
        {{=form}}
        

</div>
</div>

<script>
    function login_process(user_type){
    $('#Modallogin').modal('show');
    $('#auth_user_type').val(user_type);
    }
    
    function login(){
    var data = $('form').serialize();     
    $('form input').each(function(){$(this).attr('disabled',true);});
    $('#login_result').removeClass('alert alert-error').text('');
    $('#login_result').addClass('alert alert-info').text('Connecting...');
    $.ajax({  
  type: "POST",  
        url: '{{=URL('default','index')}}',  
  data: data,
        success : function(response){
        $('form input').each(function(){$(this).attr('disabled',false);});
        try{
        response = jQuery.parseJSON(response);
        }
        catch(e){
            var response = {'msg':'failed to proceed'};
        }
        if (!response.logged){
        $('#login_result').removeClass('alert alert-info').addClass('alert alert-error').text(response.msg);
    }else{
            window.location=response.redirect;
            }
    }
});      
    return false;
    }

</script>

Alan Etkin

unread,
Mar 1, 2013, 6:24:44 PM3/1/13
to web...@googlegroups.com
+1 for auth,ajax_login()

I'm also interested in a bare ajax login feature, but, what about the security risks of passing credentials with javascript in the background? What are the issues to take in account for that feature? I there any standard way of securing the passwords and other sensible data that can be used?

Niphlod

unread,
Mar 2, 2013, 8:04:01 AM3/2/13
to web...@googlegroups.com
The data is transmitted on the wire in the same exact manner via an ajax POST or the usual POST. The only security needed is SSL, for both, if you don't want to pass credentials in clear format.

Phyo Arkar

unread,
Mar 2, 2013, 9:46:53 AM3/2/13
to web...@googlegroups.com
If you worry about your credentials visibility over the wire , SSL.
If you worry about your credentials visibility on the screen , None actually.

On Sat, Mar 2, 2013 at 5:54 AM, Alan Etkin <spam...@gmail.com> wrote:
+1 for auth,ajax_login()

I'm also interested in a bare ajax login feature, but, what about the security risks of passing credentials with javascript in the background? What are the issues to take in account for that feature? I there any standard way of securing the passwords and other sensible data that can be used?

--
 
---
You received this message because you are subscribed to the Google Groups "web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Val K

unread,
May 4, 2016, 1:19:02 PM5/4/16
to web...@googlegroups.com
Hi!
It seems, that  ajax_login doesn't exist yet?
I trying solve this problem as follows:
  1. Checking if request is self-redirection  (see step 2) - if so  - analysing request.args that are form processing result  
  2. Setting  auth.settings.login_onfail / auth.settings.login_onaccept to custom functions with self-redirection (client_side=False) 
  3. Parsing ajax-request and setting proper request.post_vars  - doing this  if request isn't self-redirection
  4. w2p_form= auth.login()
  5. Creating my_ajax_response using w2p_form (formkey and other )
  6. return my_ajax_response
It works! but I have to re-request form when login fails, because onfail-callback is called  with form=None and I can't retrieve formkey   (see  source below) 
So, I have a little question: Why?  Otherwise,  I would have been able to pass formkey at once (that is ordinal behaviour  SQLFORM )
I changed None  to form and it works as expected!
  

                  if not user:
                        self.log_event(self.messages['login_failed_log'],
                                       request.post_vars)
                        # invalid login
                        session.flash = self.messages.invalid_login
                        callback(onfail, None)
                        redirect(
                            self.url(args=request.args, vars=request.get_vars),
                            client_side=settings.client_side)

Here is whole example:
#ajax login, uses with w2ui library 
def login():
    #------ self-redirection from onaccept/onfail from auth.login()  ----------
    if request.args(0):
        ret = Storage()
        ret.postData = dict(_formkey = request.vars.pop('_formkey', None))
        ret.record  = dict(username = request.vars.username)
        if request.args(0)=='OK':
            ret.status = 'success'
                        ret.message = 'Welcome %s' % auth_user(auth.user_id).username
            ret.next = URL(...)
        elif request.args(0)=='error':
            ret.status = 'error'
            ret.message = 'not found'
        return ret

    #------ parsing ajax-request and setting post_vars (auth.login reads them) ----------
    jq_vars = jq_param_w2p(request.body)
    if jq_vars.cmd == 'save-record':
        request.post_vars.clear()
        request.post_vars.update(jq_vars.record)
        request.post_vars._formkey = jq_vars._formkey
        request.post_vars._formname = jq_vars.name

    #------ setting self-redirection ----------
    auth.settings.login_onaccept = \
            lambda frm: redirect(URL('login.json', args=['OK'],
                                     vars = dict(_formkey =  frm.formkey, **frm.vars)
                                     ),
                                 client_side=False
                                )
    auth.settings.login_onfail = \
            lambda frm: redirect(URL('login.json', args=['error'],
                                     vars = dict(_formkey =  frm.formkey, **frm.vars)
                                     ),
                                 client_side=False
                                 )
    login_frm = auth.login()

    # code below will be executed if only auth.login() doesn't accept post_vars
    # ---------- create own response form -------------------------
    if not jq_vars.cmd: # if we're here then it's first request
        w2ui_frm = Storage()
        w2ui_frm.name = login_frm.formname
        w2ui_frm.postData =  Storage(_formkey = login_frm.formkey)
        w2ui_frm.fields=[]
        for fld_name, type, label in [['username', 'text','User'], ['password', 'password',  'Pwd' ]]:
                        w2ui_fld = Storage(name = fld_name)
            w2ui_fld.type = type
            w2ui_fld.required = True
            w2ui_fld.html=dict(caption = label)
            w2ui_frm.fields.append(w2ui_fld)
        w2ui_frm.url = URL('login.json')
        w2ui_frm.actions ='default'
        return w2ui_frm

    # ---- if we're here then formkey didn't match  - send actual one ------
    else:
        ret = Storage()
        ret.status = 'error'
        ret.message = 'Tampering!'
        ret.postData = Storage(_formkey = login_frm.formkey)
        ret.record  = dict(username = login_frm.vars.username)
        return ret


Reply all
Reply to author
Forward
0 new messages