Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
ssoauth
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Container registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
django
ssoauth
Commits
135adc0f
Commit
135adc0f
authored
7 years ago
by
Art
Browse files
Options
Downloads
Patches
Plain Diff
RC1.
parent
2aa97ee0
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
21
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
ssoauth/views.py
+193
-0
193 additions, 0 deletions
ssoauth/views.py
with
193 additions
and
0 deletions
ssoauth/views.py
0 → 100644
+
193
−
0
View file @
135adc0f
from
django.views.generic
import
View
,
FormView
from
django
import
http
from
django
import
urls
from
django.utils.decorators
import
method_decorator
from
django.views.decorators.csrf
import
csrf_exempt
from
django.contrib
import
auth
as
contrib_auth
from
django.contrib.auth
import
models
as
contrib_auth_models
from
django
import
conf
from
django.core
import
exceptions
from
django
import
forms
from
.
import
logger
from
.
import
app_settings
from
.
import
auth_utils
from
onelogin.saml2.utils
import
OneLogin_Saml2_Utils
from
onelogin.saml2.auth
import
OneLogin_Saml2_Auth
from
collections
import
OrderedDict
ATTRIBUTE_MAPPING
=
dict
(
# https://commons.lbl.gov/display/IDMgmt/Attribute+Definitions
username
=
"
urn:oid:0.9.2342.19200300.100.1.1
"
,
email
=
"
urn:oid:0.9.2342.19200300.100.1.3
"
,
forename
=
"
urn:oid:2.5.4.42
"
,
surname
=
"
urn:oid:2.5.4.4
"
,
uuid
=
"
UUID
"
,
idm_groups
=
"
IDMGroups
"
,
)
class
SAMLMixin
:
"""
Merges Django runtime info and settings for OneLogin toolkit
"""
@staticmethod
def
get_onelogin_request_data
(
request
):
return
{
# since nginx is in the way, the settings cannot be fetched from the request
'
https
'
:
'
on
'
,
# nginx should do it and django will never have a clue
'
http_host
'
:
app_settings
.
SP_HOST
,
# nginx might change it
'
server_port
'
:
app_settings
.
SP_PORT
,
# nginx will change it
'
script_name
'
:
request
.
META
[
'
PATH_INFO
'
],
'
get_data
'
:
request
.
GET
.
copy
(),
'
post_data
'
:
request
.
POST
.
copy
(),
}
@classmethod
def
get_onelogin_auth
(
cls
,
request
):
return
OneLogin_Saml2_Auth
(
request_data
=
cls
.
get_onelogin_request_data
(
request
),
old_settings
=
app_settings
.
ONELOGIN_SETTINGS
)
class
LogInView
(
SAMLMixin
,
View
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
next_url
=
"
{host}{relative}
"
.
format
(
host
=
OneLogin_Saml2_Utils
.
get_self_url
(
self
.
get_onelogin_request_data
(
request
)),
relative
=
urls
.
reverse
(
"
sso-saml2-meta
"
),
)
auth
=
self
.
get_onelogin_auth
(
request
)
login
=
auth
.
login
(
return_to
=
next_url
)
return
http
.
HttpResponseRedirect
(
login
)
class
LogOutView
(
View
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
contrib_auth
.
logout
(
request
)
logger
.
warning
(
"
Don
'
t know what to do after logging out in Django.
"
)
return
http
.
HttpResponseRedirect
(
urls
.
reverse
(
"
sso-dev
"
))
@method_decorator
(
csrf_exempt
,
"
dispatch
"
)
class
ACSAuthNView
(
SAMLMixin
,
View
):
"""
This is NOT a universal ACS. It can only consume artifacts with an AuthN statement.
It
'
s how OneLogin toolkit works, cannot easily detect/process other statements here, so I don
'
t even try.
"""
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
auth
=
self
.
get_onelogin_auth
(
request
)
auth
.
process_response
()
if
auth
.
is_authenticated
():
self
.
log_in_user
(
request
,
auth
)
if
conf
.
settings
.
DEBUG
:
request
.
session
[
"
DEBUG_SAML2_ATTRS
"
]
=
auth
.
get_attributes
()
return
http
.
HttpResponseRedirect
(
urls
.
reverse
(
"
sso-dev
"
))
else
:
logger
.
error
(
"
Not authenticated. Errors: {0}
"
.
format
(
auth
.
get_errors
()))
raise
exceptions
.
PermissionDenied
()
def
log_in_user
(
self
,
request
,
auth
):
def
get_attr
(
attribute_name
,
nullable
=
False
,
multivalued
=
False
):
attribute_id
=
ATTRIBUTE_MAPPING
[
attribute_name
]
values
=
auth
.
get_attributes
().
get
(
attribute_id
,
list
())
assert
nullable
or
values
,
"
Haven
'
t received any {0}
"
.
format
(
attribute_name
)
if
multivalued
:
return
values
else
:
assert
len
(
values
)
<=
1
,
"
Received too many {0}: {1}
"
.
format
(
attribute_name
,
values
)
return
values
[
0
]
if
values
else
None
logger
.
debug
(
"
Synchronizing user using SAML2 data: {}
"
.
format
(
auth
.
get_attributes
()))
# get the user
user
=
auth_utils
.
get_or_create_user
(
uuid
=
get_attr
(
"
uuid
"
),
username
=
get_attr
(
"
username
"
),
)
# update user data
auth_utils
.
update_user_data
(
user
=
user
,
surname
=
get_attr
(
"
surname
"
,
nullable
=
True
),
forename
=
get_attr
(
"
forename
"
,
nullable
=
True
),
email
=
get_attr
(
"
email
"
,
nullable
=
True
),
)
auth_utils
.
set_user_groups
(
user
=
user
,
group_dn_list
=
get_attr
(
"
idm_groups
"
,
nullable
=
True
,
multivalued
=
True
)
or
list
()
)
auth_utils
.
set_user_compat_flags
(
user
=
user
)
request
.
user
=
user
contrib_auth
.
login
(
request
,
user
)
logger
.
debug
(
"
Logged in {user}
"
.
format
(
**
locals
()))
class
MetadataView
(
SAMLMixin
,
View
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
meta
=
app_settings
.
ONELOGIN_SETTINGS
.
get_sp_metadata
()
errors
=
app_settings
.
ONELOGIN_SETTINGS
.
validate_metadata
(
meta
)
if
errors
:
for
e
in
errors
:
logger
.
error
(
e
)
return
http
.
HttpResponseServerError
()
return
http
.
HttpResponse
(
content_type
=
"
text/xml
"
,
content
=
meta
)
class
DevView
(
FormView
):
class
DevForm
(
forms
.
Form
):
username
=
forms
.
CharField
(
required
=
False
)
toggle_group
=
forms
.
ModelChoiceField
(
queryset
=
contrib_auth_models
.
Group
.
objects
.
all
(),
required
=
False
,
)
template_name
=
"
ssoauth/dev.html
"
form_class
=
DevForm
def
__init__
(
self
,
*
args
,
**
kwargs
):
if
not
conf
.
settings
.
DEBUG
and
False
:
raise
exceptions
.
PermissionDenied
()
else
:
super
().
__init__
(
*
args
,
**
kwargs
)
def
get_context_data
(
self
,
**
kwargs
):
assert
conf
.
settings
.
DEBUG
context
=
super
().
get_context_data
(
**
kwargs
)
user
=
self
.
request
.
user
groups
=
list
(
user
.
groups
.
all
())
if
user
.
is_authenticated
else
list
()
context
[
"
tables
"
]
=
[
[
"
User
"
,
OrderedDict
([
[
"
user
"
,
"
{0} ({1})
"
.
format
(
self
.
request
.
user
.
username
,
self
.
request
.
user
.
__class__
.
__name__
)],
[
"
groups
"
,
"
,
"
.
join
(
str
(
g
)
for
g
in
groups
)],
])],
[
"
SAML2 Attributes
"
,
self
.
request
.
session
.
get
(
"
DEBUG_SAML2_ATTRS
"
)],
[
"
Session
"
,
dict
(
self
.
request
.
session
)],
]
return
context
def
form_valid
(
self
,
form
):
assert
conf
.
settings
.
DEBUG
username
=
form
.
cleaned_data
[
"
username
"
]
toggle_group
=
form
.
cleaned_data
[
"
toggle_group
"
]
if
username
:
try
:
user
=
auth_utils
.
get_user
(
username
=
username
)
except
exceptions
.
ObjectDoesNotExist
:
import
uuid
user
=
auth_utils
.
get_or_create_user
(
username
=
username
,
uuid
=
uuid
.
uuid4
())
self
.
request
.
user
=
user
contrib_auth
.
login
(
request
=
self
.
request
,
user
=
user
)
elif
toggle_group
:
if
self
.
request
.
user
.
is_authenticated
:
if
toggle_group
in
self
.
request
.
user
.
groups
.
all
():
self
.
request
.
user
.
groups
.
remove
(
toggle_group
)
else
:
self
.
request
.
user
.
groups
.
add
(
toggle_group
)
else
:
logger
.
warning
(
"
Too anonymous to join groups.
"
)
return
http
.
HttpResponseRedirect
(
urls
.
reverse
(
"
sso-dev
"
))
This diff is collapsed.
Click to expand it.
Prev
1
2
Next
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment