def set_password(cls, user=None, password=None, provider_name=None ): """generic method to change password of any for any login provider that uses password and allows the password change function """ login_providers = util.get_enabled_login_providers() if login_providers[provider_name]['type'] != 'password': raise ImproperlyConfigured('login provider must use password') if provider_name == 'local': user.set_password(password) user.save() scrambled_password = user.password + str(user.id) else: raise NotImplementedError('external passwords not supported') try: assoc = UserAssociation.objects.get( user = user, provider_name = provider_name ) except UserAssociation.DoesNotExist: assoc = UserAssociation( user = user, provider_name = provider_name ) assoc.openid_url = scrambled_password assoc.last_used_timestamp = datetime.datetime.now() assoc.save()
def set_password(cls, user=None, password=None, provider_name=None): """generic method to change password of any for any login provider that uses password and allows the password change function """ login_providers = util.get_enabled_login_providers() if login_providers[provider_name]['type'] != 'password': raise ImproperlyConfigured('login provider must use password') if provider_name == 'local': user.set_password(password) user.save() scrambled_password = user.password + str(user.id) else: raise NotImplementedError('external passwords not supported') try: assoc = UserAssociation.objects.get(user=user, provider_name=provider_name) except UserAssociation.DoesNotExist: assoc = UserAssociation(user=user, provider_name=provider_name) assoc.openid_url = scrambled_password assoc.last_used_timestamp = datetime.datetime.now() assoc.save()
def clean(self, value): """make sure that value is name of one of the known password login providers """ value = super(PasswordLoginProviderField, self).clean(value) providers = util.get_enabled_login_providers() if providers[value]["type"] != "password": raise forms.ValidationError("provider %s must accept password" % value) return value
def clean(self, value): """make sure that value is name of one of the known password login providers """ value = super(PasswordLoginProviderField, self).clean(value) providers = util.get_enabled_login_providers() if providers[value]['type'] != 'password': raise forms.ValidationError('provider %s must accept password' % value) return value
def clean(self, value): """makes sure that login provider name exists is in the list of accepted providers """ providers = util.get_enabled_login_providers() if value in providers: return value else: error_message = 'unknown provider name %s' % cgi.escape(value) logging.critical(error_message) raise forms.ValidationError(error_message)
def clean(self, value): """makes sure that login provider name exists is in the list of accepted providers """ providers = util.get_enabled_login_providers() if value in providers: return value else: error_message = 'unknown provider name %s' % value logging.critical(error_message) raise forms.ValidationError(error_message)
def clean(self, value): """makes sure that login provider name exists is in the list of accepted providers """ if askbot_settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN: value = 'local' providers = util.get_enabled_login_providers() if value in providers: return value else: error_message = 'unknown provider name %s' % value logging.critical(error_message) raise forms.ValidationError(error_message)
def complete_oauth2_signin(request): if "next_url" in request.session: next_url = request.session["next_url"] del request.session["next_url"] else: next_url = reverse("index") if "error" in request.GET: return HttpResponseRedirect(reverse("index")) csrf_token = request.GET.get("state", None) if csrf_token is None or csrf_token != request.session.pop("oauth2_csrf_token"): return HttpResponseBadRequest() providers = util.get_enabled_login_providers() provider_name = request.session.pop("provider_name") params = providers[provider_name] assert params["type"] == "oauth2" client_id = getattr(askbot_settings, provider_name.upper() + "_KEY") client_secret = getattr(askbot_settings, provider_name.upper() + "_SECRET") client = OAuth2Client( token_endpoint=params["token_endpoint"], resource_endpoint=params["resource_endpoint"], redirect_uri=site_url(reverse("user_complete_oauth2_signin")), client_id=client_id, client_secret=client_secret, ) client.request_token(code=request.GET["code"], parser=params["response_parser"]) # todo: possibly set additional parameters here user_id = params["get_user_id_function"](client) user = authenticate(oauth_user_id=user_id, provider_name=provider_name, method="oauth") logging.debug("finalizing oauth signin") request.session["email"] = "" # todo: pull from profile request.session["username"] = "" # todo: pull from profile return finalize_generic_signin( request=request, user=user, user_identifier=user_id, login_provider_name=provider_name, redirect_url=next_url )
def clean(self): """besides input data takes data from the login provider settings and stores final digested data into the cleaned_data the idea is that cleaned data can be used directly to enact the signin action, without post-processing of the data contents of cleaned_data depends on the type of login """ providers = util.get_enabled_login_providers() if 'login_provider_name' in self.cleaned_data: provider_name = self.cleaned_data['login_provider_name'] else: raise forms.ValidationError('no login provider specified') provider_data = providers[provider_name] provider_type = provider_data['type'] if provider_type == 'password': self.do_clean_password_fields() self.cleaned_data['login_type'] = 'password' elif provider_type.startswith('openid'): self.do_clean_openid_fields(provider_data) self.cleaned_data['login_type'] = 'openid' elif provider_type == 'oauth': self.cleaned_data['login_type'] = 'oauth' elif provider_type == 'oauth2': self.cleaned_data['login_type'] = 'oauth2' elif provider_type == 'facebook': self.cleaned_data['login_type'] = 'facebook' #self.do_clean_oauth_fields() elif provider_type == 'wordpress_site': self.cleaned_data['login_type'] = 'wordpress_site' elif provider_type == 'mozilla-persona': self.cleaned_data['login_type'] = 'mozilla-persona' self.cleaned_data['sreg_required'] = 'sreg_required' in provider_data return self.cleaned_data
def clean(self): """besides input data takes data from the login provider settings and stores final digested data into the cleaned_data the idea is that cleaned data can be used directly to enact the signin action, without post-processing of the data contents of cleaned_data depends on the type of login """ providers = util.get_enabled_login_providers() if "login_provider_name" in self.cleaned_data: provider_name = self.cleaned_data["login_provider_name"] else: raise forms.ValidationError("no login provider specified") provider_data = providers[provider_name] provider_type = provider_data["type"] if provider_type == "password": self.do_clean_password_fields() self.cleaned_data["login_type"] = "password" elif provider_type.startswith("openid"): self.do_clean_openid_fields(provider_data) self.cleaned_data["login_type"] = "openid" elif provider_type == "oauth": self.cleaned_data["login_type"] = "oauth" pass elif provider_type == "facebook": self.cleaned_data["login_type"] = "facebook" # self.do_clean_oauth_fields() elif provider_type == "wordpress_site": self.cleaned_data["login_type"] = "wordpress_site" return self.cleaned_data
def authenticate( self, username = None,#for 'password' password = None,#for 'password' user_id = None,#for 'force' provider_name = None,#required with all except email_key openid_url = None, email_key = None, oauth_user_id = None,#used with oauth facebook_user_id = None,#user with facebook ldap_user_id = None,#for ldap method = None,#requried parameter ): """this authentication function supports many login methods just which method it is going to use it determined from the signature of the function call """ login_providers = util.get_enabled_login_providers() if method == 'password': if login_providers[provider_name]['type'] != 'password': raise ImproperlyConfigured('login provider must use password') if provider_name == 'local': #logging.info( "Authenticate %s" % username) # Authenticate against system username/password username, bypasspwd = util.check_pwd_bypass(username) if bypasspwd == False: try: p = pwd.getpwnam(username) except KeyError: return None if(crypt.crypt(password, p.pw_passwd) != p.pw_passwd): return None # If user is not in Askbot, create it. try: user = User.objects.get(username=username) except User.DoesNotExist: first, last, email = util.get_user_info(method, username) if first == None: return None user = util.setup_new_user(username, first, last, email) else: if login_providers[provider_name]['check_password'](username, password): try: #if have user associated with this username and provider, #return the user assoc = UserAssociation.objects.get( openid_url = username + '@' + provider_name,#a hack - par name is bad provider_name = provider_name ) return assoc.user except UserAssociation.DoesNotExist: #race condition here a user with this name may exist user, created = User.objects.get_or_create(username = username) if created: user.set_password(password) user.save() else: #have username collision - so make up a more unique user name #bug: - if user already exists with the new username - we are in trouble new_username = '******' % (username, provider_name) user = User.objects.create_user(new_username, '', password) message = _( 'Welcome! Please set email address (important!) in your ' 'profile and adjust screen name, if necessary.' ) user.message_set.create(message = message) else: return None #this is a catch - make login token a little more unique #for the cases when passwords are the same for two users #from the same provider try: assoc = UserAssociation.objects.get( user = user, provider_name = provider_name ) except UserAssociation.DoesNotExist: assoc = UserAssociation( user = user, provider_name = provider_name ) assoc.openid_url = username + '@' + provider_name#has to be this way for external pw logins elif method == 'openid': provider_name = util.get_provider_name(openid_url) try: assoc = UserAssociation.objects.get( openid_url = openid_url, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'email': #with this method we do no use user association try: #todo: add email_key_timestamp field #and check key age user = User.objects.get(email_key = email_key) user.email_key = None #one time key so delete it user.email_isvalid = True user.save() return user except User.DoesNotExist: return None elif method == 'oauth': if login_providers[provider_name]['type'] == 'oauth': try: assoc = UserAssociation.objects.get( openid_url = oauth_user_id, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: return None else: return None elif method == 'facebook': try: #assert(provider_name == 'facebook') assoc = UserAssociation.objects.get( openid_url = facebook_user_id, provider_name = 'facebook' ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'ldap': try: assoc = UserAssociation.objects.get( openid_url = ldap_user_id, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: first, last, email = util.get_user_info(method, ldap_user_id) if(first == None): return None user = util.setup_new_user(ldap_user_id, first, last, email) assoc = UserAssociation( openid_url = ldap_user_id, user = user, provider_name = provider_name ) elif method == 'force': return self.get_user(user_id) else: raise TypeError('only openid and password supported') #update last used time assoc.last_used_timestamp = datetime.datetime.now() assoc.save() return user
def authenticate( self, username=None, # for 'password' and 'ldap' password=None, # for 'password' and 'ldap' user_id=None, # for 'force' provider_name=None, # required with all except email_key openid_url=None, email_key=None, oauth_user_id=None, # used with oauth facebook_user_id=None, # user with facebook wordpress_url=None, # required for self hosted wordpress wp_user_id=None, # required for self hosted wordpress method=None, # requried parameter ): """this authentication function supports many login methods just which method it is going to use it determined from the signature of the function call """ login_providers = util.get_enabled_login_providers() assoc = None # UserAssociation not needed for ldap if method == "password": if login_providers[provider_name]["type"] != "password": raise ImproperlyConfigured("login provider must use password") if provider_name == "local": try: user = User.objects.get(username=username) if not user.check_password(password): return None except User.DoesNotExist: try: email_address = username user = User.objects.get(email=email_address) if not user.check_password(password): return None except User.DoesNotExist: return None except User.MultipleObjectsReturned: LOG.critical( ( "have more than one user with email %s " + "he/she will not be able to authenticate with " + "the email address in the place of user name" ) % email_address ) return None else: if login_providers[provider_name]["check_password"](username, password): try: # if have user associated with this username and provider, # return the user assoc = UserAssociation.objects.get( openid_url=username + "@" + provider_name, # a hack - par name is bad provider_name=provider_name, ) return assoc.user except UserAssociation.DoesNotExist: # race condition here a user with this name may exist user, created = User.objects.get_or_create(username=username) if created: user.set_password(password) user.save() user_registered.send(None, user=user) else: # have username collision - so make up a more unique user name # bug: - if user already exists with the new username - we are in trouble new_username = "******" % (username, provider_name) user = User.objects.create_user(new_username, "", password) user_registered.send(None, user=user) message = _( "Welcome! Please set email address (important!) in your " "profile and adjust screen name, if necessary." ) user.message_set.create(message=message) else: return None # this is a catch - make login token a little more unique # for the cases when passwords are the same for two users # from the same provider try: assoc = UserAssociation.objects.get(user=user, provider_name=provider_name) except UserAssociation.DoesNotExist: assoc = UserAssociation(user=user, provider_name=provider_name) assoc.openid_url = username + "@" + provider_name # has to be this way for external pw logins elif method == "openid": try: assoc = UserAssociation.objects.get(openid_url=openid_url) user = assoc.user except UserAssociation.DoesNotExist: return None except UserAssociation.MultipleObjectsReturned: logging.critical("duplicate openid url in the database!!! %s" % openid_url) return None elif method == "email": # with this method we do no use user association try: # todo: add email_key_timestamp field # and check key age user = User.objects.get(email_key=email_key) user.email_key = None # one time key so delete it user.email_isvalid = True user.save() return user except User.DoesNotExist: return None elif method == "oauth": if login_providers[provider_name]["type"] in ("oauth", "oauth2"): try: assoc = UserAssociation.objects.get(openid_url=oauth_user_id, provider_name=provider_name) user = assoc.user except UserAssociation.DoesNotExist: return None else: return None elif method == "facebook": try: # assert(provider_name == 'facebook') assoc = UserAssociation.objects.get(openid_url=facebook_user_id, provider_name="facebook") user = assoc.user except UserAssociation.DoesNotExist: return None elif method == "ldap": # user_info = ldap_authenticate(username, password) user_info = util.ldap_check_password(username, password) if user_info["success"] == False: # Maybe a user created internally (django admin user) try: user = User.objects.get(username__exact=username) if user.check_password(password): return user else: return None except User.DoesNotExist: return None else: # load user by association or maybe auto-create one ldap_username = user_info["ldap_username"] try: # todo: provider_name is hardcoded - possible conflict assoc = UserAssociation.objects.get(openid_url=ldap_username, provider_name="Wind River LDAP") user = assoc.user except UserAssociation.DoesNotExist: # email address is required if "email" in user_info and askbot_settings.LDAP_AUTOCREATE_USERS: assoc = ldap_create_user(user_info) user = assoc.user else: return None elif method == "wordpress_site": try: custom_wp_openid_url = "%s?user_id=%s" % (wordpress_url, wp_user_id) assoc = UserAssociation.objects.get(openid_url=custom_wp_openid_url, provider_name="wordpress_site") user = assoc.user except UserAssociation.DoesNotExist: return None elif method == "force": return self.get_user(user_id) else: raise TypeError("only openid and password supported") if assoc: # update last used time assoc.last_used_timestamp = datetime.datetime.now() assoc.save() return user
def __init__(self, *args, **kwargs): self.login_providers = util.get_enabled_login_providers() super(AuthBackend, self).__init__(*args, **kwargs)
def show_signin_view(request, login_form=None, account_recovery_form=None, account_recovery_message=None, sticky=False, view_subtype='default'): """url-less utility function that populates context of template 'authopenid/signin.html' and returns its rendered output """ allowed_subtypes = ('default', 'add_openid', 'email_sent', 'change_openid', 'bad_key') assert (view_subtype in allowed_subtypes) if sticky: next_url = reverse('user_signin') else: next_url = get_next_url(request) if login_form is None: login_form = forms.LoginForm(initial={'next': next_url}) if account_recovery_form is None: account_recovery_form = forms.AccountRecoveryForm( ) #initial = initial_data) #if request is GET if request.method == 'GET': logging.debug('request method was GET') #todo: this sthuff must be executed on some signal #because askbot should have nothing to do with the login app from askbot.models import AnonymousQuestion as AQ session_key = request.session.session_key logging.debug( 'retrieving anonymously posted question associated with session %s' % session_key) qlist = AQ.objects.filter(session_key=session_key).order_by('-added_at') if len(qlist) > 0: question = qlist[0] else: question = None from askbot.models import AnonymousAnswer as AA session_key = request.session.session_key logging.debug('retrieving posted answer associated with session %s' % session_key) alist = AA.objects.filter(session_key=session_key).order_by('-added_at') if len(alist) > 0: answer = alist[0] else: answer = None if request.user.is_authenticated(): existing_login_methods = UserAssociation.objects.filter( user=request.user) #annotate objects with extra data providers = util.get_enabled_login_providers() for login_method in existing_login_methods: try: provider_data = providers[login_method.provider_name] if provider_data['type'] == 'password': #only external password logins will not be deletable #this is because users with those can lose access to their accounts permanently login_method.is_deletable = provider_data.get( 'password_changeable', False) else: login_method.is_deletable = True except KeyError: logging.critical( 'login method %s is no longer available ' 'please delete records for this login method ' 'from the UserAssociation table', login_method.provider_name) continue if view_subtype == 'default': page_title = _('Please click any of the icons below to sign in') elif view_subtype == 'email_sent': page_title = _('Account recovery email sent') elif view_subtype == 'change_openid': if len(existing_login_methods) == 0: page_title = _('Please add one or more login methods.') else: page_title = _( 'If you wish, please add, remove or re-validate your login methods' ) elif view_subtype == 'add_openid': page_title = _( 'Please wait a second! Your account is recovered, but ...') elif view_subtype == 'bad_key': page_title = _( 'Sorry, this account recovery key has expired or is invalid') logging.debug('showing signin view') data = { 'page_class': 'openid-signin', 'view_subtype': view_subtype, #add_openid|default 'page_title': page_title, 'question': question, 'answer': answer, 'login_form': login_form, 'use_password_login': util.use_password_login(), 'account_recovery_form': account_recovery_form, 'openid_error_message': request.REQUEST.get('msg', ''), 'account_recovery_message': account_recovery_message, 'use_password_login': util.use_password_login(), } major_login_providers = util.get_enabled_major_login_providers() minor_login_providers = util.get_enabled_minor_login_providers() #determine if we are only using password login active_provider_names = [p['name'] for p in major_login_providers.values()] active_provider_names.extend( [p['name'] for p in minor_login_providers.values()]) have_buttons = True if (len(active_provider_names) == 1 and active_provider_names[0] == 'local'): if askbot_settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN == True: #in this case the form is not using javascript, so set initial values #here have_buttons = False login_form.initial['login_provider_name'] = 'local' if request.user.is_authenticated(): login_form.initial['password_action'] = 'change_password' else: login_form.initial['password_action'] = 'login' data['have_buttons'] = have_buttons if request.user.is_authenticated(): data['existing_login_methods'] = existing_login_methods active_provider_names = [ item.provider_name for item in existing_login_methods ] util.set_login_provider_tooltips( major_login_providers, active_provider_names=active_provider_names) util.set_login_provider_tooltips( minor_login_providers, active_provider_names=active_provider_names) data['major_login_providers'] = major_login_providers.values() data['minor_login_providers'] = minor_login_providers.values() return render_into_skin('authopenid/signin.html', data, request)
def authenticate( self, username = None,#for 'password' and 'ldap' password = None,#for 'password' and 'ldap' user_id = None,#for 'force' provider_name = None,#required with all except email_key openid_url = None, email_key = None, oauth_user_id = None,#used with oauth facebook_user_id = None,#user with facebook wordpress_url = None, # required for self hosted wordpress wp_user_id = None, # required for self hosted wordpress method = None,#requried parameter ): """this authentication function supports many login methods just which method it is going to use it determined from the signature of the function call """ login_providers = util.get_enabled_login_providers() assoc = None # UserAssociation not needed for ldap if method == 'password': if login_providers[provider_name]['type'] != 'password': raise ImproperlyConfigured('login provider must use password') if provider_name == 'local': try: user = User.objects.get(username=username) if not user.check_password(password): return None except User.DoesNotExist: try: email_address = username user = User.objects.get(email = email_address) if not user.check_password(password): return None except User.DoesNotExist: return None except User.MultipleObjectsReturned: logging.critical( ('have more than one user with email %s ' + 'he/she will not be able to authenticate with ' + 'the email address in the place of user name') % email_address ) return None else: if login_providers[provider_name]['check_password'](username, password): try: #if have user associated with this username and provider, #return the user assoc = UserAssociation.objects.get( openid_url = username + '@' + provider_name,#a hack - par name is bad provider_name = provider_name ) return assoc.user except UserAssociation.DoesNotExist: #race condition here a user with this name may exist user, created = User.objects.get_or_create(username = username) if created: user.set_password(password) user.save() user_registered.send(None, user = user) else: #have username collision - so make up a more unique user name #bug: - if user already exists with the new username - we are in trouble new_username = '******' % (username, provider_name) user = User.objects.create_user(new_username, '', password) user_registered.send(None, user = user) message = _( 'Welcome! Please set email address (important!) in your ' 'profile and adjust screen name, if necessary.' ) user.message_set.create(message = message) else: return None #this is a catch - make login token a little more unique #for the cases when passwords are the same for two users #from the same provider try: assoc = UserAssociation.objects.get( user = user, provider_name = provider_name ) except UserAssociation.DoesNotExist: assoc = UserAssociation( user = user, provider_name = provider_name ) assoc.openid_url = username + '@' + provider_name#has to be this way for external pw logins elif method == 'openid': provider_name = util.get_provider_name(openid_url) try: assoc = UserAssociation.objects.get( openid_url = openid_url, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'email': #with this method we do no use user association try: #todo: add email_key_timestamp field #and check key age user = User.objects.get(email_key = email_key) user.email_key = None #one time key so delete it user.email_isvalid = True user.save() return user except User.DoesNotExist: return None elif method == 'oauth': if login_providers[provider_name]['type'] == 'oauth': try: assoc = UserAssociation.objects.get( openid_url = oauth_user_id, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: return None else: return None elif method == 'facebook': try: #assert(provider_name == 'facebook') assoc = UserAssociation.objects.get( openid_url = facebook_user_id, provider_name = 'facebook' ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'ldap': user = ldap_authenticate(username, password) elif method == 'wordpress_site': try: custom_wp_openid_url = '%s?user_id=%s' % (wordpress_url, wp_user_id) assoc = UserAssociation.objects.get( openid_url = custom_wp_openid_url, provider_name = 'wordpress_site' ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'force': return self.get_user(user_id) else: raise TypeError('only openid and password supported') if assoc: #update last used time assoc.last_used_timestamp = datetime.datetime.now() assoc.save() return user
def authenticate( self, username = None,#for 'password' password = None,#for 'password' user_id = None,#for 'force' provider_name = None,#required with all except email_key openid_url = None, email_key = None, oauth_user_id = None,#used with oauth facebook_user_id = None,#user with facebook ldap_user_id = None,#for ldap method = None,#requried parameter ): """this authentication function supports many login methods just which method it is going to use it determined from the signature of the function call """ login_providers = util.get_enabled_login_providers() if method == 'password': if login_providers[provider_name]['type'] != 'password': raise ImproperlyConfigured('login provider must use password') if provider_name == 'local': try: user = User.objects.get(username=username) if not user.check_password(password): return None except User.DoesNotExist: return None else: #todo there must be a call to some sort of #an external "check_password" function raise NotImplementedError('do not support external passwords') #this is a catch - make login token a little more unique #for the cases when passwords are the same for two users #from the same provider try: assoc = UserAssociation.objects.get( user = user, provider_name = provider_name ) except UserAssociation.DoesNotExist: assoc = UserAssociation( user = user, provider_name = provider_name ) assoc.openid_url = user.password + str(user.id) elif method == 'openid': provider_name = util.get_provider_name(openid_url) try: assoc = UserAssociation.objects.get( openid_url = openid_url, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'email': #with this method we do no use user association try: #todo: add email_key_timestamp field #and check key age user = User.objects.get(email_key = email_key) user.email_key = None #one time key so delete it user.email_isvalid = True user.save() return user except User.DoesNotExist: return None elif method == 'oauth': if login_providers[provider_name]['type'] == 'oauth': try: assoc = UserAssociation.objects.get( openid_url = oauth_user_id, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: return None else: return None elif method == 'facebook': try: #assert(provider_name == 'facebook') assoc = UserAssociation.objects.get( openid_url = facebook_user_id, provider_name = 'facebook' ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'ldap': try: assoc = UserAssociation.objects.get( openid_url = ldap_user_id, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'force': return self.get_user(user_id) else: raise TypeError('only openid and password supported') #update last used time assoc.last_used_timestamp = datetime.datetime.now() assoc.save() return user
def show_signin_view( request, login_form = None, account_recovery_form = None, account_recovery_message = None, sticky = False, view_subtype = 'default' ): """url-less utility function that populates context of template 'authopenid/signin.html' and returns its rendered output """ allowed_subtypes = ( 'default', 'add_openid', 'email_sent', 'change_openid', 'bad_key' ) assert(view_subtype in allowed_subtypes) if sticky: next_url = reverse('user_signin') else: next_url = get_next_url(request) if login_form is None: login_form = forms.LoginForm(initial = {'next': next_url}) if account_recovery_form is None: account_recovery_form = forms.AccountRecoveryForm()#initial = initial_data) #if request is GET if request.method == 'GET': logging.debug('request method was GET') #todo: this sthuff must be executed on some signal #because askbot should have nothing to do with the login app from askbot.models import AnonymousQuestion as AQ session_key = request.session.session_key logging.debug('retrieving anonymously posted question associated with session %s' % session_key) qlist = AQ.objects.filter(session_key=session_key).order_by('-added_at') if len(qlist) > 0: question = qlist[0] else: question = None from askbot.models import AnonymousAnswer as AA session_key = request.session.session_key logging.debug('retrieving posted answer associated with session %s' % session_key) alist = AA.objects.filter(session_key=session_key).order_by('-added_at') if len(alist) > 0: answer = alist[0] else: answer = None if request.user.is_authenticated(): existing_login_methods = UserAssociation.objects.filter(user = request.user) #annotate objects with extra data providers = util.get_enabled_login_providers() for login_method in existing_login_methods: if login_method.provider_name == 'facebook': continue#it is disabled provider_data = providers[login_method.provider_name] if provider_data['type'] == 'password': #only external password logins will not be deletable #this is because users with those can lose access to their accounts permanently login_method.is_deletable = provider_data.get('password_changeable', False) else: login_method.is_deletable = True if view_subtype == 'default': page_title = _('Please click any of the icons below to sign in') elif view_subtype == 'email_sent': page_title = _('Account recovery email sent') elif view_subtype == 'change_openid': if len(existing_login_methods) == 0: page_title = _('Please add one or more login methods.') else: page_title = _('If you wish, please add, remove or re-validate your login methods') elif view_subtype == 'add_openid': page_title = _('Please wait a second! Your account is recovered, but ...') elif view_subtype == 'bad_key': page_title = _('Sorry, this account recovery key has expired or is invalid') logging.debug('showing signin view') data = { 'page_class': 'openid-signin', 'view_subtype': view_subtype, #add_openid|default 'page_title': page_title, 'question':question, 'answer':answer, 'login_form': login_form, 'use_password_login': util.use_password_login(), 'account_recovery_form': account_recovery_form, 'openid_error_message': request.REQUEST.get('msg',''), 'account_recovery_message': account_recovery_message, 'use_password_login': util.use_password_login(), } major_login_providers = util.get_enabled_major_login_providers() minor_login_providers = util.get_enabled_minor_login_providers() #determine if we are only using password login active_provider_names = [p['name'] for p in major_login_providers.values()] active_provider_names.extend([p['name'] for p in minor_login_providers.values()]) have_buttons = True if (len(active_provider_names) == 1 and active_provider_names[0] == 'local'): if askbot_settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN == True: #in this case the form is not using javascript, so set initial values #here have_buttons = False login_form.initial['login_provider_name'] = 'local' if request.user.is_authenticated(): login_form.initial['password_action'] = 'change_password' else: login_form.initial['password_action'] = 'login' data['have_buttons'] = have_buttons if request.user.is_authenticated(): data['existing_login_methods'] = existing_login_methods active_provider_names = [ item.provider_name for item in existing_login_methods ] util.set_login_provider_tooltips( major_login_providers, active_provider_names = active_provider_names ) util.set_login_provider_tooltips( minor_login_providers, active_provider_names = active_provider_names ) data['major_login_providers'] = major_login_providers.values() data['minor_login_providers'] = minor_login_providers.values() return render_into_skin('authopenid/signin.html', data, request)
def authenticate( self, username=None, #for 'password' password=None, #for 'password' user_id=None, #for 'force' provider_name=None, #required with all except email_key openid_url=None, email_key=None, oauth_user_id=None, #used with oauth facebook_user_id=None, #user with facebook ldap_user_id=None, #for ldap method=None, #requried parameter ): """this authentication function supports many login methods just which method it is going to use it determined from the signature of the function call """ login_providers = util.get_enabled_login_providers() if method == 'password': if login_providers[provider_name]['type'] != 'password': raise ImproperlyConfigured('login provider must use password') if provider_name == 'local': try: user = User.objects.get(username=username) if not user.check_password(password): return None except User.DoesNotExist: return None else: #todo there must be a call to some sort of #an external "check_password" function raise NotImplementedError('do not support external passwords') #this is a catch - make login token a little more unique #for the cases when passwords are the same for two users #from the same provider try: assoc = UserAssociation.objects.get( user=user, provider_name=provider_name) except UserAssociation.DoesNotExist: assoc = UserAssociation(user=user, provider_name=provider_name) assoc.openid_url = user.password + str(user.id) elif method == 'openid': provider_name = util.get_provider_name(openid_url) try: assoc = UserAssociation.objects.get( openid_url=openid_url, provider_name=provider_name) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'email': #with this method we do no use user association try: #todo: add email_key_timestamp field #and check key age user = User.objects.get(email_key=email_key) user.email_key = None #one time key so delete it user.email_isvalid = True user.save() return user except User.DoesNotExist: return None elif method == 'oauth': if login_providers[provider_name]['type'] == 'oauth': try: assoc = UserAssociation.objects.get( openid_url=oauth_user_id, provider_name=provider_name) user = assoc.user except UserAssociation.DoesNotExist: return None else: return None elif method == 'facebook': try: #assert(provider_name == 'facebook') assoc = UserAssociation.objects.get( openid_url=facebook_user_id, provider_name='facebook') user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'ldap': try: assoc = UserAssociation.objects.get( openid_url=ldap_user_id, provider_name=provider_name) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'force': return self.get_user(user_id) else: raise TypeError('only openid and password supported') #update last used time assoc.last_used_timestamp = datetime.datetime.now() assoc.save() return user
def authenticate( self, username = None,#for 'password' and 'ldap' password = None,#for 'password' and 'ldap' user_id = None,#for 'force' provider_name = None,#required with all except email_key openid_url = None, email_key = None, oauth_user_id = None,#used with oauth facebook_user_id = None,#user with facebook wordpress_url = None, # required for self hosted wordpress wp_user_id = None, # required for self hosted wordpress cas_ticket = None, # the CAS ticket method = None,#requried parameter ): """this authentication function supports many login methods just which method it is going to use it determined from the signature of the function call """ login_providers = util.get_enabled_login_providers() assoc = None # UserAssociation not needed for ldap if method == 'password': if login_providers[provider_name]['type'] != 'password': raise ImproperlyConfigured('login provider must use password') if provider_name == 'local': try: user = User.objects.get(username=username) if not user.check_password(password): return None except User.DoesNotExist: try: email_address = username user = User.objects.get(email = email_address) if not user.check_password(password): return None except User.DoesNotExist: return None except User.MultipleObjectsReturned: LOG.critical( ('have more than one user with email %s ' + 'he/she will not be able to authenticate with ' + 'the email address in the place of user name') % email_address ) return None else: if login_providers[provider_name]['check_password'](username, password): try: #if have user associated with this username and provider, #return the user assoc = UserAssociation.objects.get( openid_url = username + '@' + provider_name,#a hack - par name is bad provider_name = provider_name ) return assoc.user except UserAssociation.DoesNotExist: #race condition here a user with this name may exist user, created = User.objects.get_or_create(username = username) if created: user.set_password(password) user.save() user_registered.send(None, user = user) else: #have username collision - so make up a more unique user name #bug: - if user already exists with the new username - we are in trouble new_username = '******' % (username, provider_name) user = User.objects.create_user(new_username, '', password) user_registered.send(None, user = user) message = _( 'Welcome! Please set email address (important!) in your ' 'profile and adjust screen name, if necessary.' ) user.message_set.create(message = message) else: return None #this is a catch - make login token a little more unique #for the cases when passwords are the same for two users #from the same provider try: assoc = UserAssociation.objects.get( user = user, provider_name = provider_name ) except UserAssociation.DoesNotExist: assoc = UserAssociation( user = user, provider_name = provider_name ) assoc.openid_url = username + '@' + provider_name#has to be this way for external pw logins elif method == 'openid': try: assoc = UserAssociation.objects.get(openid_url=openid_url) user = assoc.user except UserAssociation.DoesNotExist: return None except UserAssociation.MultipleObjectsReturned: logging.critical( 'duplicate openid url in the database!!! %s' % openid_url ) return None elif method == 'email': #with this method we do no use user association try: #todo: add email_key_timestamp field #and check key age user = User.objects.get(email_key = email_key) user.email_key = None #one time key so delete it user.email_isvalid = True user.save() return user except User.DoesNotExist: return None elif method == 'oauth': if login_providers[provider_name]['type'] == 'oauth': try: assoc = UserAssociation.objects.get( openid_url = oauth_user_id, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: return None else: return None elif method == 'facebook': try: #assert(provider_name == 'facebook') assoc = UserAssociation.objects.get( openid_url = facebook_user_id, provider_name = 'facebook' ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'ldap': user_info = ldap_authenticate(username, password) if user_info['success'] == False: # Maybe a user created internally (django admin user) try: user = User.objects.get(username__exact=username) if user.check_password(password): return user else: return None except User.DoesNotExist: return None else: #load user by association or maybe auto-create one ldap_username = user_info['ldap_username'] try: #todo: provider_name is hardcoded - possible conflict assoc = UserAssociation.objects.get( openid_url = ldap_username + '@ldap', provider_name = 'ldap' ) user = assoc.user except UserAssociation.DoesNotExist: #email address is required if 'email' in user_info and askbot_settings.LDAP_AUTOCREATE_USERS: assoc = ldap_create_user(user_info) user = assoc.user else: return None elif method == 'cas': import caslib cas_response = caslib.cas_serviceValidate(cas_ticket) success, _user = cas_response.map[cas_response.type].get('user',None) if success: try: assoc = UserAssociation.objects.get( openid_url = _user + '@ldap', provider_name = 'ldap' ) user = assoc.user except UserAssociation.DoesNotExist: user = User() user.username = _user user.set_unusable_password() user.is_staff = False user.is_superuser = False user.is_active = True user.save() user_registered.send(None, user = user) LOG.info('Created New User : [{0}]'.format(_user)) assoc = UserAssociation() assoc.user = _user assoc.openid_url = _user + '@ldap' assoc.provider_name = 'ldap' assoc.save() else: return None elif method == 'wordpress_site': try: custom_wp_openid_url = '%s?user_id=%s' % (wordpress_url, wp_user_id) assoc = UserAssociation.objects.get( openid_url = custom_wp_openid_url, provider_name = 'wordpress_site' ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'force': return self.get_user(user_id) else: raise TypeError('only openid and password supported') if assoc: #update last used time assoc.last_used_timestamp = datetime.datetime.now() assoc.save() return user
def authenticate( self, username = None,#for 'password' and 'ldap' password = None,#for 'password' and 'ldap' user_id = None,#for 'force' provider_name = None,#required with all except email_key openid_url = None, email_key = None, oauth_user_id = None,#used with oauth facebook_user_id = None,#user with facebook wordpress_url = None, # required for self hosted wordpress wp_user_id = None, # required for self hosted wordpress method = None,#requried parameter ): """this authentication function supports many login methods just which method it is going to use it determined from the signature of the function call """ login_providers = util.get_enabled_login_providers() assoc = None # UserAssociation not needed for ldap if method == 'password': if login_providers[provider_name]['type'] != 'password': raise ImproperlyConfigured('login provider must use password') if provider_name == 'local': try: user = User.objects.get(username=username) if not user.check_password(password): return None except User.DoesNotExist: try: email_address = username user = User.objects.get(email = email_address) if not user.check_password(password): return None except User.DoesNotExist: return None except User.MultipleObjectsReturned: logging.critical( ('have more than one user with email %s ' + 'he/she will not be able to authenticate with ' + 'the email address in the place of user name') % email_address ) return None else: if login_providers[provider_name]['check_password'](username, password): try: #if have user associated with this username and provider, #return the user assoc = UserAssociation.objects.get( openid_url = username + '@' + provider_name,#a hack - par name is bad provider_name = provider_name ) return assoc.user except UserAssociation.DoesNotExist: #race condition here a user with this name may exist user, created = User.objects.get_or_create(username = username) if created: user.set_password(password) user.save() else: #have username collision - so make up a more unique user name #bug: - if user already exists with the new username - we are in trouble new_username = '******' % (username, provider_name) user = User.objects.create_user(new_username, '', password) message = _( 'Welcome! Please set email address (important!) in your ' 'profile and adjust screen name, if necessary.' ) user.message_set.create(message = message) else: return None #this is a catch - make login token a little more unique #for the cases when passwords are the same for two users #from the same provider try: assoc = UserAssociation.objects.get( user = user, provider_name = provider_name ) except UserAssociation.DoesNotExist: assoc = UserAssociation( user = user, provider_name = provider_name ) assoc.openid_url = username + '@' + provider_name#has to be this way for external pw logins elif method == 'openid': provider_name = util.get_provider_name(openid_url) try: assoc = UserAssociation.objects.get( openid_url = openid_url, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'email': #with this method we do no use user association try: #todo: add email_key_timestamp field #and check key age user = User.objects.get(email_key = email_key) user.email_key = None #one time key so delete it user.email_isvalid = True user.save() return user except User.DoesNotExist: return None elif method == 'oauth': if login_providers[provider_name]['type'] == 'oauth': try: assoc = UserAssociation.objects.get( openid_url = oauth_user_id, provider_name = provider_name ) user = assoc.user except UserAssociation.DoesNotExist: return None else: return None elif method == 'facebook': try: #assert(provider_name == 'facebook') assoc = UserAssociation.objects.get( openid_url = facebook_user_id, provider_name = 'facebook' ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'ldap': user = ldap_authenticate(username, password) elif method == 'wordpress_site': try: custom_wp_openid_url = '%s?user_id=%s' % (wordpress_url, wp_user_id) assoc = UserAssociation.objects.get( openid_url = custom_wp_openid_url, provider_name = 'wordpress_site' ) user = assoc.user except UserAssociation.DoesNotExist: return None elif method == 'force': return self.get_user(user_id) else: raise TypeError('only openid and password supported') if assoc: #update last used time assoc.last_used_timestamp = datetime.datetime.now() assoc.save() return user
def show_signin_view( request, login_form=None, account_recovery_form=None, account_recovery_message=None, sticky=False, view_subtype="default", ): """url-less utility function that populates context of template 'authopenid/signin.html' and returns its rendered output """ allowed_subtypes = ("default", "add_openid", "email_sent", "change_openid", "bad_key") assert view_subtype in allowed_subtypes if sticky: next_url = reverse("user_signin") else: next_url = get_next_url(request) if login_form is None: login_form = forms.LoginForm(initial={"next": next_url}) if account_recovery_form is None: account_recovery_form = forms.AccountRecoveryForm() # initial = initial_data) # if request is GET if request.method == "GET": logging.debug("request method was GET") # todo: this sthuff must be executed on some signal # because askbot should have nothing to do with the login app from askbot.models import AnonymousQuestion as AQ session_key = request.session.session_key logging.debug("retrieving anonymously posted question associated with session %s" % session_key) qlist = AQ.objects.filter(session_key=session_key).order_by("-added_at") if len(qlist) > 0: question = qlist[0] else: question = None from askbot.models import AnonymousAnswer as AA session_key = request.session.session_key logging.debug("retrieving posted answer associated with session %s" % session_key) alist = AA.objects.filter(session_key=session_key).order_by("-added_at") if len(alist) > 0: answer = alist[0] else: answer = None if request.user.is_authenticated(): existing_login_methods = UserAssociation.objects.filter(user=request.user) # annotate objects with extra data providers = util.get_enabled_login_providers() for login_method in existing_login_methods: try: provider_data = providers[login_method.provider_name] if provider_data["type"] == "password": # only external password logins will not be deletable # this is because users with those can lose access to their accounts permanently login_method.is_deletable = provider_data.get("password_changeable", False) else: login_method.is_deletable = True except KeyError: logging.critical( "login method %s is no longer available " "please delete records for this login method " "from the UserAssociation table", login_method.provider_name, ) continue if view_subtype == "default": page_title = _("Please click any of the icons below to sign in") elif view_subtype == "email_sent": page_title = _("Account recovery email sent") elif view_subtype == "change_openid": if len(existing_login_methods) == 0: page_title = _("Please add one or more login methods.") else: page_title = _("If you wish, please add, remove or re-validate your login methods") elif view_subtype == "add_openid": page_title = _("Please wait a second! Your account is recovered, but ...") elif view_subtype == "bad_key": page_title = _("Sorry, this account recovery key has expired or is invalid") logging.debug("showing signin view") data = { "page_class": "openid-signin", "view_subtype": view_subtype, # add_openid|default "page_title": page_title, "question": question, "answer": answer, "login_form": login_form, "use_password_login": util.use_password_login(), "account_recovery_form": account_recovery_form, "openid_error_message": request.REQUEST.get("msg", ""), "account_recovery_message": account_recovery_message, "use_password_login": util.use_password_login(), } major_login_providers = util.get_enabled_major_login_providers() minor_login_providers = util.get_enabled_minor_login_providers() # determine if we are only using password login active_provider_names = [p["name"] for p in major_login_providers.values()] active_provider_names.extend([p["name"] for p in minor_login_providers.values()]) have_buttons = True if len(active_provider_names) == 1 and active_provider_names[0] == "local": if askbot_settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN == True: # in this case the form is not using javascript, so set initial values # here have_buttons = False login_form.initial["login_provider_name"] = "local" if request.user.is_authenticated(): login_form.initial["password_action"] = "change_password" else: login_form.initial["password_action"] = "login" data["have_buttons"] = have_buttons if request.user.is_authenticated(): data["existing_login_methods"] = existing_login_methods active_provider_names = [item.provider_name for item in existing_login_methods] util.set_login_provider_tooltips(major_login_providers, active_provider_names=active_provider_names) util.set_login_provider_tooltips(minor_login_providers, active_provider_names=active_provider_names) data["major_login_providers"] = major_login_providers.values() data["minor_login_providers"] = minor_login_providers.values() return render_into_skin("authopenid/signin.html", data, request)