2011-09-13 19:13:14 +02:00
|
|
|
"""
|
|
|
|
Dispatcher for basic auth form authentifications
|
|
|
|
"""
|
|
|
|
import Cookie
|
2011-12-07 18:49:50 +01:00
|
|
|
import base64
|
2012-07-08 20:55:13 +02:00
|
|
|
import copy
|
2011-10-06 17:50:40 +02:00
|
|
|
import re
|
2014-09-05 19:16:27 +02:00
|
|
|
import os
|
2011-12-07 18:49:50 +01:00
|
|
|
import traceback
|
2011-09-19 19:38:48 +02:00
|
|
|
import urllib
|
2011-09-13 19:13:14 +02:00
|
|
|
|
2011-10-03 18:33:03 +02:00
|
|
|
import mandaye
|
|
|
|
|
2011-09-21 19:34:02 +02:00
|
|
|
from cookielib import CookieJar
|
2011-10-03 18:33:03 +02:00
|
|
|
from datetime import datetime
|
2011-10-07 22:45:07 +02:00
|
|
|
from lxml.html import fromstring
|
2011-09-13 19:13:14 +02:00
|
|
|
from urlparse import parse_qs
|
|
|
|
|
2014-05-21 13:15:40 +02:00
|
|
|
from mandaye import config, __version__
|
2012-07-08 20:55:13 +02:00
|
|
|
from mandaye.exceptions import MandayeException
|
2011-12-23 11:01:03 +01:00
|
|
|
from mandaye.log import logger
|
2011-09-19 19:18:32 +02:00
|
|
|
from mandaye.http import HTTPResponse, HTTPHeader, HTTPRequest
|
2011-09-13 19:13:14 +02:00
|
|
|
from mandaye.response import _500, _302, _401
|
|
|
|
from mandaye.response import template_response
|
2011-09-19 19:18:32 +02:00
|
|
|
from mandaye.server import get_response
|
2011-09-13 19:13:14 +02:00
|
|
|
|
2014-09-10 18:51:54 +02:00
|
|
|
from mandaye.backends.default import Association
|
2013-05-21 11:59:19 +02:00
|
|
|
|
2011-12-23 11:01:03 +01:00
|
|
|
try:
|
|
|
|
from Crypto.Cipher import AES
|
|
|
|
except ImportError:
|
2013-05-21 11:59:19 +02:00
|
|
|
config.encrypt_sp_password = False
|
2011-10-04 14:31:03 +02:00
|
|
|
|
2011-09-13 19:13:14 +02:00
|
|
|
class AuthForm(object):
|
|
|
|
|
2014-05-21 13:15:40 +02:00
|
|
|
def __init__(self, env, mapper):
|
2011-11-17 18:47:47 +01:00
|
|
|
"""
|
2014-05-21 13:15:40 +02:00
|
|
|
env: WSGI environment
|
|
|
|
mapper: mapper's module like mandaye.mappers.linuxfr
|
2011-09-13 19:13:14 +02:00
|
|
|
"""
|
2014-05-21 13:15:40 +02:00
|
|
|
self.env = env
|
|
|
|
self.urls = mapper.urls
|
|
|
|
self.site_name = self.env["mandaye.config"]["site_name"]
|
|
|
|
self.form_values = mapper.form_values
|
|
|
|
if not self.form_values.has_key('form_headers'):
|
|
|
|
self.form_values['form_headers'] = {
|
2011-09-22 12:31:46 +02:00
|
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
2014-05-21 13:15:40 +02:00
|
|
|
'User-Agent': 'Mozilla/5.0 Mandaye/%s' % __version__
|
2011-09-22 12:31:46 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 13:15:40 +02:00
|
|
|
if not self.form_values.has_key('post_fields') or \
|
|
|
|
not self.form_values.has_key('username_field') or \
|
|
|
|
not self.form_values.has_key('login_url'):
|
2011-12-23 11:01:03 +01:00
|
|
|
logger.critical("Bad configuration: AuthForm form_values dict must have \
|
2013-05-23 22:30:16 +02:00
|
|
|
this keys: post_fields and username_field")
|
2012-07-08 20:55:13 +02:00
|
|
|
raise MandayeException, 'AuthForm bad configuration'
|
2014-05-21 13:15:40 +02:00
|
|
|
if not self.form_values.has_key('form_attrs') and \
|
|
|
|
not self.form_values.has_key('post_url'):
|
2013-05-24 11:04:12 +02:00
|
|
|
logger.critical("Bad configuration: you must set form_attrs or post_url")
|
2014-05-21 13:15:40 +02:00
|
|
|
if config.encrypt_secret and not self.form_values.has_key('password_field'):
|
2012-07-08 20:55:13 +02:00
|
|
|
logger.critical("Bad configuration: AuthForm form_values dict must have a \
|
|
|
|
a password_field key if you want to encode a password.")
|
|
|
|
raise MandayeException, 'AuthForm bad configuration'
|
2011-09-22 12:31:46 +02:00
|
|
|
|
2014-05-21 13:15:40 +02:00
|
|
|
self.login_url = self.form_values.get('login_url')
|
2012-07-08 20:55:13 +02:00
|
|
|
if not self.form_values.has_key('post_fields'):
|
|
|
|
self.form_values['post_fields'] = []
|
2014-05-21 13:15:40 +02:00
|
|
|
|
|
|
|
def get_default_mapping(self):
|
2014-08-07 18:50:16 +02:00
|
|
|
mapping = [
|
|
|
|
{
|
2014-11-21 14:51:26 +01:00
|
|
|
'path': r'%s$' % self.urls.get('logout_url', '/mandaye/logout'),
|
2014-08-07 18:50:16 +02:00
|
|
|
'on_response': [{'auth': 'slo'}]
|
|
|
|
},
|
|
|
|
]
|
2014-07-09 14:32:07 +02:00
|
|
|
if config.a2_auto_connection:
|
|
|
|
mapping.append({
|
2014-07-11 12:20:57 +02:00
|
|
|
'path': r'/',
|
2014-07-09 14:32:07 +02:00
|
|
|
'response': {
|
2014-07-11 13:54:20 +02:00
|
|
|
'filter': self.auto_connection,
|
2014-07-09 14:32:07 +02:00
|
|
|
'condition': self.is_connected_a2
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return mapping
|
|
|
|
|
2013-06-04 19:20:10 +02:00
|
|
|
def encrypt_pwd(self, password):
|
2011-12-07 18:49:50 +01:00
|
|
|
""" This method allows you to encrypt a password
|
2013-05-21 11:59:19 +02:00
|
|
|
To use this feature you muste set encrypt_sp_password to True
|
2011-12-07 18:49:50 +01:00
|
|
|
in your configuration and set a secret in encrypt_secret
|
2013-06-04 19:20:10 +02:00
|
|
|
|
|
|
|
Return encrypted password
|
2011-12-07 18:49:50 +01:00
|
|
|
"""
|
|
|
|
if config.encrypt_secret:
|
2012-07-08 20:55:13 +02:00
|
|
|
logger.debug("Encrypt password")
|
2014-06-25 15:38:26 +02:00
|
|
|
try:
|
|
|
|
cipher = AES.new(config.encrypt_secret, AES.MODE_CFB, "0000000000000000")
|
|
|
|
password = cipher.encrypt(password)
|
|
|
|
password = base64.b64encode(password)
|
|
|
|
return password
|
|
|
|
except Exception, e:
|
|
|
|
if config.debug:
|
|
|
|
traceback.print_exc()
|
|
|
|
logger.warning('Password encrypting failed %s' % e)
|
2011-12-07 18:49:50 +01:00
|
|
|
else:
|
2014-06-25 15:38:26 +02:00
|
|
|
logger.warning("You must set a secret to use pwd encryption")
|
2011-12-07 18:49:50 +01:00
|
|
|
|
2013-06-04 19:20:10 +02:00
|
|
|
def decrypt_pwd(self, password):
|
2011-12-07 18:49:50 +01:00
|
|
|
""" This method allows you to dencrypt a password encrypt with
|
2013-06-04 19:20:10 +02:00
|
|
|
encrypt_pwd method. To use this feature you muste set
|
2013-05-21 11:59:19 +02:00
|
|
|
encrypt_sp_password to True in your configuration and
|
2011-12-07 18:49:50 +01:00
|
|
|
set a secret in encrypt_secret
|
2013-06-04 19:20:10 +02:00
|
|
|
|
|
|
|
Return decrypted password
|
2011-12-07 18:49:50 +01:00
|
|
|
"""
|
|
|
|
if config.encrypt_secret:
|
2012-07-08 20:55:13 +02:00
|
|
|
logger.debug("Decrypt password")
|
2011-12-07 18:49:50 +01:00
|
|
|
try:
|
2012-07-08 20:55:13 +02:00
|
|
|
cipher = AES.new(config.encrypt_secret, AES.MODE_CFB, "0000000000000000")
|
|
|
|
password = base64.b64decode(password)
|
|
|
|
password = cipher.decrypt(password)
|
2013-06-04 19:20:10 +02:00
|
|
|
return password
|
2011-12-07 18:49:50 +01:00
|
|
|
except Exception, e:
|
|
|
|
if config.debug:
|
|
|
|
traceback.print_exc()
|
2014-06-03 10:37:47 +02:00
|
|
|
logger.warning('Decrypting password failed: %r', e)
|
2011-12-07 18:49:50 +01:00
|
|
|
else:
|
2011-12-23 11:01:03 +01:00
|
|
|
logger.warning("You must set a secret to use pwd decryption")
|
2011-12-07 18:49:50 +01:00
|
|
|
|
2013-05-22 16:00:27 +02:00
|
|
|
def get_current_unique_id(self, env):
|
2014-07-16 12:32:34 +02:00
|
|
|
if env['beaker.session'].has_key('unique_id'):
|
|
|
|
return env['beaker.session']['unique_id']
|
|
|
|
return None
|
2013-05-22 16:00:27 +02:00
|
|
|
|
2012-07-08 20:55:13 +02:00
|
|
|
def replay(self, env, post_values):
|
2011-09-13 19:13:14 +02:00
|
|
|
""" replay the login / password
|
2011-09-23 08:49:32 +02:00
|
|
|
env: WSGI env with beaker session and the target
|
2012-07-08 20:55:13 +02:00
|
|
|
post_values: dict with the field name (key) and the field value (value)
|
2011-09-13 19:13:14 +02:00
|
|
|
"""
|
2014-06-03 10:37:47 +02:00
|
|
|
logger.debug("authform.replay post_values: %r", post_values)
|
2011-09-22 12:31:46 +02:00
|
|
|
cj = CookieJar()
|
|
|
|
request = HTTPRequest()
|
2013-05-24 11:04:12 +02:00
|
|
|
action = self.form_values.get('post_url')
|
2011-10-07 22:45:07 +02:00
|
|
|
auth_form = None
|
2013-05-23 22:30:16 +02:00
|
|
|
# if there is a form parse it
|
2013-05-24 11:04:12 +02:00
|
|
|
if not "://" in self.login_url:
|
2014-09-05 19:16:27 +02:00
|
|
|
self.login_url = os.path.join(env['target'].geturl(), self.login_url)
|
2013-05-24 11:04:12 +02:00
|
|
|
login = get_response(env, request, self.login_url, cj)
|
|
|
|
if login.code == 502:
|
|
|
|
return login
|
|
|
|
if self.form_values.has_key('form_attrs'):
|
2013-05-23 22:30:16 +02:00
|
|
|
html = fromstring(login.msg)
|
|
|
|
for form in html.forms:
|
|
|
|
is_good = True
|
|
|
|
for key, value in self.form_values['form_attrs'].iteritems():
|
|
|
|
if form.get(key) != value:
|
|
|
|
is_good = False
|
|
|
|
if is_good:
|
|
|
|
auth_form = form
|
|
|
|
break
|
|
|
|
|
|
|
|
if auth_form == None:
|
2014-06-03 10:37:47 +02:00
|
|
|
logger.critical("%r %r: can't find login form on %r",
|
|
|
|
env['HTTP_HOST'], env['PATH_INFO'], self.login_url)
|
2013-05-23 22:30:16 +02:00
|
|
|
return _500(env['PATH_INFO'], "Replay: Can't find login form")
|
|
|
|
params = {}
|
|
|
|
for input in auth_form.inputs:
|
|
|
|
if input.name and input.type != 'button':
|
|
|
|
if input.value:
|
|
|
|
params[input.name] = input.value.encode('utf-8')
|
|
|
|
else:
|
|
|
|
params[input.name] = ''
|
|
|
|
for key, value in post_values.iteritems():
|
|
|
|
params[key] = value
|
2011-09-22 12:31:46 +02:00
|
|
|
else:
|
2013-05-23 22:30:16 +02:00
|
|
|
params = post_values
|
|
|
|
|
2013-05-24 11:04:12 +02:00
|
|
|
if not self.form_values.has_key('post_url'):
|
2014-09-02 11:55:15 +02:00
|
|
|
if len(auth_form) and not auth_form.action:
|
2014-06-03 10:37:47 +02:00
|
|
|
logger.critical("%r %r: don't find form action on %r",
|
|
|
|
env['HTTP_HOST'], env['PATH_INFO'], self.login_url)
|
2013-05-24 11:04:12 +02:00
|
|
|
return _500(env['PATH_INFO'], 'Replay: form action not found')
|
|
|
|
action = auth_form.action
|
|
|
|
|
2011-09-22 12:31:46 +02:00
|
|
|
if not "://" in action:
|
2014-09-05 19:16:27 +02:00
|
|
|
login_url = re.sub(r'\?.*$', '', self.login_url)
|
|
|
|
action = os.path.join(login_url, action)
|
2011-09-19 22:47:35 +02:00
|
|
|
|
2011-10-19 11:59:02 +02:00
|
|
|
cookies = login.cookies
|
2011-09-19 19:18:32 +02:00
|
|
|
headers = HTTPHeader()
|
2011-09-22 12:31:46 +02:00
|
|
|
headers.load_from_dict(self.form_values['form_headers'])
|
2013-05-23 22:30:16 +02:00
|
|
|
params = urllib.urlencode(params)
|
2011-09-21 19:34:02 +02:00
|
|
|
request = HTTPRequest(cookies, headers, "POST", params)
|
2011-09-22 12:31:46 +02:00
|
|
|
return get_response(env, request, action, cj)
|
2011-09-13 19:13:14 +02:00
|
|
|
|
2013-05-21 11:59:19 +02:00
|
|
|
def _save_association(self, env, unique_id, post_values):
|
2011-12-07 18:49:50 +01:00
|
|
|
""" save an association in the database
|
|
|
|
env: wsgi environment
|
2013-05-21 11:59:19 +02:00
|
|
|
unique_id: idp uinique id
|
2012-07-08 20:55:13 +02:00
|
|
|
post_values: dict with the post values
|
2011-12-07 18:49:50 +01:00
|
|
|
"""
|
2013-06-05 15:48:01 +02:00
|
|
|
logger.debug('AuthForm._save_association: save a new association')
|
2013-05-21 11:59:19 +02:00
|
|
|
sp_login = post_values[self.form_values['username_field']]
|
|
|
|
if config.encrypt_sp_password:
|
2013-06-04 19:20:10 +02:00
|
|
|
password = self.encrypt_pwd(post_values[self.form_values['password_field']])
|
|
|
|
post_values[self.form_values['password_field']] = password
|
2014-09-10 18:51:54 +02:00
|
|
|
|
|
|
|
asso_id = Association.update_or_create(self.site_name, sp_login,
|
|
|
|
post_values, unique_id)
|
2014-10-28 16:09:26 +01:00
|
|
|
old_association_id = env['beaker.session'].get('old_association_id')
|
|
|
|
if old_association_id and old_association_id != asso_id:
|
|
|
|
Association.delete(old_association_id)
|
|
|
|
env['beaker.session']['old_association_id'] = None
|
2013-05-21 11:59:19 +02:00
|
|
|
env['beaker.session']['unique_id'] = unique_id
|
2014-09-10 18:51:54 +02:00
|
|
|
env['beaker.session'][self.site_name] = asso_id
|
2011-12-07 18:49:50 +01:00
|
|
|
env['beaker.session'].save()
|
|
|
|
|
2014-07-09 19:48:09 +02:00
|
|
|
def associate_submit(self, env, values, request, response):
|
2011-10-04 14:31:03 +02:00
|
|
|
""" Associate your login / password into your database
|
2011-09-13 19:13:14 +02:00
|
|
|
"""
|
2011-12-23 11:01:03 +01:00
|
|
|
logger.debug("Trying to associate a user")
|
2013-05-21 11:59:19 +02:00
|
|
|
unique_id = env['beaker.session'].get('unique_id')
|
2011-09-13 19:13:14 +02:00
|
|
|
if request.msg:
|
2013-05-21 11:59:19 +02:00
|
|
|
if not unique_id:
|
2011-12-23 11:01:03 +01:00
|
|
|
logger.warning("Association failed: user isn't login on Mandaye")
|
2014-05-21 13:15:40 +02:00
|
|
|
return _302(self.urls.get('connection_url'))
|
2013-06-04 19:20:10 +02:00
|
|
|
if type(request.msg) == str:
|
|
|
|
post = parse_qs(request.msg, request)
|
|
|
|
else:
|
|
|
|
post = parse_qs(request.msg.read(), request)
|
2014-06-03 10:37:47 +02:00
|
|
|
logger.debug("association post: %r", post)
|
2011-11-28 17:49:29 +01:00
|
|
|
qs = parse_qs(env['QUERY_STRING'])
|
|
|
|
for key, value in qs.iteritems():
|
|
|
|
qs[key] = value[0]
|
2012-07-08 20:55:13 +02:00
|
|
|
post_fields = self.form_values['post_fields']
|
|
|
|
post_values = {}
|
|
|
|
for field in post_fields:
|
|
|
|
if not post.has_key(field):
|
|
|
|
logger.info('Association auth failed: form not correctly filled')
|
2014-06-03 10:37:47 +02:00
|
|
|
logger.info('%r is missing', field)
|
2012-07-08 20:55:13 +02:00
|
|
|
qs['type'] = 'badlogin'
|
2014-05-21 13:15:40 +02:00
|
|
|
return _302(self.urls.get('associate_url') + "?%s" % urllib.urlencode(qs))
|
2012-07-08 20:55:13 +02:00
|
|
|
post_values[field] = post[field][0]
|
|
|
|
response = self.replay(env, post_values)
|
2014-07-09 19:48:09 +02:00
|
|
|
if eval(values['condition']):
|
2011-12-23 11:01:03 +01:00
|
|
|
logger.debug("Replay works: save the association")
|
2013-05-21 11:59:19 +02:00
|
|
|
self._save_association(env, unique_id, post_values)
|
2011-11-28 17:49:29 +01:00
|
|
|
if qs.has_key('next_url'):
|
|
|
|
return _302(qs['next_url'], response.cookies)
|
2011-11-24 15:19:04 +01:00
|
|
|
return response
|
2013-05-27 18:43:51 +02:00
|
|
|
logger.info('Auth failed: Bad password or login')
|
2011-11-28 17:49:29 +01:00
|
|
|
qs['type'] = 'badlogin'
|
2014-05-21 13:15:40 +02:00
|
|
|
return _302(self.urls.get('associate_url') + "?%s" % urllib.urlencode(qs))
|
2011-09-13 19:13:14 +02:00
|
|
|
|
2014-09-10 18:51:54 +02:00
|
|
|
def _login_sp_user(self, association, env, condition, values):
|
2013-05-21 11:59:19 +02:00
|
|
|
""" Log in sp user
|
2011-10-05 15:51:24 +02:00
|
|
|
"""
|
2014-09-10 18:51:54 +02:00
|
|
|
if not association['sp_login']:
|
2011-10-05 15:51:24 +02:00
|
|
|
return _500(env['PATH_INFO'],
|
|
|
|
'Invalid values for AuthFormDispatcher.login')
|
2014-09-10 18:51:54 +02:00
|
|
|
post_values = copy.copy(association['sp_post_values'])
|
2013-05-21 11:59:19 +02:00
|
|
|
if config.encrypt_sp_password:
|
2013-06-04 19:20:10 +02:00
|
|
|
password = self.decrypt_pwd(post_values[self.form_values['password_field']])
|
|
|
|
post_values[self.form_values['password_field']] = password
|
2012-07-08 20:55:13 +02:00
|
|
|
response = self.replay(env, post_values)
|
2013-05-27 19:13:07 +02:00
|
|
|
qs = parse_qs(env['QUERY_STRING'])
|
2011-10-05 15:51:24 +02:00
|
|
|
if condition and eval(condition):
|
2014-09-10 18:51:54 +02:00
|
|
|
Association.update_last_connection(association['id'])
|
2014-10-28 16:09:26 +01:00
|
|
|
env['beaker.session']['old_association_id'] = None
|
2014-09-10 18:51:54 +02:00
|
|
|
env['beaker.session'][self.site_name] = association['id']
|
2011-10-05 15:51:24 +02:00
|
|
|
env['beaker.session'].save()
|
2013-05-27 19:13:07 +02:00
|
|
|
if qs.has_key('next_url'):
|
|
|
|
return _302(qs['next_url'][0], response.cookies)
|
|
|
|
else:
|
|
|
|
return response
|
2011-10-05 15:51:24 +02:00
|
|
|
else:
|
2014-10-28 16:09:26 +01:00
|
|
|
env['beaker.session']['old_association_id'] = association['id']
|
|
|
|
env['beaker.session'].save()
|
2014-05-21 13:15:40 +02:00
|
|
|
return _302(self.urls.get('associate_url') + "?type=failed")
|
2011-10-05 15:51:24 +02:00
|
|
|
|
2014-07-09 19:48:09 +02:00
|
|
|
def login(self, env, values, request, response):
|
2011-09-13 19:13:14 +02:00
|
|
|
""" Automatic login on a site with a form
|
|
|
|
"""
|
2013-05-21 11:59:19 +02:00
|
|
|
# Specific method to get current idp unique id
|
|
|
|
unique_id = self.get_current_unique_id(env)
|
2011-12-23 11:01:03 +01:00
|
|
|
logger.debug('Trying to login on Mandaye')
|
2013-05-21 11:59:19 +02:00
|
|
|
if not unique_id:
|
2011-09-13 19:13:14 +02:00
|
|
|
return _401('Access denied: invalid token')
|
2011-10-03 18:33:03 +02:00
|
|
|
|
2011-12-07 18:56:35 +01:00
|
|
|
# FIXME: hack to force beaker to generate an id
|
|
|
|
# somtimes beaker doesn't do it by himself
|
|
|
|
env['beaker.session'].regenerate_id()
|
|
|
|
|
2013-05-21 11:59:19 +02:00
|
|
|
env['beaker.session']['unique_id'] = unique_id
|
2011-10-03 18:33:03 +02:00
|
|
|
env['beaker.session'].save()
|
|
|
|
|
2013-05-21 11:59:19 +02:00
|
|
|
logger.debug('User %s successfully login' % env['beaker.session']['unique_id'])
|
|
|
|
|
2014-09-10 18:51:54 +02:00
|
|
|
association = Association.get_last_connected(self.site_name, unique_id)
|
|
|
|
if not association:
|
2013-05-21 11:59:19 +02:00
|
|
|
logger.debug('User %s is not associate' % env['beaker.session']['unique_id'])
|
2014-05-21 13:15:40 +02:00
|
|
|
return _302(self.urls.get('associate_url') + "?type=first")
|
2014-09-10 18:51:54 +02:00
|
|
|
return self._login_sp_user(association, env, values['condition'], values)
|
2011-10-04 14:31:03 +02:00
|
|
|
|
2011-10-20 12:13:35 +02:00
|
|
|
def logout(self, env, values, request, response):
|
|
|
|
""" Destroy the Beaker session
|
|
|
|
"""
|
2011-12-23 11:01:03 +01:00
|
|
|
logger.debug('Logout from Mandaye')
|
2011-10-20 12:13:35 +02:00
|
|
|
env['beaker.session'].delete()
|
|
|
|
return response
|
|
|
|
|
2014-07-11 14:20:21 +02:00
|
|
|
def auto_connection(self, env, values, request, response):
|
2014-07-11 13:54:20 +02:00
|
|
|
connection_url = self.urls["connection_url"]
|
|
|
|
logger.debug("Redirection using url : %s" % connection_url)
|
|
|
|
return _302(connection_url)
|
|
|
|
|
2014-01-20 10:55:26 +01:00
|
|
|
def local_logout(self, env, values, request, response):
|
|
|
|
logger.info('SP logout initiated by Mandaye')
|
|
|
|
self.logout(env, values, request, response)
|
|
|
|
|
|
|
|
next_url = None
|
|
|
|
qs = parse_qs(env['QUERY_STRING'])
|
|
|
|
if qs.has_key('RelayState'):
|
|
|
|
next_url = qs['RelayState'][0]
|
|
|
|
elif qs.has_key('next_url'):
|
|
|
|
next_url = qs['next_url'][0]
|
|
|
|
elif values.has_key('next_url'):
|
|
|
|
next_url = values['next_url']
|
2014-09-12 10:01:30 +02:00
|
|
|
logout_url = None
|
|
|
|
if self.env['mandaye.config'].has_key('sp_logout_url'):
|
|
|
|
logout_url = self.env['mandaye.config'].get('sp_logout_url')
|
|
|
|
elif self.env['mandaye.config'].has_key('saml2_sp_logout_url'):
|
|
|
|
logger.warning("Deprecated saml2_sp_logout_url optioin use sp_logout_url instead")
|
|
|
|
logout_url = self.env['mandaye.config'].get('saml2_sp_logout_url')
|
2014-01-20 10:55:26 +01:00
|
|
|
|
|
|
|
req_cookies = request.cookies
|
2014-09-12 10:01:30 +02:00
|
|
|
if not logout_url:
|
|
|
|
logger.warning('sp_logout_url not set into vhost configuration only removing cookies')
|
|
|
|
for cookie in req_cookies.values():
|
|
|
|
cookie['expires'] = 'Thu, 01 Jan 1970 00:00:01 GMT'
|
|
|
|
cookie['path'] = self.env['mandaye.config'].get('cookies_path', '/')
|
|
|
|
if next_url:
|
|
|
|
return _302(next_url, req_cookies)
|
|
|
|
else:
|
|
|
|
return _302('/', req_cookies)
|
2014-10-08 17:54:12 +02:00
|
|
|
request = HTTPRequest(req_cookies)
|
|
|
|
response = get_response(env, request, logout_url)
|
|
|
|
if next_url:
|
|
|
|
return _302(next_url, response.cookies)
|
|
|
|
else:
|
|
|
|
return response
|
2014-01-20 10:55:26 +01:00
|
|
|
|
2011-10-04 14:31:03 +02:00
|
|
|
def change_user(self, env, values, request, response):
|
2011-10-04 17:14:39 +02:00
|
|
|
""" Multi accounts feature
|
|
|
|
Change the current login user
|
2011-10-04 14:31:03 +02:00
|
|
|
You must call this method into a response filter
|
|
|
|
This method must have a query string with a username parameter
|
|
|
|
"""
|
|
|
|
# TODO: need to logout the first
|
2013-05-21 11:59:19 +02:00
|
|
|
unique_id = env['beaker.session']['unique_id']
|
2011-10-04 14:31:03 +02:00
|
|
|
qs = parse_qs(env['QUERY_STRING'])
|
2014-04-16 12:26:53 +02:00
|
|
|
if not qs.has_key('id') and not unique_id:
|
2011-10-19 18:45:05 +02:00
|
|
|
return _401('Access denied: beaker session invalid or not qs id')
|
2014-04-16 12:26:53 +02:00
|
|
|
if qs.has_key('id'):
|
2014-09-10 18:51:54 +02:00
|
|
|
asso_id = qs['id'][0]
|
|
|
|
association = Association.get_by_id(asso_id)
|
2014-04-16 12:26:53 +02:00
|
|
|
else:
|
2014-09-10 18:51:54 +02:00
|
|
|
association = Association.get_last_connected(self.site_name, unique_id)
|
|
|
|
if not association:
|
2014-05-21 13:15:40 +02:00
|
|
|
return _302(self.urls.get('associate_url'))
|
2014-09-10 18:51:54 +02:00
|
|
|
return self._login_sp_user(association, env, 'response.code==302', values)
|
2011-09-13 19:13:14 +02:00
|
|
|
|
2011-10-04 17:14:39 +02:00
|
|
|
def disassociate(self, env, values, request, response):
|
2013-05-29 18:13:17 +02:00
|
|
|
""" Disassociate an account with the Mandaye account
|
|
|
|
You need to put the id of the sp user you want to disassociate
|
2014-01-20 10:55:26 +01:00
|
|
|
in the query string (..?id=42) or use by service provider name
|
|
|
|
(..?sp_name=)
|
2011-10-04 17:14:39 +02:00
|
|
|
"""
|
2014-01-20 10:55:26 +01:00
|
|
|
if env['beaker.session'].has_key('unique_id'):
|
|
|
|
unique_id = env['beaker.session']['unique_id']
|
2011-10-28 17:51:26 +02:00
|
|
|
else:
|
|
|
|
return _401('Access denied: no session')
|
2011-10-04 17:14:39 +02:00
|
|
|
qs = parse_qs(env['QUERY_STRING'])
|
2014-01-20 10:55:26 +01:00
|
|
|
if values.get('next_url'):
|
|
|
|
next_url = values.get('next_url')
|
|
|
|
else:
|
|
|
|
next_url = '/'
|
|
|
|
if qs.has_key('next_url'):
|
|
|
|
next_url = qs['next_url'][0]
|
|
|
|
if qs.has_key('id'):
|
2014-09-10 18:51:54 +02:00
|
|
|
asso_id = qs['id'][0]
|
|
|
|
if Association.has_id(asso_id):
|
|
|
|
Association.delete(asso_id)
|
|
|
|
if Association.get(self.site_name, unique_id):
|
2014-04-16 12:26:53 +02:00
|
|
|
env['QUERY_STRING'] = ''
|
|
|
|
return self.change_user(env, values, request, response)
|
2014-01-20 10:55:26 +01:00
|
|
|
else:
|
|
|
|
return _401('Access denied: bad id')
|
|
|
|
elif qs.has_key('sp_name'):
|
|
|
|
sp_name = qs['sp_name'][0]
|
2014-09-10 18:51:54 +02:00
|
|
|
for asso in \
|
|
|
|
Association.get(sp_name, unique_id):
|
|
|
|
Association.delete(asso['id'])
|
2011-10-19 18:45:05 +02:00
|
|
|
else:
|
2014-01-20 10:55:26 +01:00
|
|
|
return _401('Access denied: no id or sp name')
|
|
|
|
values['next_url'] = next_url
|
|
|
|
if qs.has_key('logout'):
|
|
|
|
return self.local_logout(env, values, request, response)
|
|
|
|
return _302(next_url)
|
2011-10-04 17:14:39 +02:00
|
|
|
|
2014-07-09 14:32:07 +02:00
|
|
|
def is_connected_a2(self, env, request, response):
|
|
|
|
""" Auto connection only which works only with Authentic2
|
|
|
|
"""
|
|
|
|
if request.cookies.has_key('A2_OPENED_SESSION') and\
|
|
|
|
not env['beaker.session'].has_key('unique_id'):
|
2014-07-09 19:48:09 +02:00
|
|
|
logger.info('Trying an auto connection')
|
2014-07-09 14:32:07 +02:00
|
|
|
return True
|
|
|
|
return False
|
2011-10-04 14:31:03 +02:00
|
|
|
|