prevent user login after registration using django-allauth - django-allauth

i'm using django-allauth for my django app. by default, when a user successfully sign's up, they are automatically logged in. how do you override the default behaviour and prevent the user from logging in after after successful signup. After the user signs up, he/she must be redirected to the login page. ive disabled email verification. Thank you.
# settings.py
LOGIN_REDIRECT_URL = 'welcome'
ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS = False
ACCOUNT_LOGOUT_REDIRECT_URL = 'thanks'
ACCOUNT_EMAIL_REQUIRED = False
ACCOUNT_EMAIL_VERIFICATION = 'none'

If you don't need the email verification, you can skip the login like this:
First in your urls.py, you must override the url to the default SignupView with a url to your own view:
url(r^'accounts/signup/$', views.CustomSignupView.as_view(), name="account_signup")
Then in your views.py, you have a custom view that will return a path to your frontpage instead of continuing to login the user.
class CustomSignupView(SignupView):
def form_valid(self, form):
self.user = form.save(self.request)
return redirect('/frontpage')

Related

How to get logged in Active Directory username in Ruby

How can I fetch the logged in AD user in my ROR application.
I have tried:
Etc.getlogin - It gives me the username of where the server is running
system(`WhoAmI`) - returns false
ENV["USERNAME"], ENV["USER"], ENV["USERID"] - Doesn't return anything
And how to check if the User is logged in or not ?
I am using Net::LDAP for this:
a = Net::LDAP::Filter.eq("sAMAccountName", "username")
ldap.search(:filter => a)
It return me the data of the user as :
#myhash=
{:dn=>["CN=Test Windows,CN=Users,DC=example,DC=local"],
:objectclass=>["top", "person", "organizationalPerson", "user"],
:cn=>["Test Windows"],
:sn=>["Windows"],
:givenname=>["Test"],
:distinguishedname=>["CN=Test Windows,CN=Users,DC=example,DC=local"],
:instancetype=>["4"],
:whencreated=>["20211004113850.0Z"],
:whenchanged=>["20211004124559.0Z"],
:displayname=>["Test Windows"],
:usncreated=>["16489"],
:usnchanged=>["16525"],
:name=>["Test Windows"],
:objectguid=>["Some ID"],
:useraccountcontrol=>["22038"],
:badpwdcount=>["0"],
:codepage=>["0"],
:countrycode=>["0"],
:badpasswordtime=>["0"],
:lastlogoff=>["0"],
:lastlogon=>["0"],
:pwdlastset=>["1327782117765465"],
:primarygroupid=>["213"],
:objectsid=>["Some ID"],
:accountexpires=>["9223876536854775807"],
:logoncount=>["0"],
:samaccountname=>["username"],
:samaccounttype=>["93806368"],
:userprincipalname=>["username#example.local"],
:objectcategory=>["CN=Person,CN=Schema,CN=Configuration,DC=example,DC=local"],
:dscorepropagationdata=>["16010101000000.0Z"],
:mail=>["abc#abc.com"]}>]
But here how to know if the user is logged in ?
lastlogoff & lastlogon is always "0"
Thanks.
MSAL API should let us know the username that is currently logged in so that we don't have to create a separate cookie and manage this cookie and logic.
getAllAcounts should give us all the accounts.
getAccount should give us the account that it is currently signed in/active.
Here is how you can check if user is loggedIn or not:
cdef raw_info
#raw_info ||= access_token.get('/me').parse
Then you can check if the token is valid or not. If it is valid then the user is loggedIn otherwise not.

Allow user to register using django-all-auth even if the social account exists and then connect the two automatically

So, I have been able to connect social accounts (fb or google) to be connected to the local email account if already exists.
However, I also want the reverse functionality, i.e. I would like to allow user to sign up even if the (google or FB) social account exists. Currently it says:
{ A user is already registered with this email address }
I am using django-all-auth and django-rest-auth with Django 2.1
Yes, you can do that. You should be able to modify the password reset endpoint provided by django-rest-auth to set a password and then be able to login:
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import PasswordResetForm as DjangoPasswordResetForm
from rest_auth.serializers import (
PasswordResetSerializer as RestAuthPasswordResetSerializer
)
from rest_auth.views import PasswordResetView as RestAuthPasswordResetView
UserModel = get_user_model()
class PasswordResetForm(DjangoPasswordResetForm):
def get_users(self, email):
"""
Given an email, return matching user(s) who should receive a reset.
"""
active_users = UserModel._default_manager.filter(**{
'%s__iexact' % UserModel.get_email_field_name(): email,
'is_active': True,
})
return iter(active_users)
# or (u for u in active_users if not u.has_usable_password())
class PasswordResetSerializer(RestAuthPasswordResetSerializer):
password_reset_form_class = PasswordResetForm
class PasswordResetView(RestAuthPasswordResetView):
serializer_class = PasswordResetSerializer
You can add this view to your urls.py as general endpoint to reset passwords (remember to place it in front of the rest_auths' URLs) or as an additional endpoint to set passwords (see the commented line). Then you can add a note to your signup page that links to your page that serves your new endpoint.
As an alternative, you could also add a field to your user settings page where users can set a password.
You could also send an e-mail with a link via send_confirmation to set a password when a user tries to sign up and the e-mail exists already (or only in case this user has a social account). If you like I could add an example here how to do that.

Login to external site from Rails

I would like to login to an external https site, through rails based on user/password credentials saved into a rails database. Something like a single sign on. The external site does not provide an API to login; only a login form. Their docs say you can post the credentials to their login form by loading the email and password to the form and then pressing ok.
But if I do that, then by viewing the source code of the login form, someone may find out the login credentials. I have looked into Mechanize and loading cookies like here Submitting POST data from the controller in rails to another website and Rails 3 - Log into another site and keep cookie in session but it does not seem right.
Is there a way to automatically load the credentials from the controller and post to the external site immediately in order to login to that site?
Thank you in advance
I would use Oauth2. Here is a good wrapper: https://github.com/intridea/oauth2
I was able to do this via mechanize. For facebook for example, which uses https, the code is shown below
In my user_controller.rb:
def face_book
#website = 'https://www.facebook.com/login.php?login_attempt=1&lwv=110'
agent = Mechanize.new
agent.log = Logger.new "mechanize.log"
agent.user_agent_alias = 'Mac Safari'
agent.follow_meta_refresh = true
agent.redirect_ok = true
login_page = agent.get (#website)
login_form = login_page.forms.first
email_field = login_form.field_with(name: "email")
password_field = login_form.field_with(name: "pass")
email_field.value = 'PUT_YOUR_EMAIL_HERE'
password_field.value = 'PUT_YOUR_PASSWORD_HERE'
home_page = login_form.click_button
#blah = agent.get("https://m.facebook.com/")
end

Manually Invoking email verification

We've been using django-allauth for quite some time now in production. We can enable account email verification which works great. But we now have a REST api that allows users to register through the API and the workflow doesn't go through django-allauth. Is it possible to manually invoke the django-allauth email verification feature or do we need to use a custom solution?
I'll just post my answer here as I've been searching for adding email verification with Django Built-in Authentication (And using a Custom Auth Model), I used the method mentioned by Marcus, I'll just add all the other stuff around it for anyone who wants to do the same.
First: Install django-allauth as described here
Second: Add your email configurations in the settings.py file :
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com' #I used gmail in my case
EMAIL_HOST_USER = <Your Email>
EMAIL_HOST_PASSWORD = <Your Password>
EMAIL_PORT = 587
DEFAULT_FROM_EMAIL = <Default Sender name and email>
Third: Add configurations for verification and default login url, you'll find the documentation of all config parameters here, note that in my example I'm using a custom user model as mentioned, that's why I'm setting ACCOUNT_EMAIL_REQUIRED to True & ACCOUNT_USER_MODEL_USERNAME_FIELD and ACCOUNT_USERNAME_REQUIRED to False, also the LOGIN_URL,ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL andLOGIN_REDIRECT_URL parameters are used after the user clicks on the confirmation link sent by email to him
ACCOUNT_EMAIL_VERIFICATION='mandatory'
ACCOUNT_CONFIRM_EMAIL_ON_GET=True
ACCOUNT_EMAIL_REQUIRED=True
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
LOGIN_URL='app:login_user'
LOGIN_REDIRECT_URL='app:login_user'
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL='app:login_user'
Fourth: After your signup form, save the user instance with is_active parameter set to False, then call the method:
from allauth.account.utils import *
send_email_confirmation(request, user, True)
Finally: Receive the signal after the user confirms his email, and set is_active to True
from allauth.account.signals import email_confirmed
from django.dispatch import receiver
# Signal sent to activate user upon confirmation
#receiver(email_confirmed)
def email_confirmed_(request, email_address, **kwargs):
user = MyUser.objects.get(email=email_address.email)
user.is_active = True
user.save()
Finally, you would want to change the default site name from Django Admin as it will be included in the email sent.
I had the same problem, and the solution I've found was to call the original send_email_confirmation method from allauth. I am using DRF3 for my API.
from allauth.account.utils import send_email_confirmation
...
def some_view(request):
user = ...
...
#using request._request to avoid TypeError on change made in DRF3 (from HTTPRequest to Request object)
send_email_confirmation(request._request, user)
...
I hope this helps you.

Using Grails Acegi Plugin when a User domains "enabled" field is set to false. The user can still login

Is the disabling of users natively supported by the Acegi Grails plugin?
From the Documentation it appears to support the "enabled" field..
But after setting the Users "enabled" field to false, the user can still login and no "user is disabled" exception is thrown ( although there appears to be a catch for a user disabled exception in the default logincontroller)...
If this functionality is supported are there any other changes needed other than setting the users "enabled" field to false?
Guessing that this may not be supported, i have added a check to the login controller to check if a user is enabled when the user is logged in and sending them back to the login screen with a disabled message...
def index = {
if (isLoggedIn()) {
def dc = authenticateService.principal().domainClass
def user = User.get( dc.id )
if (!user.enabled){
session.invalidate()
flash.message = "User '"+user.username+"' is disabled."
redirect action: auth, params: params
}else{
setLoginDate()
redirect uri: '/home/'
}
}
However, this only work when I access the login page directly. When I try to login after entering a url (eg */user/list) from within the application; the user logs in and is taken url without calling my check in the logincontroller...
Try using a filter instead. I'm not sure the index closure is called unless you indeed hit the base URI for that controller.
http://www.grails.org/doc/1.3.x/guide/single.html#6.6%20Filters

Resources