Working of authentication (Login) in django
==============================================
1)
site-packages/django/contrib/auth/forms.py
from django.contrib.auth import authenticate
class AuthenticationForm(forms.Form):
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
self.user_cache = authenticate(username=username,
password=password)
2)
./openstack_dashboard/settings.py
AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',)
3)
site-packages/django/contrib/auth/__init__.py
def get_backends():
from django.conf import settings
backends = []
for backend_path in settings.AUTHENTICATION_BACKENDS:
backends.append(load_backend(backend_path))
if not backends:
raise ImproperlyConfigured('No authentication backends have been defined. Does AUTHENTICATION_BACKENDS contain anything?')
return backends
def authenticate(**credentials):
"""
If the given credentials are valid, return a User object.
"""
for backend in get_backends():
try:
user = backend.authenticate(**credentials)
except TypeError:
# This backend doesn't accept these credentials as arguments. Try the next one.
continue
if user is None:
continue
# Annotate the user object with the path of the backend.
user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
return user
# The credentials supplied are invalid to all backends, fire signal
user_login_failed.send(sender=__name__,
credentials=_clean_credentials(credentials))
Working of authentication (Login) in Horizon
==============================================
1a)
horizon/openstack_dashboard/views.py
from openstack_auth import views
@vary.vary_on_cookie
def splash(request):
if request.user.is_authenticated():
return shortcuts.redirect(get_user_home(request.user))
form = views.Login(request)
request.session.clear()
request.session.set_test_cookie()
return shortcuts.render(request, 'splash.html', {'form': form})
1b)
site-packages/openstack_auth/views.py
from django.contrib.auth.views import login as django_login
from .forms import Login
def login(request):
initial = {}
current_region = request.session.get('region_endpoint', None)
requested_region = request.GET.get('region', None)
regions = dict(getattr(settings, "AVAILABLE_REGIONS", []))
if requested_region in regions and requested_region != current_region:
initial.update({'region': requested_region})
if request.method == "POST":
form = curry(Login, request)
else:
form = curry(Login, initial=initial)
extra_context = {'redirect_field_name': REDIRECT_FIELD_NAME}
if request.is_ajax():
template_name = 'auth/_login.html'
extra_context['hide'] = True
else:
template_name = 'auth/login.html'
res = django_login(request,
template_name=template_name,
authentication_form=form,
extra_context=extra_context)
# Set the session data here because django's session key rotation
# will erase it if we set it earlier.
if request.user.is_authenticated():
set_session_from_user(request, request.user)
regions = dict(Login.get_region_choices())
region = request.user.endpoint
region_name = regions.get(region)
request.session['region_endpoint'] = region
request.session['region_name'] = region_name
return res
1c)
site-packages/django/contrib/auth/views.py
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
////blabla////
return TemplateResponse(request, template_name, context,
current_app=current_app)
1d)
site-packages/openstack_auth/forms.py
from django.contrib.auth import authenticate
class Login(AuthenticationForm):
region = forms.ChoiceField(label=_("Region"), required=False)
username = forms.CharField(label=_("User Name"))
password = forms.CharField(label=_("Password"),
widget=forms.PasswordInput(render_value=False))
def clean(self):
default_domain = getattr(settings,
'OPENSTACK_KEYSTONE_DEFAULT_DOMAIN',
'Default')
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
region = self.cleaned_data.get('region')
domain = self.cleaned_data.get('domain', default_domain)
if not (username and password):
# Don't authenticate, just let the other validators handle it.
return self.cleaned_data
try:
self.user_cache = authenticate(request=self.request,
username=username,
password=password,
user_domain_name=domain,
auth_url=region)
msg = 'Login successful for user "%(username)s".' % \
{'username': username}
LOG.info(msg)
except KeystoneAuthException as exc:
msg = 'Login failed for user "%(username)s".' % \
{'username': username}
LOG.warning(msg)
self.request.session.flush()
raise forms.ValidationError(exc)
self.check_for_test_cookie()
return self.cleaned_data
2)
Same as in django
3)
Same as in django
4)
site-packages/openstack_auth/backend.py
from .user import create_user_from_token
from .user import Token
from .utils import check_token_expiration
from .utils import get_keystone_client
class KeystoneBackend(object):
def authenticate(self, request=None, username=None, password=None,
user_domain_name=None, auth_url=None):
"""Authenticates a user via the Keystone Identity API. """
LOG.debug('Beginning user authentication for user "%s".' % username)
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
endpoint_type = getattr(
settings, 'OPENSTACK_ENDPOINT_TYPE', 'publicURL')
keystone_client = get_keystone_client()
try:
client = keystone_client.Client(
user_domain_name=user_domain_name,
username=username,
password=password,
auth_url=auth_url,
insecure=insecure,
debug=settings.DEBUG)
unscoped_auth_ref = client.auth_ref
unscoped_token = Token(auth_ref=unscoped_auth_ref)
except (keystone_exceptions.Unauthorized,
keystone_exceptions.Forbidden,
keystone_exceptions.NotFound) as exc:
msg = _('Invalid user name or password.')
LOG.debug(exc.message)
raise KeystoneAuthException(msg)
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure) as exc:
msg = _("An error occurred authenticating. "
"Please try again later.")
LOG.debug(exc.message)
raise KeystoneAuthException(msg)
# Check expiry for our unscoped auth ref.
self.check_auth_expiry(unscoped_auth_ref)
# Check if token is automatically scoped to default_project
if unscoped_auth_ref.project_scoped:
auth_ref = unscoped_auth_ref
else:
# For now we list all the user's projects and iterate through.
try:
if get_keystone_version() < 3:
projects = client.tenants.list()
else:
client.management_url = auth_url
projects = client.projects.list(
user=unscoped_auth_ref.user_id)
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure) as exc:
msg = _('Unable to retrieve authorized projects.')
raise KeystoneAuthException(msg)
# Abort if there are no projects for this user
if not projects:
msg = _('You are not authorized for any projects.')
raise KeystoneAuthException(msg)
while projects:
project = projects.pop()
try:
client = keystone_client.Client(
tenant_id=project.id,
token=unscoped_auth_ref.auth_token,
auth_url=auth_url,
insecure=insecure,
debug=settings.DEBUG)
auth_ref = client.auth_ref
break
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure):
auth_ref = None
if auth_ref is None:
msg = _("Unable to authenticate to any available projects.")
raise KeystoneAuthException(msg)
# Check expiry for our new scoped token.
self.check_auth_expiry(auth_ref)
# If we made it here we succeeded. Create our User!
user = create_user_from_token(
request,
Token(auth_ref),
client.service_catalog.url_for(endpoint_type=endpoint_type))
if request is not None:
request.session['unscoped_token'] = unscoped_token.id
request.user = user
# Support client caching to save on auth calls.
setattr(request, KEYSTONE_CLIENT_ATTR, client)
LOG.debug('Authentication completed for user "%s".' % username)
return user
==============================================
1)
site-packages/django/contrib/auth/forms.py
from django.contrib.auth import authenticate
class AuthenticationForm(forms.Form):
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
self.user_cache = authenticate(username=username,
password=password)
2)
./openstack_dashboard/settings.py
AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',)
3)
site-packages/django/contrib/auth/__init__.py
def get_backends():
from django.conf import settings
backends = []
for backend_path in settings.AUTHENTICATION_BACKENDS:
backends.append(load_backend(backend_path))
if not backends:
raise ImproperlyConfigured('No authentication backends have been defined. Does AUTHENTICATION_BACKENDS contain anything?')
return backends
def authenticate(**credentials):
"""
If the given credentials are valid, return a User object.
"""
for backend in get_backends():
try:
user = backend.authenticate(**credentials)
except TypeError:
# This backend doesn't accept these credentials as arguments. Try the next one.
continue
if user is None:
continue
# Annotate the user object with the path of the backend.
user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
return user
# The credentials supplied are invalid to all backends, fire signal
user_login_failed.send(sender=__name__,
credentials=_clean_credentials(credentials))
Working of authentication (Login) in Horizon
==============================================
1a)
horizon/openstack_dashboard/views.py
from openstack_auth import views
@vary.vary_on_cookie
def splash(request):
if request.user.is_authenticated():
return shortcuts.redirect(get_user_home(request.user))
form = views.Login(request)
request.session.clear()
request.session.set_test_cookie()
return shortcuts.render(request, 'splash.html', {'form': form})
1b)
site-packages/openstack_auth/views.py
from django.contrib.auth.views import login as django_login
from .forms import Login
def login(request):
initial = {}
current_region = request.session.get('region_endpoint', None)
requested_region = request.GET.get('region', None)
regions = dict(getattr(settings, "AVAILABLE_REGIONS", []))
if requested_region in regions and requested_region != current_region:
initial.update({'region': requested_region})
if request.method == "POST":
form = curry(Login, request)
else:
form = curry(Login, initial=initial)
extra_context = {'redirect_field_name': REDIRECT_FIELD_NAME}
if request.is_ajax():
template_name = 'auth/_login.html'
extra_context['hide'] = True
else:
template_name = 'auth/login.html'
res = django_login(request,
template_name=template_name,
authentication_form=form,
extra_context=extra_context)
# Set the session data here because django's session key rotation
# will erase it if we set it earlier.
if request.user.is_authenticated():
set_session_from_user(request, request.user)
regions = dict(Login.get_region_choices())
region = request.user.endpoint
region_name = regions.get(region)
request.session['region_endpoint'] = region
request.session['region_name'] = region_name
return res
1c)
site-packages/django/contrib/auth/views.py
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
////blabla////
return TemplateResponse(request, template_name, context,
current_app=current_app)
1d)
site-packages/openstack_auth/forms.py
from django.contrib.auth import authenticate
class Login(AuthenticationForm):
region = forms.ChoiceField(label=_("Region"), required=False)
username = forms.CharField(label=_("User Name"))
password = forms.CharField(label=_("Password"),
widget=forms.PasswordInput(render_value=False))
def clean(self):
default_domain = getattr(settings,
'OPENSTACK_KEYSTONE_DEFAULT_DOMAIN',
'Default')
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
region = self.cleaned_data.get('region')
domain = self.cleaned_data.get('domain', default_domain)
if not (username and password):
# Don't authenticate, just let the other validators handle it.
return self.cleaned_data
try:
self.user_cache = authenticate(request=self.request,
username=username,
password=password,
user_domain_name=domain,
auth_url=region)
msg = 'Login successful for user "%(username)s".' % \
{'username': username}
LOG.info(msg)
except KeystoneAuthException as exc:
msg = 'Login failed for user "%(username)s".' % \
{'username': username}
LOG.warning(msg)
self.request.session.flush()
raise forms.ValidationError(exc)
self.check_for_test_cookie()
return self.cleaned_data
2)
Same as in django
3)
Same as in django
4)
site-packages/openstack_auth/backend.py
from .user import create_user_from_token
from .user import Token
from .utils import check_token_expiration
from .utils import get_keystone_client
class KeystoneBackend(object):
def authenticate(self, request=None, username=None, password=None,
user_domain_name=None, auth_url=None):
"""Authenticates a user via the Keystone Identity API. """
LOG.debug('Beginning user authentication for user "%s".' % username)
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
endpoint_type = getattr(
settings, 'OPENSTACK_ENDPOINT_TYPE', 'publicURL')
keystone_client = get_keystone_client()
try:
client = keystone_client.Client(
user_domain_name=user_domain_name,
username=username,
password=password,
auth_url=auth_url,
insecure=insecure,
debug=settings.DEBUG)
unscoped_auth_ref = client.auth_ref
unscoped_token = Token(auth_ref=unscoped_auth_ref)
except (keystone_exceptions.Unauthorized,
keystone_exceptions.Forbidden,
keystone_exceptions.NotFound) as exc:
msg = _('Invalid user name or password.')
LOG.debug(exc.message)
raise KeystoneAuthException(msg)
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure) as exc:
msg = _("An error occurred authenticating. "
"Please try again later.")
LOG.debug(exc.message)
raise KeystoneAuthException(msg)
# Check expiry for our unscoped auth ref.
self.check_auth_expiry(unscoped_auth_ref)
# Check if token is automatically scoped to default_project
if unscoped_auth_ref.project_scoped:
auth_ref = unscoped_auth_ref
else:
# For now we list all the user's projects and iterate through.
try:
if get_keystone_version() < 3:
projects = client.tenants.list()
else:
client.management_url = auth_url
projects = client.projects.list(
user=unscoped_auth_ref.user_id)
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure) as exc:
msg = _('Unable to retrieve authorized projects.')
raise KeystoneAuthException(msg)
# Abort if there are no projects for this user
if not projects:
msg = _('You are not authorized for any projects.')
raise KeystoneAuthException(msg)
while projects:
project = projects.pop()
try:
client = keystone_client.Client(
tenant_id=project.id,
token=unscoped_auth_ref.auth_token,
auth_url=auth_url,
insecure=insecure,
debug=settings.DEBUG)
auth_ref = client.auth_ref
break
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure):
auth_ref = None
if auth_ref is None:
msg = _("Unable to authenticate to any available projects.")
raise KeystoneAuthException(msg)
# Check expiry for our new scoped token.
self.check_auth_expiry(auth_ref)
# If we made it here we succeeded. Create our User!
user = create_user_from_token(
request,
Token(auth_ref),
client.service_catalog.url_for(endpoint_type=endpoint_type))
if request is not None:
request.session['unscoped_token'] = unscoped_token.id
request.user = user
# Support client caching to save on auth calls.
setattr(request, KEYSTONE_CLIENT_ATTR, client)
LOG.debug('Authentication completed for user "%s".' % username)
return user
How to get region
ReplyDeletesite-packages/openstack_auth/forms.py:
class Login(AuthenticationForm):
def __init__(self, *args, **kwargs):
self.fields['region'].choices = self.get_region_choices()
if len(self.fields['region'].choices) == 1:
self.fields['region'].initial = self.fields['region'].choices[0][0]
self.fields['region'].widget = forms.widgets.HiddenInput()
@staticmethod
def get_region_choices():
default_region = (settings.OPENSTACK_KEYSTONE_URL, "Default Region")
return getattr(settings, 'AVAILABLE_REGIONS', [default_region])
How to test user authentication with openstack_auth and keystoneclient modules
ReplyDelete--------------------------
##Activate virtual environment and goto the horizon directory
##Goto django console
python manage.py shell
##import django settings
from django.conf import settings
dir(settings)
vars(settings)
getattr(settings, 'OPENSTACK_API_VERSIONS', {})
##Imports
from openstack_auth import utils as auth_utils
from openstack_auth.user import Token
from openstack_auth.utils import check_token_expiration
dir(auth_utils)
##site-packages/openstack_auth/backend.py
##client
auth_utils.get_keystone_version()
keystone_client = auth_utils.get_keystone_client()
region_or_auth_url = "http://192.168.56.101:5000/v3"
##User authentication on a domain (Default domain) with username and password
client = keystone_client.Client(
user_domain_name="Default",
username="admin",
password="password",
auth_url=region_or_auth_url,
insecure=False,
debug=True)
##Token
unscoped_auth_ref = client.auth_ref
unscoped_auth_ref.auth_token
##Get token object
unscoped_token = Token(auth_ref=unscoped_auth_ref)
check_token_expiration(unscoped_auth_ref)##False means expired
##Get all projects, keystone version 3
client.management_url = region_or_auth_url
projects = client.projects.list(user=unscoped_auth_ref.user_id)
Create new user
ReplyDelete------------------------------
client = keystone_client.Client(
user_domain_name="Default",
username="manu",
password="manu",
auth_url=region_or_auth_url,
insecure=False,
debug=True)
p = [x for x in client.projects.list() if x.name in ["demo"]]
u = client.users.create("ss2", password="ss2", project=p[0].id)
r = [x for x in client.roles.list() if x.name in ["Member"]]
client.roles.grant(r[0], user=u.id, project=p[0].id)