Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F92017915
external_authentication_ldap.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Nov 16, 16:06
Size
9 KB
Mime Type
text/x-python
Expires
Mon, Nov 18, 16:06 (2 d)
Engine
blob
Format
Raw Data
Handle
22364164
Attached To
R3600 invenio-infoscience
external_authentication_ldap.py
View Options
# -*- coding: utf-8 -*-
##
## $Id$
##
## This file is part of CDS Invenio.
## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
##
## CDS Invenio is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2 of the
## License, or (at your option) any later version.
##
## CDS Invenio is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with CDS Invenio; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
"""External user authentication for EPFL's LDAP instance.
This LDAP external authentication system relies on a collaborative LDAP
organized like this:
o=EPFL, c=CH
|
|
+--ou=groups
| |
| |
| +--- cn=xxx
| displayName= name of the group
| uniqueIdentifier= some local id for groups
|
|
|
+--ou=users
| |
| |
| +---uid= some local id for users (ex: grfavre)
| uniqueIdentifier= another local id (ex: 128933)
| mail=xxx@xxx.xx
| memberOf= id of a group
| memberOf= id of another group
|
+
This example of an LDAP authentication should help you develop yours in your
specific installation.
"""
__revision__
=
\
"$Id$"
import
ldap
from
invenio.external_authentication
import
ExternalAuth
,
\
InvenioWebAccessExternalAuthError
CFG_EXTERNAL_AUTH_LDAP_SERVERS
=
[
'ldap://scoldap.epfl.ch'
]
CFG_EXTERNAL_AUTH_LDAP_CONTEXT
=
"o=EPFL,c=CH"
CFG_EXTERNAL_AUTH_LDAP_USER_UID
=
[
"uid"
,
"uniqueIdentifier"
,
"mail"
]
CFG_EXTERNAL_AUTH_LDAP_MAIL_ENTRY
=
'mail'
CFG_EXTERNAL_AUTH_LDAP_GROUP_MEMBERSHIP
=
'memberOf'
CFG_EXTERNAL_AUTH_LDAP_GROUP_UID
=
'uniqueIdentifier'
CFG_EXTERNAL_AUTH_LDAP_GROUP_NAME
=
'displayName'
CFG_EXTERNAL_AUTH_LDAP_HIDDEN_GROUPS
=
[
'EPFL-unit'
,
'users'
]
class
ExternalAuthLDAP
(
ExternalAuth
):
"""
External authentication example for a custom LDAP-based
authentication service.
"""
def
__init__
(
self
):
"""Initialize stuff here"""
ExternalAuth
.
__init__
(
self
)
self
.
enforce_external_nicknames
=
True
def
_ldap_try
(
self
,
command
):
""" Try to run the specified command on the first LDAP server that
is not down."""
for
server
in
CFG_EXTERNAL_AUTH_LDAP_SERVERS
:
try
:
connection
=
ldap
.
initialize
(
server
)
return
command
(
connection
)
except
ldap
.
SERVER_DOWN
,
error_message
:
continue
raise
InvenioWebAccessExternalAuthError
def
auth_user
(
self
,
username
,
password
,
req
=
None
):
"""
Check USERNAME and PASSWORD against the LDAP system.
Return None if authentication failed, or the email address of the
person if the authentication was successful.
Raise InvenioWebAccessExternalAuthError in case of external troubles.
Note: for SSO the parameter are discarded and overloaded by Shibboleth
variables
"""
if
not
password
:
return
None
query
=
'(|'
+
''
.
join
([
'(
%s
=
%s
)'
%
(
attrib
,
username
)
for
attrib
in
CFG_EXTERNAL_AUTH_LDAP_USER_UID
])
\
+
')'
def
_check
(
connection
):
users
=
connection
.
search_s
(
CFG_EXTERNAL_AUTH_LDAP_CONTEXT
,
ldap
.
SCOPE_SUBTREE
,
query
)
# We pick the first result, as all the data we are interested
# in should be the same in all the entries.
if
len
(
users
):
user_dn
,
user_info
=
users
[
0
]
else
:
return
None
try
:
connection
.
simple_bind_s
(
user_dn
,
password
)
except
ldap
.
INVALID_CREDENTIALS
:
# It is enough to fail on one server to consider the credential
# to be invalid
return
None
return
user_info
[
CFG_EXTERNAL_AUTH_LDAP_MAIL_ENTRY
][
0
]
return
self
.
_ldap_try
(
_check
)
def
user_exists
(
self
,
email
,
req
=
None
):
"""Check the external authentication system for existance of email.
@return True if the user exists, False otherwise
"""
query
=
'(
%s
=
%s
)'
%
(
CFG_EXTERNAL_AUTH_LDAP_MAIL_ENTRY
,
email
)
def
_check
(
connection
):
users
=
connection
.
search_s
(
CFG_EXTERNAL_AUTH_LDAP_CONTEXT
,
ldap
.
SCOPE_SUBTREE
,
query
)
return
len
(
users
)
!=
0
return
self
.
_ldap_try
(
_check
)
def
fetch_user_nickname
(
self
,
username
,
password
,
req
=
None
):
"""Given a username and a password, returns the right nickname belonging
to that user (username could be an email).
"""
query
=
'(|'
+
''
.
join
([
'(
%s
=
%s
)'
%
(
attrib
,
username
)
for
attrib
in
CFG_EXTERNAL_AUTH_LDAP_USER_UID
])
\
+
')'
def
_get_nickname
(
connection
):
users
=
connection
.
search_s
(
CFG_EXTERNAL_AUTH_LDAP_CONTEXT
,
ldap
.
SCOPE_SUBTREE
,
query
)
# We pick the first result, as all the data we are interested
# in should be the same in all the entries.
if
len
(
users
):
user_dn
,
user_info
=
users
[
0
]
else
:
return
None
emails
=
user_info
[
CFG_EXTERNAL_AUTH_LDAP_MAIL_ENTRY
]
if
len
(
emails
):
email
=
emails
[
0
]
else
:
return
False
(
left_part
,
right_part
)
=
email
.
split
(
'@'
)
nickname
=
left_part
.
replace
(
'.'
,
' '
)
.
title
()
if
right_part
!=
'epfl.ch'
:
nickname
+=
' - '
+
right_part
return
nickname
return
self
.
_ldap_try
(
_get_nickname
)
def
fetch_user_groups_membership
(
self
,
username
,
password
,
req
=
None
):
"""Given a username and a password, returns a dictionary of groups
and their description to which the user is subscribed.
Raise InvenioWebAccessExternalAuthError in case of troubles.
"""
query_person
=
'(|'
+
''
.
join
([
'(
%s
=
%s
)'
%
(
attrib
,
username
)
for
attrib
in
CFG_EXTERNAL_AUTH_LDAP_USER_UID
])
\
+
')'
def
_get_groups
(
connection
):
users
=
connection
.
search_s
(
CFG_EXTERNAL_AUTH_LDAP_CONTEXT
,
ldap
.
SCOPE_SUBTREE
,
query_person
)
if
len
(
users
):
user_dn
,
user_info
=
users
[
0
]
else
:
return
{}
groups
=
{}
group_ids
=
user_info
[
CFG_EXTERNAL_AUTH_LDAP_GROUP_MEMBERSHIP
]
for
group_id
in
group_ids
:
query_group
=
'(
%s
=
%s
)'
%
(
CFG_EXTERNAL_AUTH_LDAP_GROUP_UID
,
group_id
)
ldap_group
=
connection
.
search_s
(
CFG_EXTERNAL_AUTH_LDAP_CONTEXT
,
ldap
.
SCOPE_SUBTREE
,
query_group
)
if
len
(
ldap_group
):
group_dn
,
group_infos
=
ldap_group
[
0
]
group_name
=
group_infos
[
CFG_EXTERNAL_AUTH_LDAP_GROUP_NAME
][
0
]
if
group_name
in
CFG_EXTERNAL_AUTH_LDAP_HIDDEN_GROUPS
:
continue
groups
[
group_id
]
=
group_name
return
groups
return
self
.
_ldap_try
(
_get_groups
)
def
fetch_user_preferences
(
self
,
username
,
password
=
None
,
req
=
None
):
"""Given a username and a password, returns a dictionary of keys and
values, corresponding to external infos and settings.
userprefs = {"telephone": "2392489",
"address": "10th Downing Street"}
(WEBUSER WILL erase all prefs that starts by EXTERNAL_ and will
store: "EXTERNAL_telephone"; all internal preferences can use whatever
name but starting with EXTERNAL). If a pref begins with HIDDEN_ it will
be ignored.
"""
query
=
'(|'
+
''
.
join
([
'(
%s
=
%s
)'
%
(
attrib
,
username
)
for
attrib
in
CFG_EXTERNAL_AUTH_LDAP_USER_UID
])
\
+
')'
def
_get_personal_infos
(
connection
):
users
=
connection
.
search_s
(
CFG_EXTERNAL_AUTH_LDAP_CONTEXT
,
ldap
.
SCOPE_SUBTREE
,
query
)
if
len
(
users
):
user_dn
,
user_info
=
users
[
0
]
return
user_info
else
:
return
{}
return
self
.
_ldap_try
(
_get_personal_infos
)
Event Timeline
Log In to Comment