Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
cd941ead
Commit
cd941ead
authored
Jun 12, 2015
by
Braden MacDonald
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New SAML/Shibboleth tests - PR 8518
parent
b4904adc
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
561 additions
and
9 deletions
+561
-9
common/djangoapps/student/views.py
+1
-1
common/djangoapps/third_party_auth/management/commands/saml.py
+2
-2
common/djangoapps/third_party_auth/models.py
+16
-5
common/djangoapps/third_party_auth/tests/data/saml_key.key
+15
-0
common/djangoapps/third_party_auth/tests/data/saml_key.pub
+17
-0
common/djangoapps/third_party_auth/tests/data/saml_key_alt.key
+16
-0
common/djangoapps/third_party_auth/tests/data/saml_key_alt.pub
+15
-0
common/djangoapps/third_party_auth/tests/data/testshib_metadata.xml
+155
-0
common/djangoapps/third_party_auth/tests/data/testshib_response.txt
+2
-0
common/djangoapps/third_party_auth/tests/specs/test_testshib.py
+229
-0
common/djangoapps/third_party_auth/tests/test_views.py
+64
-0
common/djangoapps/third_party_auth/tests/testutil.py
+28
-0
lms/djangoapps/student_account/views.py
+1
-1
No files found.
common/djangoapps/student/views.py
View file @
cd941ead
...
@@ -368,7 +368,7 @@ def signin_user(request):
...
@@ -368,7 +368,7 @@ def signin_user(request):
for
msg
in
messages
.
get_messages
(
request
):
for
msg
in
messages
.
get_messages
(
request
):
if
msg
.
extra_tags
.
split
()[
0
]
==
"social-auth"
:
if
msg
.
extra_tags
.
split
()[
0
]
==
"social-auth"
:
# msg may or may not be translated. Try translating [again] in case we are able to:
# msg may or may not be translated. Try translating [again] in case we are able to:
third_party_auth_error
=
_
(
msg
)
# pylint: disable=translation-of-non-string
third_party_auth_error
=
_
(
unicode
(
msg
)
)
# pylint: disable=translation-of-non-string
break
break
context
=
{
context
=
{
...
...
common/djangoapps/third_party_auth/management/commands/saml.py
View file @
cd941ead
...
@@ -60,7 +60,7 @@ class Command(BaseCommand):
...
@@ -60,7 +60,7 @@ class Command(BaseCommand):
self
.
stdout
.
write
(
"
\n
→ Fetching {}
\n
"
.
format
(
url
))
self
.
stdout
.
write
(
"
\n
→ Fetching {}
\n
"
.
format
(
url
))
if
not
url
.
lower
()
.
startswith
(
'https'
):
if
not
url
.
lower
()
.
startswith
(
'https'
):
self
.
stdout
.
write
(
"→ WARNING: This URL is not secure! It should use HTTPS.
\n
"
)
self
.
stdout
.
write
(
"→ WARNING: This URL is not secure! It should use HTTPS.
\n
"
)
response
=
requests
.
get
(
url
,
verify
=
True
)
# May raise HTTPError or SSLError
response
=
requests
.
get
(
url
,
verify
=
True
)
# May raise HTTPError or SSLError
or ConnectionError
response
.
raise_for_status
()
# May raise an HTTPError
response
.
raise_for_status
()
# May raise an HTTPError
try
:
try
:
...
@@ -75,7 +75,7 @@ class Command(BaseCommand):
...
@@ -75,7 +75,7 @@ class Command(BaseCommand):
public_key
,
sso_url
,
expires_at
=
self
.
_parse_metadata_xml
(
xml
,
entity_id
)
public_key
,
sso_url
,
expires_at
=
self
.
_parse_metadata_xml
(
xml
,
entity_id
)
self
.
_update_data
(
entity_id
,
public_key
,
sso_url
,
expires_at
)
self
.
_update_data
(
entity_id
,
public_key
,
sso_url
,
expires_at
)
except
Exception
as
err
:
# pylint: disable=broad-except
except
Exception
as
err
:
# pylint: disable=broad-except
self
.
stderr
.
write
(
"→ ERROR: {}
\n\n
"
.
format
(
err
.
message
))
self
.
stderr
.
write
(
u
"→ ERROR: {}
\n\n
"
.
format
(
err
.
message
))
@classmethod
@classmethod
def
_parse_metadata_xml
(
cls
,
xml
,
entity_id
):
def
_parse_metadata_xml
(
cls
,
xml
,
entity_id
):
...
...
common/djangoapps/third_party_auth/models.py
View file @
cd941ead
...
@@ -8,6 +8,7 @@ from django.conf import settings
...
@@ -8,6 +8,7 @@ from django.conf import settings
from
django.core.exceptions
import
ValidationError
from
django.core.exceptions
import
ValidationError
from
django.db
import
models
from
django.db
import
models
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext
as
_
import
json
import
json
import
logging
import
logging
from
social.backends.base
import
BaseAuth
from
social.backends.base
import
BaseAuth
...
@@ -53,7 +54,7 @@ class AuthNotConfigured(SocialAuthBaseException):
...
@@ -53,7 +54,7 @@ class AuthNotConfigured(SocialAuthBaseException):
self
.
provider_name
=
provider_name
self
.
provider_name
=
provider_name
def
__str__
(
self
):
def
__str__
(
self
):
return
'Authentication with {} is currently unavailable.'
.
format
(
return
_
(
'Authentication with {} is currently unavailable.'
)
.
format
(
self
.
provider_name
self
.
provider_name
)
)
...
@@ -313,10 +314,20 @@ class SAMLConfiguration(ConfigurationModel):
...
@@ -313,10 +314,20 @@ class SAMLConfiguration(ConfigurationModel):
self
.
org_info_str
=
clean_json
(
self
.
org_info_str
,
dict
)
self
.
org_info_str
=
clean_json
(
self
.
org_info_str
,
dict
)
self
.
other_config_str
=
clean_json
(
self
.
other_config_str
,
dict
)
self
.
other_config_str
=
clean_json
(
self
.
other_config_str
,
dict
)
self
.
private_key
=
self
.
private_key
.
replace
(
"-----BEGIN PRIVATE KEY-----"
,
""
)
.
strip
()
self
.
private_key
=
(
self
.
private_key
=
self
.
private_key
.
replace
(
"-----END PRIVATE KEY-----"
,
""
)
.
strip
()
self
.
private_key
self
.
public_key
=
self
.
public_key
.
replace
(
"-----BEGIN CERTIFICATE-----"
,
""
)
.
strip
()
.
replace
(
"-----BEGIN RSA PRIVATE KEY-----"
,
""
)
self
.
public_key
=
self
.
public_key
.
replace
(
"-----END CERTIFICATE-----"
,
""
)
.
strip
()
.
replace
(
"-----BEGIN PRIVATE KEY-----"
,
""
)
.
replace
(
"-----END RSA PRIVATE KEY-----"
,
""
)
.
replace
(
"-----END PRIVATE KEY-----"
,
""
)
.
strip
()
)
self
.
public_key
=
(
self
.
public_key
.
replace
(
"-----BEGIN CERTIFICATE-----"
,
""
)
.
replace
(
"-----END CERTIFICATE-----"
,
""
)
.
strip
()
)
def
get_setting
(
self
,
name
):
def
get_setting
(
self
,
name
):
""" Get the value of a setting, or raise KeyError """
""" Get the value of a setting, or raise KeyError """
...
...
common/djangoapps/third_party_auth/tests/data/saml_key.key
0 → 100644
View file @
cd941ead
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDM+Nf7IeRdIIgYUke6sR3n7osHVYXwH6pb+Ovq8j3hUoy8kzT9
kJF0RB3h3Q2VJ3ZWiQtT94fZX2YYorVdoGVK2NWzjLwgpHUsgfeJq5pCjP0d2OQu
9Qvjg6YOtYP6PN3j7eK7pUcxQvIcaY9APDF57ua/zPsm3UzbjhRlJZQUewIDAQAB
AoGADWBsD/qdQaqe1x9/iOKINhuuPRNKw2n9nzT2iIW4nhzaDHB689VceL79SEE5
4rMJmQomkBtGZVxBeHgd5/dQxNy3bC9lPN1uoMuzjQs7UMk+lvy0MoHfiJcuIxPX
RdyZTV9LKN8vq+ZpVykVu6pBdDlne4psPZeQ76ynxke/24ECQQD3NX7JeluZ64la
tC6b3VHzA4Hd1qTXDWtEekh2WaR2xuKzcLyOWhqPIWprylBqVc1m+FA/LRRWQ9y6
vJMiXMk7AkEA1ELWj9DtZzk9BV1JxsDUUP0/IMAiYliVac3YrvQfys8APCY1xr9q
BAGurH4VWXuEnbx1yNXK89HqFI7kDrMtwQJAVTXtVAmHFZEosUk2X6d0He3xj8Py
4eXQObRk0daoaAC6F9weQnsweHGuOyVrfpvAx2OEVaJ2Rh3yMbPai5esDQJAS9Yh
gLqdx26M3bjJ3igQ82q3vkTHRCnwICA6la+FGFnC9LqWJg9HmmzbcqeNiy31YMHv
tzSjUV+jaXrwAkyEQQJAK/SCIVsWRhFe/ssr8hS//V+hZC4kvCv4b3NqzZK1x+Xm
7GaGMV0xEWN7shqVSRBU4O2vn/RWD6/6x3sHkU57qg==
-----END RSA PRIVATE KEY-----
common/djangoapps/third_party_auth/tests/data/saml_key.pub
0 → 100644
View file @
cd941ead
-----BEGIN CERTIFICATE-----
MIICsDCCAhmgAwIBAgIJAJrENr8EPgpcMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTUwNjEzMDEwNTE0WhcNMjUwNjEyMDEwNTE0WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQDM+Nf7IeRdIIgYUke6sR3n7osHVYXwH6pb+Ovq8j3hUoy8kzT9kJF0RB3h3Q2V
J3ZWiQtT94fZX2YYorVdoGVK2NWzjLwgpHUsgfeJq5pCjP0d2OQu9Qvjg6YOtYP6
PN3j7eK7pUcxQvIcaY9APDF57ua/zPsm3UzbjhRlJZQUewIDAQABo4GnMIGkMB0G
A1UdDgQWBBTjOyPvAuej5q4C80jlFrQmOlszmzB1BgNVHSMEbjBsgBTjOyPvAuej
5q4C80jlFrQmOlszm6FJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUt
U3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAJrENr8E
PgpcMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAV5w0SxjUTFWfL3ZG
6sgA0gKf8aV8w3AlihLt9tKCRgrK4sBK9xmfwp/fnbdxkHU58iozI894HqmrRzCi
aRLWmy3W8640E/XCa6P+i8ET7RksgNJ5cD9WtISHkGc2dnW76+2nv8d24JKeIx2w
oJAtspMywzr0SoxDIJr42N6Kvjk=
-----END CERTIFICATE-----
common/djangoapps/third_party_auth/tests/data/saml_key_alt.key
0 → 100644
View file @
cd941ead
-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMoR8CP+HlvsPRwi
VCCuWxZOdNjYa4Qre3JEWPkqlUwpci1XGTBqH7DK9b2hmBXMjYoDKOnF5pL7Y453
3JSJ2+AG7D4AJGSotA3boKF18EDgeMzAWjAhDVhTprGz+/1G+W0R4SSyY5QGyBhL
Z36xF2w5HyeiqN/Iiq3QKGl2CFORAgMBAAECgYEAwH2CAudqSCqstAZHmbI99uva
B09ybD93owxUrVbRTfIVX/eeeS4+7g0JNxGebPWkxxnneXoaAV4UIn0v1RfWKMs3
QGiBsOSup1DWWwkBfvQ1hNlJfVCqgZH1QVbhPpw9M9gxhLZQaSZoI/qY/8n/54L0
zU4S6VYBH6hnkgZZmiECQQDpYUS8HgnkMUX/qcDNBJT23qHewHsZOe6uqC+7+YxQ
xKT8iCxybDbZU7hmZ1Av8Ns4iF7EvZ0faFM8Ls76wFX1AkEA3afLUMLHfTx40XwO
oU7GWrYFyLNCc3/7JeWi6ZKzwzQqiGvFderRf/QGQsCtpLQ8VoLz/knF9TkQdSh6
yuIprQJATfcmxUmruEYVwnFtbZBoS4jYvtfCyAyohkS9naiijaEEFTFQ1/D66eOk
KOG+0iU+t0YnksZdpU5u8B4bG34BuQJAXv6FhTQk+MhM40KupnUzTzcJXY1t4kAs
K36yBjZoMjWOMO83LiUX6iVz9XHMOXVBEraGySlm3IS7R+q0TXUF9QJAQ69wautf
8q1OQiLcg5WTFmSFBEXqAvVwX6FcDSxor9UnI0iHwyKBss3a2IXY9LoTPTjR5SHh
GDq2lXmP+kmbnQ==
-----END PRIVATE KEY-----
common/djangoapps/third_party_auth/tests/data/saml_key_alt.pub
0 → 100644
View file @
cd941ead
-----BEGIN CERTIFICATE-----
MIICWDCCAcGgAwIBAgIJAMlM2wrOvplkMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTUwNjEzMDEyMTAwWhcNMjUwNjEyMDEyMTAwWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQDKEfAj/h5b7D0cIlQgrlsWTnTY2GuEK3tyRFj5KpVMKXItVxkwah+wyvW9oZgV
zI2KAyjpxeaS+2OOd9yUidvgBuw+ACRkqLQN26ChdfBA4HjMwFowIQ1YU6axs/v9
RvltEeEksmOUBsgYS2d+sRdsOR8noqjfyIqt0ChpdghTkQIDAQABo1AwTjAdBgNV
HQ4EFgQUU0TNPc1yGas/W4HJl/Hgtrmdu6MwHwYDVR0jBBgwFoAUU0TNPc1yGas/
W4HJl/Hgtrmdu6MwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCE4BqJ
v2s99DS16NbZtR7tpqXDxiDaCg59VtgcHQwxN4qXcixZi5N4yRvzjYschAQN5tQ6
bofXdIK3tJY9Ynm0KPO+5l0RCv7CkhNgftTww0bWC91xaHJ/y66AqONuLpaP6s43
SZYG2D6ric57ZY4kQ6ZlUv854TPzmvapnGG7Hw==
-----END CERTIFICATE-----
common/djangoapps/third_party_auth/tests/data/testshib_metadata.xml
0 → 100644
View file @
cd941ead
<!-- Cached and simplified copy of https://www.testshib.org/metadata/testshib-providers.xml -->
<EntitiesDescriptor
Name=
"urn:mace:shibboleth:testshib:two"
xmlns=
"urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:ds=
"http://www.w3.org/2000/09/xmldsig#"
xmlns:mdalg=
"urn:oasis:names:tc:SAML:metadata:algsupport"
xmlns:mdui=
"urn:oasis:names:tc:SAML:metadata:ui"
xmlns:shibmd=
"urn:mace:shibboleth:metadata:1.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
>
<EntityDescriptor
entityID=
"https://idp.testshib.org/idp/shibboleth"
>
<Extensions>
<mdalg:DigestMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#sha512"
/>
<mdalg:DigestMethod
Algorithm=
"http://www.w3.org/2001/04/xmldsig-more#sha384"
/>
<mdalg:DigestMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#sha256"
/>
<mdalg:DigestMethod
Algorithm=
"http://www.w3.org/2000/09/xmldsig#sha1"
/>
<mdalg:SigningMethod
Algorithm=
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"
/>
<mdalg:SigningMethod
Algorithm=
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"
/>
<mdalg:SigningMethod
Algorithm=
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
/>
<mdalg:SigningMethod
Algorithm=
"http://www.w3.org/2000/09/xmldsig#rsa-sha1"
/>
</Extensions>
<IDPSSODescriptor
protocolSupportEnumeration=
"urn:oasis:names:tc:SAML:1.1:protocol urn:mace:shibboleth:1.0 urn:oasis:names:tc:SAML:2.0:protocol"
>
<Extensions>
<shibmd:Scope
regexp=
"false"
>
testshib.org
</shibmd:Scope>
<mdui:UIInfo>
<mdui:DisplayName
xml:lang=
"en"
>
TestShib Test IdP
</mdui:DisplayName>
<mdui:Description
xml:lang=
"en"
>
TestShib IdP. Use this as a source of attributes
for your test SP.
</mdui:Description>
<mdui:Logo
height=
"88"
width=
"253"
>
https://www.testshib.org/testshibtwo.jpg
</mdui:Logo>
</mdui:UIInfo>
</Extensions>
<KeyDescriptor>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIEDjCCAvagAwIBAgIBADANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzEV
MBMGA1UECBMMUGVubnN5bHZhbmlhMRMwEQYDVQQHEwpQaXR0c2J1cmdoMREwDwYD
VQQKEwhUZXN0U2hpYjEZMBcGA1UEAxMQaWRwLnRlc3RzaGliLm9yZzAeFw0wNjA4
MzAyMTEyMjVaFw0xNjA4MjcyMTEyMjVaMGcxCzAJBgNVBAYTAlVTMRUwEwYDVQQI
EwxQZW5uc3lsdmFuaWExEzARBgNVBAcTClBpdHRzYnVyZ2gxETAPBgNVBAoTCFRl
c3RTaGliMRkwFwYDVQQDExBpZHAudGVzdHNoaWIub3JnMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEArYkCGuTmJp9eAOSGHwRJo1SNatB5ZOKqDM9ysg7C
yVTDClcpu93gSP10nH4gkCZOlnESNgttg0r+MqL8tfJC6ybddEFB3YBo8PZajKSe
3OQ01Ow3yT4I+Wdg1tsTpSge9gEz7SrC07EkYmHuPtd71CHiUaCWDv+xVfUQX0aT
NPFmDixzUjoYzbGDrtAyCqA8f9CN2txIfJnpHE6q6CmKcoLADS4UrNPlhHSzd614
kR/JYiks0K4kbRqCQF0Dv0P5Di+rEfefC6glV8ysC8dB5/9nb0yh/ojRuJGmgMWH
gWk6h0ihjihqiu4jACovUZ7vVOCgSE5Ipn7OIwqd93zp2wIDAQABo4HEMIHBMB0G
A1UdDgQWBBSsBQ869nh83KqZr5jArr4/7b+QazCBkQYDVR0jBIGJMIGGgBSsBQ86
9nh83KqZr5jArr4/7b+Qa6FrpGkwZzELMAkGA1UEBhMCVVMxFTATBgNVBAgTDFBl
bm5zeWx2YW5pYTETMBEGA1UEBxMKUGl0dHNidXJnaDERMA8GA1UEChMIVGVzdFNo
aWIxGTAXBgNVBAMTEGlkcC50ZXN0c2hpYi5vcmeCAQAwDAYDVR0TBAUwAwEB/zAN
BgkqhkiG9w0BAQUFAAOCAQEAjR29PhrCbk8qLN5MFfSVk98t3CT9jHZoYxd8QMRL
I4j7iYQxXiGJTT1FXs1nd4Rha9un+LqTfeMMYqISdDDI6tv8iNpkOAvZZUosVkUo
93pv1T0RPz35hcHHYq2yee59HJOco2bFlcsH8JBXRSRrJ3Q7Eut+z9uo80JdGNJ4
/SJy5UorZ8KazGj16lfJhOBXldgrhppQBb0Nq6HKHguqmwRfJ+WkxemZXzhediAj
Geka8nz8JjwxpUjAiSWYKLtJhGEaTqCYxCCX2Dw+dOTqUzHOZ7WKv4JXPK5G/Uhr
8K/qhmFT2nIQi538n6rVYLeWj8Bbnl+ev0peYzxFyF5sQA==
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#aes256-cbc"
/>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#aes192-cbc"
/>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#aes128-cbc"
/>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
/>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"
/>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#rsa-1_5"
/>
</KeyDescriptor>
<ArtifactResolutionService
Binding=
"urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding"
Location=
"https://idp.testshib.org:8443/idp/profile/SAML1/SOAP/ArtifactResolution"
index=
"1"
/>
<ArtifactResolutionService
Binding=
"urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location=
"https://idp.testshib.org:8443/idp/profile/SAML2/SOAP/ArtifactResolution"
index=
"2"
/>
<NameIDFormat>
urn:mace:shibboleth:1.0:nameIdentifier
</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:transient
</NameIDFormat>
<SingleSignOnService
Binding=
"urn:mace:shibboleth:1.0:profiles:AuthnRequest"
Location=
"https://idp.testshib.org/idp/profile/Shibboleth/SSO"
/>
<SingleSignOnService
Binding=
"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location=
"https://idp.testshib.org/idp/profile/SAML2/POST/SSO"
/>
<SingleSignOnService
Binding=
"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location=
"https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO"
/>
<SingleSignOnService
Binding=
"urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location=
"https://idp.testshib.org/idp/profile/SAML2/SOAP/ECP"
/>
</IDPSSODescriptor>
<AttributeAuthorityDescriptor
protocolSupportEnumeration=
"urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol"
>
<KeyDescriptor>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIEDjCCAvagAwIBAgIBADANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzEV
MBMGA1UECBMMUGVubnN5bHZhbmlhMRMwEQYDVQQHEwpQaXR0c2J1cmdoMREwDwYD
VQQKEwhUZXN0U2hpYjEZMBcGA1UEAxMQaWRwLnRlc3RzaGliLm9yZzAeFw0wNjA4
MzAyMTEyMjVaFw0xNjA4MjcyMTEyMjVaMGcxCzAJBgNVBAYTAlVTMRUwEwYDVQQI
EwxQZW5uc3lsdmFuaWExEzARBgNVBAcTClBpdHRzYnVyZ2gxETAPBgNVBAoTCFRl
c3RTaGliMRkwFwYDVQQDExBpZHAudGVzdHNoaWIub3JnMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEArYkCGuTmJp9eAOSGHwRJo1SNatB5ZOKqDM9ysg7C
yVTDClcpu93gSP10nH4gkCZOlnESNgttg0r+MqL8tfJC6ybddEFB3YBo8PZajKSe
3OQ01Ow3yT4I+Wdg1tsTpSge9gEz7SrC07EkYmHuPtd71CHiUaCWDv+xVfUQX0aT
NPFmDixzUjoYzbGDrtAyCqA8f9CN2txIfJnpHE6q6CmKcoLADS4UrNPlhHSzd614
kR/JYiks0K4kbRqCQF0Dv0P5Di+rEfefC6glV8ysC8dB5/9nb0yh/ojRuJGmgMWH
gWk6h0ihjihqiu4jACovUZ7vVOCgSE5Ipn7OIwqd93zp2wIDAQABo4HEMIHBMB0G
A1UdDgQWBBSsBQ869nh83KqZr5jArr4/7b+QazCBkQYDVR0jBIGJMIGGgBSsBQ86
9nh83KqZr5jArr4/7b+Qa6FrpGkwZzELMAkGA1UEBhMCVVMxFTATBgNVBAgTDFBl
bm5zeWx2YW5pYTETMBEGA1UEBxMKUGl0dHNidXJnaDERMA8GA1UEChMIVGVzdFNo
aWIxGTAXBgNVBAMTEGlkcC50ZXN0c2hpYi5vcmeCAQAwDAYDVR0TBAUwAwEB/zAN
BgkqhkiG9w0BAQUFAAOCAQEAjR29PhrCbk8qLN5MFfSVk98t3CT9jHZoYxd8QMRL
I4j7iYQxXiGJTT1FXs1nd4Rha9un+LqTfeMMYqISdDDI6tv8iNpkOAvZZUosVkUo
93pv1T0RPz35hcHHYq2yee59HJOco2bFlcsH8JBXRSRrJ3Q7Eut+z9uo80JdGNJ4
/SJy5UorZ8KazGj16lfJhOBXldgrhppQBb0Nq6HKHguqmwRfJ+WkxemZXzhediAj
Geka8nz8JjwxpUjAiSWYKLtJhGEaTqCYxCCX2Dw+dOTqUzHOZ7WKv4JXPK5G/Uhr
8K/qhmFT2nIQi538n6rVYLeWj8Bbnl+ev0peYzxFyF5sQA==
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#aes256-cbc"
/>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#aes192-cbc"
/>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#aes128-cbc"
/>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
/>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"
/>
<EncryptionMethod
Algorithm=
"http://www.w3.org/2001/04/xmlenc#rsa-1_5"
/>
</KeyDescriptor>
<AttributeService
Binding=
"urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding"
Location=
"https://idp.testshib.org:8443/idp/profile/SAML1/SOAP/AttributeQuery"
/>
<AttributeService
Binding=
"urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location=
"https://idp.testshib.org:8443/idp/profile/SAML2/SOAP/AttributeQuery"
/>
<NameIDFormat>
urn:mace:shibboleth:1.0:nameIdentifier
</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:transient
</NameIDFormat>
</AttributeAuthorityDescriptor>
<Organization>
<OrganizationName
xml:lang=
"en"
>
TestShib Two Identity Provider
</OrganizationName>
<OrganizationDisplayName
xml:lang=
"en"
>
TestShib Two
</OrganizationDisplayName>
<OrganizationURL
xml:lang=
"en"
>
http://www.testshib.org/testshib-two/
</OrganizationURL>
</Organization>
<ContactPerson
contactType=
"technical"
>
<GivenName>
Nate
</GivenName>
<SurName>
Klingenstein
</SurName>
<EmailAddress>
ndk@internet2.edu
</EmailAddress>
</ContactPerson>
</EntityDescriptor>
</EntitiesDescriptor>
common/djangoapps/third_party_auth/tests/data/testshib_response.txt
0 → 100644
View file @
cd941ead
RelayState=testshib&SAMLResponse=PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOlJlc3BvbnNlIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBEZXN0aW5hdGlvbj0iaHR0cDovL2V4YW1wbGUubm9uZS9hdXRoL2NvbXBsZXRlL3RwYS1zYW1sLyIgSUQ9Il9hMDdmZDlhMDg0ODM3M2U1NTMyMGRjMzQyNDk0ZWY1ZCIgSW5SZXNwb25zZVRvPSJURVNUSUQiIElzc3VlSW5zdGFudD0iMjAxNS0wNi0xNVQwMDowNzoxNS4xODhaIiBWZXJzaW9uPSIyLjAiPjxzYW1sMjpJc3N1ZXIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5odHRwczovL2lkcC50ZXN0c2hpYi5vcmcvaWRwL3NoaWJib2xldGg8L3NhbWwyOklzc3Vlcj48c2FtbDJwOlN0YXR1cz48c2FtbDJwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbDJwOlN0YXR1cz48c2FtbDI6RW5jcnlwdGVkQXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj48eGVuYzpFbmNyeXB0ZWREYXRhIHhtbG5zOnhlbmM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyIgSWQ9Il9kYzc3ODI3YmY1ZGMzYjZmNGQzNjkzZWUzMTU2YmE1MiIgVHlwZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjRWxlbWVudCI%2BPHhlbmM6RW5jcnlwdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI2FlczEyOC1jYmMiIHhtbG5zOnhlbmM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyIvPjxkczpLZXlJbmZvIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48eGVuYzpFbmNyeXB0ZWRLZXkgSWQ9Il85NzhhN2I2NDE5YTMxOGQ4NmUzMzE0Y2Y5YjFjOTEzZiIgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjIj48eGVuYzpFbmNyeXB0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjcnNhLW9hZXAtbWdmMXAiIHhtbG5zOnhlbmM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyI%2BPGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIiB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyIvPjwveGVuYzpFbmNyeXB0aW9uTWV0aG9kPjxkczpLZXlJbmZvPjxkczpYNTA5RGF0YT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSUNzRENDQWhtZ0F3SUJBZ0lKQUpyRU5yOEVQZ3BjTUEwR0NTcUdTSWIzRFFFQkJRVUFNRVV4Q3pBSkJnTlZCQVlUQWtGVk1STXcKRVFZRFZRUUlFd3BUYjIxbExWTjBZWFJsTVNFd0h3WURWUVFLRXhoSmJuUmxjbTVsZENCWGFXUm5hWFJ6SUZCMGVTQk1kR1F3SGhjTgpNVFV3TmpFek1ERXdOVEUwV2hjTk1qVXdOakV5TURFd05URTBXakJGTVFzd0NRWURWUVFHRXdKQlZURVRNQkVHQTFVRUNCTUtVMjl0ClpTMVRkR0YwWlRFaE1COEdBMVVFQ2hNWVNXNTBaWEp1WlhRZ1YybGtaMmwwY3lCUWRIa2dUSFJrTUlHZk1BMEdDU3FHU0liM0RRRUIKQVFVQUE0R05BRENCaVFLQmdRRE0rTmY3SWVSZElJZ1lVa2U2c1Izbjdvc0hWWVh3SDZwYitPdnE4ajNoVW95OGt6VDlrSkYwUkIzaAozUTJWSjNaV2lRdFQ5NGZaWDJZWW9yVmRvR1ZLMk5XempMd2dwSFVzZ2ZlSnE1cENqUDBkMk9RdTlRdmpnNllPdFlQNlBOM2o3ZUs3CnBVY3hRdkljYVk5QVBERjU3dWEvelBzbTNVemJqaFJsSlpRVWV3SURBUUFCbzRHbk1JR2tNQjBHQTFVZERnUVdCQlRqT3lQdkF1ZWoKNXE0QzgwamxGclFtT2xzem16QjFCZ05WSFNNRWJqQnNnQlRqT3lQdkF1ZWo1cTRDODBqbEZyUW1PbHN6bTZGSnBFY3dSVEVMTUFrRwpBMVVFQmhNQ1FWVXhFekFSQmdOVkJBZ1RDbE52YldVdFUzUmhkR1V4SVRBZkJnTlZCQW9UR0VsdWRHVnlibVYwSUZkcFpHZHBkSE1nClVIUjVJRXgwWklJSkFKckVOcjhFUGdwY01Bd0dBMVVkRXdRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFRkJRQURnWUVBVjV3MFN4alUKVEZXZkwzWkc2c2dBMGdLZjhhVjh3M0FsaWhMdDl0S0NSZ3JLNHNCSzl4bWZ3cC9mbmJkeGtIVTU4aW96STg5NEhxbXJSekNpYVJMVwpteTNXODY0MEUvWENhNlAraThFVDdSa3NnTko1Y0Q5V3RJU0hrR2MyZG5XNzYrMm52OGQyNEpLZUl4MndvSkF0c3BNeXd6cjBTb3hECklKcjQyTjZLdmprPTwvZHM6WDUwOUNlcnRpZmljYXRlPjwvZHM6WDUwOURhdGE%2BPC9kczpLZXlJbmZvPjx4ZW5jOkNpcGhlckRhdGEgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjIj48eGVuYzpDaXBoZXJWYWx1ZT5sWEEvSGI2SlIxaW1UM2M1citrQU9taHVieVYvOUpqTUNzdkRJYlBEckxVR1g0aWFVbGl6c2d0dkdzRzdYOVpQWUxhc281U2ZlK1dTbVpKeW9tMGc0UU9HOWd6R3FIVGwybzFGMlJib0ZKS2FzaDZoQ011c2dSRmpJWElSUzdvTWJJTGxmcGhvcUN2c0pGdUpKY1FldU9SeWwyZmlrcUJSclhjNmwyMks2YzA9PC94ZW5jOkNpcGhlclZhbHVlPjwveGVuYzpDaXBoZXJEYXRhPjwveGVuYzpFbmNyeXB0ZWRLZXk%2BPC9kczpLZXlJbmZvPjx4ZW5jOkNpcGhlckRhdGEgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjIj48eGVuYzpDaXBoZXJWYWx1ZT5UQWdqL1d3ait2b0ppdHNhUE9IdmFSUHN3WE5oaHhEMmx2Q0t6MXJzQmtYbmJheVhlNmJucE1CMHg5aWpFMVdqOFV4YmtJQmhBMTEwRHhhTjZabkhReUs4amI3U29VU09jQkovUGxrT1NJc21zcS94dTVZTDJrdC9qdTdwRDR6K3BpcUlJbWRSVXdkcEhPdXFSVUxzUUJNU1NCRU5QT2sxQkRjcWZxb091N1g1VFIyOHE2eEwwUlFoV2NqMHBoTW9BMHdZS2ZFU0tacmRDQVRLcXVFcUJTRGJzRThNekh1cndiUkVkcjM5YnpBMGRNTm1zVFBFWmpsdkdqSEJmdVRaS3VPWXBoR3lFV1FVa29PbEtMQ1ROQ3VQYnhaWjFZNi80SGhlTGpQL3pnSU9ieWdLVkdadmNBSWpyTmZXNi9iQkJ0MVJjbndKV3pTZU5XR3hnd2hnZTJDank4RVFTUHJxbWZYK29VSVY3NExmT1NhV2JONXRwK3dtbzgveGlzWFErRysyZzA1ZnBiZEVmcEhacFZhMmFZY24xYWRtYy9uK3p1U0w2LzRTVWtXcTIvRHpRTTBWQVNQN2o0MXNIc0wwZEt2ZkhiQk5BcFB3NzdyTWdXRkwxcjVRajZiUmVjSElkQ3ozamZLcDZtdzBURzFQaUxCc2FXZ2wzYnZVR0lJNmxOWTg1TStFWHpoUnNCY29uVjgwUWFnKzBoTks3OWNteFkvOFByOGZkdXErMmgva3UxUzN2REo0cTlpR0FPaG1MUUFrWEQwWGF5Q1hXa0x1MEFyTmdOalNjaU55UXY2c3RmOUx1NGdUd1lKWUsyV0lWYUEvTzdMbUl2WmxkL0thL2VSaHdJQnV5YnpmemxWSVA0a2VVVmpldDVZMnZUVzA5bG02bWQzV1dmOTYrb21yNGVBQjllWjBmaFRxRkV4UzJkQVFqWi9JV21ZNnNXQXJCSkg4aEhya0IxdVBrQkZYTVFNbSs5T3ZKMWpnWXZtdVJUcHZzc1ZlL1MwWDhIVlVSdUpZVDVBY09YNHhuTWw0QkpXdnlLbzFFUms4bmRZOXJTTkJscGUrSXRUQXY5ZDgveVdJcGlYRVRLWGpKbTlVVWt6NnIyclhDUkN0VDhWa3J2M29jZmY0Z09nUjlTSWR0b21hU2w5RG9sTjVFL0ljTm1DUkhrbTR0U1J4bDNrNzNiMy8rNUxJNDhHc3l2c1VsNlNaZ1dCNmhSdDZaNDNuS2Iza3czOWd1cjk0VStrcURuUndub3lyeDVoc3N1NWRVVFNURkJPajhENGk0SjZwYi9sQ3FvWDVtR3lNODVJWnpxQk1Sa3IzeldPUzg3SVhBQm1uVDZ6aE1NdEpzN3EwRG9WZUhQbExUeUlVRHFMZWlaMjREQzN3Z1BjNmh0STVNeU1EZG5OM0hLczdnT3lhY3ppV280c3I1RGJCc3FqaFd1ZzJIanJEQ2hXZUszY1NuTlcwbkZCT1RJOFZMSFJXK2lhd3ZJWnUwZGdSenR1aEFjQ3lCelB0SHUrSzZlZmgyR0lNT0NhVVJCUzA3eGRETkw2MG9jOTBZZUlmOGV5WDFqV3ZDaDJZSnNxMDRtU3AySUFFQzFQSS9mc3lleGIrU2lMWTNzR1FyNEQ1bGx6ZHh6VEpKa2tYd2c4dHMxeklvSEx2TDdkQ29BRVNmNDJVVERFdWo4bGtadjYrM0JkNkwrM3Z6WFFPb2xwQ1kxeGRodVFOQjhsbG5KWHRNMmdtb1NEcmRwN1JzZWtTM2hkOWkxSkxkYWR1bW9oM0hmd0x6d0c4SkpCRkpmb3k0cGtzM05vMWFyT0lKRVBzZ3ZCMzZZUitScFFvc2hHM01PS0EwTUphcDNJbE5yQlVjdmw4WW5jSGkzbE9CUWpySFcrSURVVHhxZG9jdmw0NTBscmVUdkVoZXYraUFLU0J4alhNclNDQytaOWFIS1BJR2s4UzR2dWtudURIMUpsdTNLSFBwNFA5bnhSMnp3V3ZldktkYjNLdjZ3emhidmlxR0pPY05CeUZzRVJvNkEwSVVNVHQvOFJkQzJkZndyTjNBTHZ4dktrTmE0c3dEcElqYkRkb3RrZWgzT29FTVRETGE4M1R6Ym9ROFdWcDJLbEJiZDlWdXVNRm8xVUtrN2Q0dFh4VXRnWkZ3YlZQUWNzU21TV1dud1QvMFhxdDB0Yk8zQ0lnNkVZOHFXaUxoWU5naGw4eUhXTGIxbUUzVWNoSUhhVDBoWmNXTXVLMmtNbVpNMlJJeWVJY3o4M2NmY2lSWFJUb0g2TzFPenF5ZytBVUZiendibXQxR2d3V1hnMTdZQVJxSFViaDZwdktUMGJFRzdPUDRMZ0U4ajQvdTJoQjFraUFnUXpQSC84RHVCQlQwdkdOeElnKzhNWi9ObUFmUWRxODBlcVNQTDVpczlGbkZVei9GUzYzdEVCb0xYZnk5VzFRUjBsZ3VUY3o5b3l1dkdPdmVDZUt4RE9pZU9ZSktFTTlhVFVzVjRGc2c5M0NzMTQvRkhXQzJpclRKN1J3Ymg4eG1WUzBqUnVFQUdBejdETDNaSkFiRElLUUM5ZWZ2QUYxRHREVjZiVEI5cnNlczdsOWlDS3RnSnRWRE83Nmc5M2tWSGwvdXpYbVhwQ0NveS9XYStvVFErek5WL0lMbXAwVnorRnhJRHROUmcyL0V3eENyN042RW05ZmRibHgrMjYyWkdEVWVKcXcwNjB3L0RDTThiMDJmc2dyQTJ4NUVvcjF4a0tmcXMvaFMvVlo5azlVRHB0ZVFaMWdrSEU5TEN6TzY1azFRRTNENDNRK21ReFM2cGRJL1BpOUUxVkRoN3pMemdpOUVscXFLVHZNYjhPQUxmdSthTStPWlFaUjN4L21UVjQycTNmQlZya2lYRHpNd0pkclhjNW5UcmxLSDJTSUZsV2JaUzNXK0tHUVpoVzJ4dVRzdU9yS1FiVDY2OEVRbEpNTEhuckxLQTFrV0NvalJKV1hqZGFxSGVrWURDWjlFcDZaRnZ4NjJzWlRTdWMrVlNjK3UxSnZjT0w3NTZzNEFFWnNjR3ZnbXNxbUx5MldYOHpLbGw2MEdVUlE0YlBHMHd3YVUxRGF3dnJTejZqTCtyUjVBTTlGdTFlQi9WaUZSVVo4R0prR0VIOTdRWmNKcjV6RFpXNnZkOVBZRnlTd0Zqa21rOWxuZ1NFdFNPZFFITmZTZXRxbXZrcS9HbTB2enlTSWVyM3N5OCszR2IzNjJHaHd5MFNCekp6dEdHM0dQWTE3NUxRK3FWcGJCc1Y0MmgvOExPcnFaUGpVY0RrUk1NMU1LTHBtOEpSeVRGeWM5c0NxZ1lVMzNBbTByRzlkTHgxeVVKaTkwUncxc1pDa0lYUFIxYWFRUlkyNFEyekhVNjNBNHZDQVVaaVBOSHdVZlI4Qzk0cDdDeks5UTlreFpoaGZ6bjRBOFdadVZMSjkvWWI3d1RmNWQvNlNmNVFXWUM2anAvbUVWMDAxRnVBZnUzcUZNNmNuNXpXV2xkR2tjaU5RcUJ3SmZoWk9oUnk1VjBEaW5rMDBjSVlncDFmVnVnWHFkR1grV1ZCQkJ5M29va0toYW05S2RPc1N6aEI4NXZyN3h6R2JsREVXVGhFN0F5U3duRUVVNnBjcXpxR1E3Mk9KLytWS2I4ZVNPVWxzQW1LZnZ0czgzTHBYR2o0dkdRR1UwNVptK2grakdWeEpjMTJSQW5lbUhYK1FiNVhJdGk4ek1CazJkT2I4NUVPRUlvVnduWXpmSmhqQmtpOFhYMUtWaTVWbDE5dmV4OExxQ2pLdW9JeUsrSFpVQWtGMmpqY01WenUybXEvM3JPblJvTUhqVEszbFpGZm53S1E3WUxqd2dlVk45QnBmNm1Zem5Bb1RhVG1kQTUza29ocnMrVExuK0toUEpCRFc3Rml6L0ZDbVhzU2dJQ2tQcHAzVnJnQkY0N1ZDUEtPQi9yR2hPaklKd0V2bjgvZ0o1MU5qSmY3NkI4OUxHKzhLOXZpV2ZCeDRvMGxIczZLRmtCSk5RSTF4TCtVRGREWThURitlNXFtaVg3TTh6QmVsQjJlalZKaW9DRkhUcG9mRlZyT0kzTTlGcUk0Mk9KYVdrQytFTFJCaHR6dmJxaisrMWNOdlArcXVKQkRseTZNY2d3SE5BbzlhOHZIcjNjTmRHdmdjVGNFemx1aHpXOW9wb0dSTERPbHRUT0RqOUNQeUVXU2VablFxV2pHRGZiZkRkWm85bTRTWmUxTjQzNUNZYzJBY2VtR3JDdjAySUhyNmgvR1dZMTRFRlJ6T3crTFQ0Skg2TDBzM2w5V1JlZVlvR2NJc2RxYmhrN1Y0OXF5b1lBKzRlb3IvUi9VRzhZaFFYVzJJckQxaTVveDRGTEtXa0Q1UWtKRWU0VmpyNUVRTTBNTHJzNnE4YW5URklITGV3YXE4V0lnanJLS2FtRWloU2tGK2RnMHdScllTeUpuSzdySUsxWi9GQTlPakFUeGlIN0Y1TWcraGhlbXozYlFrU1FTaGN2T1lVSEdjU2sreHQrMXBuSG1lc1ZZTUlCb2d4S3JkUy9yLy9LM0lxdWR1Wko1bE5oVElXZ3dISkpiTVBHTG9mQUJybTlwZUFCVG5mVUFkcDIxK08wQmluVjdYZVg4RXFmVGhVejhrY2Z0MmgrSW5hajZwd1lDdGJ2MmE4dld5UXFKM0haNnBiZHV3bUJFVzhMa3Y2Qm44Yng5TllZMTdyMDliWDNCbmF6QWpGVW1EN3l6R3pLSnR2c1ZVOUw0RmMyU1B4ZUpQVjluQy91c0ZKc1ZlTEFMMTdqVERyV1k3NXhRdkpDVkJGNFlIS0JHaiszSk5WSWRudElOam5DTWhRak1CZU02V29RRkcyei9IQU9hU1lnaXlJSnlaNzd4MW1UYUtuTkNvSTlzZ3JNZkJzUE9mTXJUbkVGbTR5SThERjFGSTh4VnVONnpBcWp2dGkzNVczRGIzdG9Wa0pYVWk0OStKZzIxRWwxSkNqcjJoVmhBQjN5dE5kV2VnTXlTSFRnY0tRVVdRQmt3WUlEbUphdjY5am9udE9RdWpVbGFIM0lBRExHMUpPSWxuREduN0F2OUhkb0JzdnA3MDdLN20xZmJwOUxZK3NCdkwzcXdNbmpZbGhuZHBmYjdVbGxEajl2SCtuNDE5Z0FWMU9GUkRmVHVkVkRpdEFlQzI5ZWRjSmFGZXBYbmpKeHpvTzNqZHFrVTBiMWRmeEo2T1BCa01XSzJKcDZqTmllVlF6emwzRGJWMnRjcTNpekhQVmRySVZ2eEFqVWl3eENWK1VLTzZmMmlXaG9jQjhsWWE5U2xPOTRxd1Y2SkxSbDlIU3pFbDZtQUdRKzRCaW90aEhleDd2ODlGYnJ3eW00UjkwOGl4cU5odzNCc25wcHkyVzhlQXJtcENxMTRHdjlpM3R4em1mS1c3allIV2xWT0JQZFdoSnQ5NTZWbmliV2pWaVBBME9WOVNRWFZ6L2tpSit1WnZzT0FPY1h0YVRDaTZQL0dDMHJyRmhLc1paQW82ZE5paUF0N1BtVzduQjc5RDU5SzRBd3RNaW5iV016TjRQQzFGcHA5eklQTlEvU0laY1IwN0FjMnJ0ODdoQ0JPNUNIY0xhL2EwZDcxZDNZenEzNFlSWDZRYmdRY2taVytLN0FTbGpUcnFQczBHUXo3eFVRVjY1SnRBUTZvbjBxWGwwQ3drdUFCR0gvVVZ3TXpTalBuSnh5WmhQczN5NFhmdTVOUWhabkQvWWNtenR2Y0tkanBvMExSZzkxZnN3QjQybS8vL282VTd5K1hJNGlXMDMxRFQ0R3ViVWV4NW5mZTByWjdlRTRMaGJkaWJiWVRkTDFESHJuTGhYUVpDaEFRSno5SVV1OWYweEtMY3ovR0lubzRQRC9VK2hKOVkrb3FtelpGM3NhVXpKNTRJY1lGeEVROGo5L25nOTVpWHc0SWM5aXovZmY0Wm9hN2hJMTUzalBMNHFOcS91akphYXd2MXpxRlFhRVJYZUU1UyswZTMwaC9UKzByMmMxMTJkYndZdXljN2UwNi9RVnJpckdSRnQyZnRHUFN2VVRMdTJKVzRBUHVDN1NpNmpYWjQ1QlArenJTNzJteWdQQm9LTSt6N2RYTWMySmhQTnhQcmlGRVJlUmJnQlFFM1RSckpMSVpaR3NPczNJbFdBdGpLRTJaVFd0bjNJQmFQM0loY2sySFJ4MnRXRDJYRnYweTQ1bXhlQnkwMXY0cjAwQjJnMW9JVlYvZkgvajZUQnFLU2VENjBWRGZ3OXMxeXU1VUVhbzRicy9oZmFjWVpZZzg1Y2daS1QrTkZCeHBadG84M3E3bzRBeUNMQTl5dzQ2ZFRzdUlSYnBsMC81MVp0R0hDa29YMkdOa0JRc2pFWTVSNHVoZGRJNnBFSkxuaWNvVnpGS0dsTFErZDJMKy9odnBldHUxMGFTVHhEMmJqWlMrUVlHM0VLZ0VvbDZveThVTHl4bjRMb041bk1zV2d3N0p6NDJWT0V1ZHFENHY0ZVFUdXB0NkRpQzhvRzVzaVdWZER2amZpUHdwN1l5cEFZOE8reFBLOVgzWkU2bVR6aEV6TGxud0Jtc1RuQWpjMTRsYTVha1FBdHJRaXZIY1Vmb1pCcWtQKzFqTmdOZ0lYQlB3WlRBMHh5aEVuYlRMK3JPd3dzcUEycjdMbUlTaFpNa3V0cUQzdC9GbmNBTCtkaTJvQ2pBOVRNdnVwMnRqNm5FaXNwbXpYcmE1WWVnUlVjOE5UNjJxL1dXU25aKy9pb0hUMWFjeldJWG9sN1JhZ0VlQlRlMkFlVVEvam5wd2RwR3gzUldLeGIrajdtN0RuaVpoSmlzZUw5a2JleC9RQUFBV1VxajRBQldtdEptQ1QrUy9KVit6R2FGaU4ybXFzcUd0Mm9qN2w1UzRmMkozcXdxaEpNbXVDRGlteUpzQ0FzOVlNQVFmOXRFRVNSa3pKTy9wOHdEamlFbGRZRUdMNkl2RHJkWHFERzhSTGJkQnczTHJxeUJQOEYwU3lzWmlHYWdXY3BSZGY4NmJKdXgra2gxOXo4eldvSWM4OUVBK2JCVm9ON2M5TEFETEFPbzlYY0pqdllJcFRiWXlJTk1iOVpCRGZlb3d5ZkViZ2Q2bGxiK004MzB5SXFIWVEvaFl0dWpWaDhXazdseG1mMjJzL280eUp3aHNYQlV2OWVWQkFyTDVmbUxPM3NjRmdBejRsR2cvbEN2cThSS0JRaFFYd29CNTM2aDdkRWFnWGxqQk41WGhZcTVmNkZhK0xRRkFIRnlyM2VHT3RZNjJsU3NMUE9Sa2VGQXl6RTY3bk1BZ3lrb1hEUHRrUE9hd2x6bW4zdEVOT3FMMDVRWmEzTkFvZ1RtYVZLYmlUTk1RVVF5M2JQNElYdDE0RlNEa3pweU5pREptcE5yeDJ3cjlVNmJvT08xQTl5eHFMZ1ZHdVNXc1E5Y1ByTm4zV2VZVXJvTjhhZkk4b2w2bFNuODgxaEUrU2I2OU9lZ2UxY09RYUduTUJ4WlpiVThzVDJxd0JsVWFzc0dYWlBOMUU5b3M3UUh5bzJKcmxkU0xrWGpsWWpxV3I2SkJtYmxiRXpRWXg4clA0TDVDUG5RME96WjA0MDV6MklUZXBzSUpHMW90Wng4VmIyWGwvSDNqajNja2F0TUZLU1ZrNTdBQkVIRUp3a3pmbXB4Y3Z0SzBjK081MGpPZUpTOGpJRUhnZUJJSkJTNzRRb0F2VGcvbW5NeTVHVTRGYllHSHZHMDBzYXdBbkNVbW90cm13R2dzcGhkM2orNFNuYm9HZ2Mvd0NzN2FTM0NJcHBBbC8wNTFCbWZhYk8rV2JpRDl4c3dzaElxSjZua3RMSk9mWmM0NjZVZmVpTkVJeG04cU5yQncxTlBrc1lXOWtjK2FtM3diTk1PMVp0N3hIYXU1M01odDVFRExIUjZ6a0wwcGFjY0ZuSndCNXFsS1hSN01Lb3huSmo5VTQyS1FOTFRQditUL2NlNG5oS2dIc2dua00wbU1YelF6Tkx0MDBDdkdGWDRuNnE4Q1JCRnY2SHFSVVdwWGFGdWlrc3Mwa1M3RDc0TThTQ2VnTmRuWit4Z3BLQ0IzOWZWWDEvYmMwUjlDbWN4M050d0hFYXNkZllpUlRIcFI0bGJndG1RUUcrYWNTdVhJWVRaSWFTRzlLWlZVZ3oxeFI4TVhMQXAveDRHbGMzaGNCMURnZ0cybE82RnNBTUhBTDExU3NySk1RUmZsUmxJOU0zNFB0SHRTY2pqSGcwcHRMT3JCOUI4c0NqMEk5bG1aWHU4cW1pMEQzMmg2VC96MnRvOFJMcmExVldZblp5NW9nYmhiQ2E4Sk5JZmNGQmJDTytpUXZlN2xGQ0RXZGJncDZJallGcXR4amdGUmkzVURaMExtQjVqSk9lejA1VWRNT3c3SjFudkhvSDM3RGZFclE5VWZKeUlpRjdGNzR4c2ZMSFIxSXpGenB6YnIyM2QwU3c5OXlCNjlDa1ZtdERCaXo3aWFmaVpXYzBZU2svajkrWDR4NENwU1diOVRMRTY5djI1MStjS0xzZzRPT2ppUHVSYTRnL25oaFB6eGN5bGE4WjNYb2s1ZTdJRy9BbWtCNkEvL29pRFdEKzBzbXJGOUI4VlNnVENiRHRNdFNyUStGUVBzZHBMdG52UndOY0pGcHJEaVVHN25FUTdMQnhoZHhraTZ3dXRuTnY1b2dsUkdheHV4Tk9XYXZaNGUxOTVEaXlVQkN4cjM5MlRjUkxKNExIOE1rTUpnNml2dmlNYllqeTBwSVpLVGJGSjRzOXZ6WlFwVjZVd1FlWEM0TGRWd1E2dlltb05Mb2JCaUlsSE9hUUUxM1hpTEliVTU2aEJVRnJqSHhiNzNRUm1SQ1poeWZpVUNSdUg4YWZjOEpyMFFkMXlJYTJNczd4bU9FczlCWmFwejdTR01OeURXUXlIY0Q5VzgvQ0d1OFlhUldRaWlBQTU4MDRlQWF6MmJnYUNuR0wrNHdZeXpYOXNvWnVGWFZ2eklDbVk3bVF5c1pVMllqUVZoRjdHZWFGTDNKL2ZGTTdqOVdiaThjZG1MNzJENGdLVDVXUmpKTGNVY01HNHNXZTJoNkJncWVybDNJeDFmMzRteGZOSUpFVnlLTTVzVW54a0kvTTFORDU5M2g0UWJGYWVUTjZkc2NLenRrK084OW82Rnhma1dvUFZYRlZJTmF0WFhoSVJHU0cvKzhSQXNNYi81QUZMb0Y5U2x6YytXaWkxQkQ5RGhwZFQvd01ya0lDUWdzVklMbUt4bnhobXZhS3pvcGEyaG9GdXBiL3A2Z2hMQVZpY2RROHZJa3Y4U0hBeGZJc0sxaFZXcHNRMUl0SGw5N3lnSHNtQ0lkR1NJcVNiaGwzdW9CNXhWWWVGV0FObXpYQ3g0OE5oTlc2SnNHZ1c5RXp1NjdlY2Z3VUZlUEZpYXpvbWFPUTFRc3ZjYVhHVGIxWjA0UzdQay9OZmlCWWFJSkoxbGlIMnBaeDhMZGZwZTVuRENtbTlYTVZHbUY2SVdWVjM0QW1uK1B5TlNCcWxzZDZyQlNjWVRISm43ZElUZm9Zd3JvZjZvNVBUR2lwUHNlYXNHbDJoWFpCMWRYc1U0aTJKVDNLenVTeUl1RVU2Y2Z5M242T3duNmNjV0NyUFNLc3Vwb2Z0QithenZpZzd0bUFvRHlFTHN4eUE1dzQrZ0RmQm1BeStwNG02NnVNWjFUWEJiSTZhZ2RzVEpteUtHMm1NNFZrUmo0Z1cvcW0yMDNISno0YlVJN2dlcXNHQktNbGdPR1ZHRDRGZGlPaWxPbkNxeGo5NmFiY0Q5SnVmeVJUYUFmSC9QbGJaaU5mOTVORWtxaXZmNC9CN2lqaEdIZlUwcXFNblJlYVdackFuK2M3RlByc2h6UWIrMC9OUSt1dWRMbGJ6czZHd1IyUG5sNmlNdjRsUFZ3d1UyTWprYzdMUzY5ZzZpSnBZZytsbDM1N0toSWhPUTRpMkNzVXhXWHlVZy9VZCtaQmhSTDFhWWxWQ1NaK1VRZlJodVNCREdkLzNrYjR0azNvUVMzaVgrS09EVFB5RGwxaTUweXhZdjJQZjRPdG1QR1RVYkdUeUJQd1RPUGN4TUR5dDBjWjAzdVdtY0MwblVrMllnWnlLeFFXTTBSaHJVK2pRUVZwL1BWY1NRdGYwREtTSDZzUEh2M1RlbmJMV25sdzNKaUlveEhmRjRJTGZhY255M0xPTGFxcXN1QU95REJmMnQxdlF2UTdkMmtZMGhwdUF4Y091c0I4dXpmdmQyTWtramZwVHFNWGN4TndNbUxWYXRobGVpQUUwRVBFaTFDanZuWVgyQUE5a2pwLy9oRlZaaklvK0ZYRzlQRE5ObVdDTVRPSXQwcmZoRzFxNTFDbG1sQW41Mm1vQ016d0lNOGlLVXk0MDNPdElBQkgrSzhTbHQ4aFpEaHRmRDBoR0xVOXg0TVBaUmhxMmdRd0tCL3Fpd3BnVnNWbDhrNmVxUnZpMjFjeWFJRklIRVQ3L0ljT25zWU1rYnh2azBQdGtIL0VUSHhsQjVqMUJ6TmJhQ0hJZ291bWJwVDdadlEyWjRESFhXNXJQdU55YVN6MEF2bTZ3dHljMDVxVTJVbXRWMXFOL1NOb203SkFkbms5ajg1TFUydUh1bVdqZHNLbVdFNXFLdWprcW16N3pEOE8yVGhuVzc3SWZQRngveG8yWXlaZUU2OXRFVlJCZ0dHUFA3R1NyaTVMaUl2TzZwTkZMak96QnRJTERnMUxFQUo1VUlqNjd4U0VzUjRIRW9CVEM1NHZKSUFoLzMxak0vUE96VFdkZ01YcXhlSlhGenE3ZHRqTWcrLzNSY0hIVm9LRGd3NjlrMmNnYXpwRzIwdVZuMTZkUUJYN0Jpdk12TVc3OStUb0xPcm0ydXhrN0VtUkNTVFUzMlFBbVZ6Z09mZHRKUDF2TWk0SU93aDVSYW51YWh2ekhIWDNHR3pRTkx4a1RiUXFFUjZmaHV0cEVVcEFOWmVMbnA2UzVaMkIwZGtVZ1BSeGc2NUpXY05OS1BSc0NrWkkxK1NTU1haeVMrOWFrUzhtd3c0NXRzdHRaTlZSR003RVh4YjUrU0FkMkwybFpLbnlNRll1M2lSZWcrSnZtMUIxVFZRL3lKejY0MFlLUzNMYitIQ3hoSmhTTGlhYk5Kb1Y3V1VuZTBGekt6bXVDdGRtR3BIWkM5cXh1SGdDcHRuVTJVb2oxNWF6Y2dBWHAyZjF6OHVUVCs2dXpxTm5lOVdzUHlwdE9NdlFhNDJzdmtZNlU5TkcvSi9VUTdRRmUrL2VUNnp6ZGQ2a2lSNzA1ZXBVeTA5MkpIekQrOWJDMmxtYWk4RGo0U3o0MVhUWmEvTHYzdXQwOTk1L3ptb3Z1R2M2VTdXMmFTSG9LcUs4dXRKeEliVmtKb3hYbFFuckVIMlM1YXc3WG1lREtwbzVwYXlLTU56eXhJeGxoTmxsRUVqbVdnODFBajRLbmFsOUR3N09sVVhrWE02eWFqWjNqaUN2Uk9RQVRVbGVid2gzWFppTnJtc1J4b3lWMVg5OWEzaWN1THlpRUJBVkRYQ0kwcTJqYWdCc1h4L3Nrci9oa2lhYkZqSCs3MUVvVWVjRm11RmhvcGxMak1td0tsSWFwTk02NENUaGRpdGdoUklUTFVDb2ZGYUQxOHd6bldlaEZrSFlVUW1JWXRFdzJYb005V2FMN1Fod0ZoeHVhL3FScFRLUTMxOXBNWk1qN2UrMlhaYk93Y0VLYnE2MFhRSllHaDNGMTUxSENYVW9lRHY1Nm42Yk52ckU2YVdkdkFEa3F1RWw3RTNYSmdueTlXOVJCSnMvMEo4QkxjNnlPOWk3V3ZIVVFwN3JRZkhGWklMbEIwSHgrcXhVWG1LWG5KZTczcGhSY0tTNjVIb3d4WjYreHppclFHTXhtci85R05VUEd5TVROR1ArRGlKbW1La3FMT09jd0NFSFNuZnl1NmExN24rM1l3U1g5NitNbkVmdTIwckhPb1pqVVZuT1ptRkNFRFFYZ0s3NWR5b3BzclZlM0pLZHBmYVFOVDllT0dvNk1qZDNiS3UrTVZDR3g4TitrNWE3ajJ3cGxtTVhuTVB6Q1JmcEkzd1pQeTRQc1VhVTEyS2xvaUZFT3poZTJGMk9EYUwxU3lGY2RueWhyRTgvcnZSc3pVV2R3UjZEai9LaVh0OC9vSm5aY2R5bDdjKzZSNi9HenRlSHZqY0oya1BnUk9nTURpUDFlTmVkNzJ0UmtzQjllNXZsczNZRnNrNWlBa1hiNEw5MjRibGx6c1VXQXBCeFRkMXFLS1hYZzhQVFhqanNCYTQ5dnNBNUVvaFZmbUUwMnR2NHNjQkZMaU5VcXdZY0dxZ25KbEFQQ3FaOGdnT1E3VnhWZFZuMVlRZkJPMm1vVGdaU0wrQ0NUeE9qRXlwSkR2RnM5Z01JZ0l3V0hBSFhNOGdQanZucXBsN1d3bXh0a2l3aUdEU1V6bjFscHViTEV2czdxYWxNZ2hieXVuVzRlcU5WdlBmUmlNMlllSGhheUF6dFF5MXFXaTJ6cGg1VWExWjFKQVREaW9FanBFMHNTN0FlZEdPNmovVzFmZDV6R1pibHlIN1M5VDY2ZEU0OHRjaFo0R0YxVmsvZlFYSGRRT0lkb1pabUE1T05yS0FuQWVWOEh2QUFxa29Nd3J4ZGFXN1lYMWNHSitXTUdOR08xU0VLVWczMldmUG1pY1hLTG9JWDBEUW1OYmd3TjNFenVtMm1uNjNNUTN2amVqckVaRnpsUmhKbStDYVMwTGJxVDVIRkRWWVBOb2xOZjl3aEFxMzAvSFZaaWt6UHhWM3lJQmlrdmE1QTFuSmZWcFhZRXFNa2IvaDR0V05iNXN3U2pucUVEOHViOU5Pc3RIcmVZaE9RYnBLelVHU2RjTkF1K1IrVDJzUlJBQzQ2TlZadmZOcVZ5UU90YVh0czhRdzRXdEJCaXpKS0xtLzBYd1oxMXdNZmtqci9nckg0cmllRGEwZTd1S2tQV3pZOXJqc2lpQ2MwL1ozUjBIM1hLNTVTOTB1bjVIVitRbkt1eHlyYk03UGhFUXVnRVE2TlQ3cVhvV1U1b3BSL1p2NmloSEhYMzB1ZStFYW53SmdlUUN4WGpsTlZEUGY2WEpFNXQ4eWxLMFd5andOQWZpdzdiZ2F3MVk5YVU1MU5ZZUc3QXo5RldXSWhHVGpmSXZMMThVY0pQWndib1hqNHZHMkdyc01YRDNMUjFKV2xJZGIwL29uTndvOENZYncrOFlhc3RtOUw0dzlDQUQzTHZRVzBBQ3dkS3hMQ1NycW5UWmw0YStTbHUvNXFTN2RIdzlBSGpMVnFFRGtLWU9qNnFEVHdpTWFzNkR4bEt0RmxXa2wyaWZFaFl0UGVERmg5d2ZOdHFhUjdBRFZtcWQyL3p0aFpzcmlaTVpvdmluMlJSWGptSTZsRGRkMFhScFhNV2hWQkUrN1JKZ0VRZTNzV28yS3d2TUtZMS9PcWVXYkxndUZZSVZTZ0w4NkFTU3g8L3hlbmM6Q2lwaGVyVmFsdWU%2BPC94ZW5jOkNpcGhlckRhdGE%2BPC94ZW5jOkVuY3J5cHRlZERhdGE%2BPC9zYW1sMjpFbmNyeXB0ZWRBc3NlcnRpb24%2BPC9zYW1sMnA6UmVzcG9uc2U%2B
\ No newline at end of file
common/djangoapps/third_party_auth/tests/specs/test_testshib.py
0 → 100644
View file @
cd941ead
"""
Third_party_auth integration tests using a mock version of the TestShib provider
"""
from
django.core.management
import
call_command
from
django.core.urlresolvers
import
reverse
import
httpretty
from
mock
import
patch
import
StringIO
from
student.tests.factories
import
UserFactory
from
third_party_auth.tests
import
testutil
import
unittest
TESTSHIB_ENTITY_ID
=
'https://idp.testshib.org/idp/shibboleth'
TESTSHIB_METADATA_URL
=
'https://mock.testshib.org/metadata/testshib-providers.xml'
TESTSHIB_SSO_URL
=
'https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO'
TPA_TESTSHIB_LOGIN_URL
=
'/auth/login/tpa-saml/?auth_entry=login&next=
%2
Fdashboard&idp=testshib'
TPA_TESTSHIB_REGISTER_URL
=
'/auth/login/tpa-saml/?auth_entry=register&next=
%2
Fdashboard&idp=testshib'
TPA_TESTSHIB_COMPLETE_URL
=
'/auth/complete/tpa-saml/'
@unittest.skipUnless
(
testutil
.
AUTH_FEATURE_ENABLED
,
'third_party_auth not enabled'
)
class
TestShibIntegrationTest
(
testutil
.
SAMLTestCase
):
"""
TestShib provider Integration Test, to test SAML functionality
"""
def
setUp
(
self
):
super
(
TestShibIntegrationTest
,
self
)
.
setUp
()
self
.
login_page_url
=
reverse
(
'signin_user'
)
self
.
register_page_url
=
reverse
(
'register_user'
)
self
.
enable_saml
(
private_key
=
self
.
_get_private_key
(),
public_key
=
self
.
_get_public_key
(),
entity_id
=
"https://saml.example.none"
,
)
# Mock out HTTP requests that may be made to TestShib:
httpretty
.
enable
()
def
metadata_callback
(
_request
,
_uri
,
headers
):
""" Return a cached copy of TestShib's metadata by reading it from disk """
return
(
200
,
headers
,
self
.
_read_data_file
(
'testshib_metadata.xml'
))
httpretty
.
register_uri
(
httpretty
.
GET
,
TESTSHIB_METADATA_URL
,
content_type
=
'text/xml'
,
body
=
metadata_callback
)
self
.
addCleanup
(
httpretty
.
disable
)
self
.
addCleanup
(
httpretty
.
reset
)
# Configure the SAML library to use the same request ID for every request.
# Doing this and freezing the time allows us to play back recorded request/response pairs
uid_patch
=
patch
(
'onelogin.saml2.utils.OneLogin_Saml2_Utils.generate_unique_id'
,
return_value
=
'TESTID'
)
uid_patch
.
start
()
self
.
addCleanup
(
uid_patch
.
stop
)
def
test_login_before_metadata_fetched
(
self
):
self
.
_configure_testshib_provider
(
fetch_metadata
=
False
)
# The user goes to the login page, and sees a button to login with TestShib:
self
.
_check_login_page
()
# The user clicks on the TestShib button:
try_login_response
=
self
.
client
.
get
(
TPA_TESTSHIB_LOGIN_URL
)
# The user should be redirected to back to the login page:
self
.
assertEqual
(
try_login_response
.
status_code
,
302
)
self
.
assertEqual
(
try_login_response
[
'Location'
],
self
.
url_prefix
+
self
.
login_page_url
)
# When loading the login page, the user will see an error message:
response
=
self
.
client
.
get
(
self
.
login_page_url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertIn
(
'Authentication with TestShib is currently unavailable.'
,
response
.
content
)
# Note: the following patch is only needed until https://github.com/edx/edx-platform/pull/8262 is merged
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
"AUTOMATIC_AUTH_FOR_TESTING"
:
True
})
def
test_register
(
self
):
self
.
_configure_testshib_provider
()
self
.
_freeze_time
(
timestamp
=
1434326820
)
# This is the time when the saved request/response was recorded.
# The user goes to the register page, and sees a button to register with TestShib:
self
.
_check_register_page
()
# The user clicks on the TestShib button:
try_login_response
=
self
.
client
.
get
(
TPA_TESTSHIB_REGISTER_URL
)
# The user should be redirected to TestShib:
self
.
assertEqual
(
try_login_response
.
status_code
,
302
)
self
.
assertTrue
(
try_login_response
[
'Location'
]
.
startswith
(
TESTSHIB_SSO_URL
))
# Now the user will authenticate with the SAML provider
testshib_response
=
self
.
_fake_testshib_login_and_return
()
# We should be redirected to the register screen since this account is not linked to an edX account:
self
.
assertEqual
(
testshib_response
.
status_code
,
302
)
self
.
assertEqual
(
testshib_response
[
'Location'
],
self
.
url_prefix
+
self
.
register_page_url
)
register_response
=
self
.
client
.
get
(
self
.
register_page_url
)
# We'd now like to see if the "You've successfully signed into TestShib" message is
# shown, but it's managed by a JavaScript runtime template, and we can't run JS in this
# type of test, so we just check for the variable that triggers that message.
self
.
assertIn
(
'"currentProvider": "TestShib"'
,
register_response
.
content
)
self
.
assertIn
(
'"errorMessage": null'
,
register_response
.
content
)
# Now do a crude check that the data (e.g. email) from the provider is displayed in the form:
self
.
assertIn
(
'"defaultValue": "myself@testshib.org"'
,
register_response
.
content
)
self
.
assertIn
(
'"defaultValue": "Me Myself And I"'
,
register_response
.
content
)
# Now complete the form:
ajax_register_response
=
self
.
client
.
post
(
reverse
(
'user_api_registration'
),
{
'email'
:
'myself@testshib.org'
,
'name'
:
'Myself'
,
'username'
:
'myself'
,
'honor_code'
:
True
,
}
)
self
.
assertEqual
(
ajax_register_response
.
status_code
,
200
)
# Then the AJAX will finish the third party auth:
continue_response
=
self
.
client
.
get
(
TPA_TESTSHIB_COMPLETE_URL
)
# And we should be redirected to the dashboard:
self
.
assertEqual
(
continue_response
.
status_code
,
302
)
self
.
assertEqual
(
continue_response
[
'Location'
],
self
.
url_prefix
+
reverse
(
'dashboard'
))
# Now check that we can login again:
self
.
client
.
logout
()
self
.
_test_return_login
()
def
test_login
(
self
):
self
.
_configure_testshib_provider
()
self
.
_freeze_time
(
timestamp
=
1434326820
)
# This is the time when the saved request/response was recorded.
user
=
UserFactory
.
create
()
# The user goes to the login page, and sees a button to login with TestShib:
self
.
_check_login_page
()
# The user clicks on the TestShib button:
try_login_response
=
self
.
client
.
get
(
TPA_TESTSHIB_LOGIN_URL
)
# The user should be redirected to TestShib:
self
.
assertEqual
(
try_login_response
.
status_code
,
302
)
self
.
assertTrue
(
try_login_response
[
'Location'
]
.
startswith
(
TESTSHIB_SSO_URL
))
# Now the user will authenticate with the SAML provider
testshib_response
=
self
.
_fake_testshib_login_and_return
()
# We should be redirected to the login screen since this account is not linked to an edX account:
self
.
assertEqual
(
testshib_response
.
status_code
,
302
)
self
.
assertEqual
(
testshib_response
[
'Location'
],
self
.
url_prefix
+
self
.
login_page_url
)
login_response
=
self
.
client
.
get
(
self
.
login_page_url
)
# We'd now like to see if the "You've successfully signed into TestShib" message is
# shown, but it's managed by a JavaScript runtime template, and we can't run JS in this
# type of test, so we just check for the variable that triggers that message.
self
.
assertIn
(
'"currentProvider": "TestShib"'
,
login_response
.
content
)
self
.
assertIn
(
'"errorMessage": null'
,
login_response
.
content
)
# Now the user enters their username and password.
# The AJAX on the page will log them in:
ajax_login_response
=
self
.
client
.
post
(
reverse
(
'user_api_login_session'
),
{
'email'
:
user
.
email
,
'password'
:
'test'
}
)
self
.
assertEqual
(
ajax_login_response
.
status_code
,
200
)
# Then the AJAX will finish the third party auth:
continue_response
=
self
.
client
.
get
(
TPA_TESTSHIB_COMPLETE_URL
)
# And we should be redirected to the dashboard:
self
.
assertEqual
(
continue_response
.
status_code
,
302
)
self
.
assertEqual
(
continue_response
[
'Location'
],
self
.
url_prefix
+
reverse
(
'dashboard'
))
# Now check that we can login again:
self
.
client
.
logout
()
self
.
_test_return_login
()
def
_test_return_login
(
self
):
""" Test logging in to an account that is already linked. """
# Make sure we're not logged in:
dashboard_response
=
self
.
client
.
get
(
reverse
(
'dashboard'
))
self
.
assertEqual
(
dashboard_response
.
status_code
,
302
)
# The user goes to the login page, and sees a button to login with TestShib:
self
.
_check_login_page
()
# The user clicks on the TestShib button:
try_login_response
=
self
.
client
.
get
(
TPA_TESTSHIB_LOGIN_URL
)
# The user should be redirected to TestShib:
self
.
assertEqual
(
try_login_response
.
status_code
,
302
)
self
.
assertTrue
(
try_login_response
[
'Location'
]
.
startswith
(
TESTSHIB_SSO_URL
))
# Now the user will authenticate with the SAML provider
login_response
=
self
.
_fake_testshib_login_and_return
()
# There will be one weird redirect required to set the login cookie:
self
.
assertEqual
(
login_response
.
status_code
,
302
)
self
.
assertEqual
(
login_response
[
'Location'
],
self
.
url_prefix
+
TPA_TESTSHIB_COMPLETE_URL
)
# And then we should be redirected to the dashboard:
login_response
=
self
.
client
.
get
(
TPA_TESTSHIB_COMPLETE_URL
)
self
.
assertEqual
(
login_response
.
status_code
,
302
)
self
.
assertEqual
(
login_response
[
'Location'
],
self
.
url_prefix
+
reverse
(
'dashboard'
))
# Now we are logged in:
dashboard_response
=
self
.
client
.
get
(
reverse
(
'dashboard'
))
self
.
assertEqual
(
dashboard_response
.
status_code
,
200
)
def
_freeze_time
(
self
,
timestamp
):
""" Mock the current time for SAML, so we can replay canned requests/responses """
now_patch
=
patch
(
'onelogin.saml2.utils.OneLogin_Saml2_Utils.now'
,
return_value
=
timestamp
)
now_patch
.
start
()
self
.
addCleanup
(
now_patch
.
stop
)
def
_check_login_page
(
self
):
""" Load the login form and check that it contains a TestShib button """
response
=
self
.
client
.
get
(
self
.
login_page_url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertIn
(
"TestShib"
,
response
.
content
)
self
.
assertIn
(
TPA_TESTSHIB_LOGIN_URL
.
replace
(
'&'
,
'&'
),
response
.
content
)
return
response
def
_check_register_page
(
self
):
""" Load the login form and check that it contains a TestShib button """
response
=
self
.
client
.
get
(
self
.
register_page_url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertIn
(
"TestShib"
,
response
.
content
)
self
.
assertIn
(
TPA_TESTSHIB_REGISTER_URL
.
replace
(
'&'
,
'&'
),
response
.
content
)
return
response
def
_configure_testshib_provider
(
self
,
**
kwargs
):
""" Enable and configure the TestShib SAML IdP as a third_party_auth provider """
fetch_metadata
=
kwargs
.
pop
(
'fetch_metadata'
,
True
)
kwargs
.
setdefault
(
'name'
,
'TestShib'
)
kwargs
.
setdefault
(
'enabled'
,
True
)
kwargs
.
setdefault
(
'idp_slug'
,
'testshib'
)
kwargs
.
setdefault
(
'entity_id'
,
TESTSHIB_ENTITY_ID
)
kwargs
.
setdefault
(
'metadata_source'
,
TESTSHIB_METADATA_URL
)
kwargs
.
setdefault
(
'icon_class'
,
'fa-university'
)
kwargs
.
setdefault
(
'attr_email'
,
'urn:oid:1.3.6.1.4.1.5923.1.1.1.6'
)
# eduPersonPrincipalName
self
.
configure_saml_provider
(
**
kwargs
)
if
fetch_metadata
:
stdout
=
StringIO
.
StringIO
()
stderr
=
StringIO
.
StringIO
()
self
.
assertTrue
(
httpretty
.
is_enabled
())
call_command
(
'saml'
,
'pull'
,
stdout
=
stdout
,
stderr
=
stderr
)
stdout
=
stdout
.
getvalue
()
.
decode
(
'utf-8'
)
stderr
=
stderr
.
getvalue
()
.
decode
(
'utf-8'
)
self
.
assertEqual
(
stderr
,
''
)
self
.
assertIn
(
u'Fetching {}'
.
format
(
TESTSHIB_METADATA_URL
),
stdout
)
self
.
assertIn
(
u'Created new record for SAMLProviderData'
,
stdout
)
def
_fake_testshib_login_and_return
(
self
):
""" Mocked: the user logs in to TestShib and then gets redirected back """
# The SAML provider (TestShib) will authenticate the user, then get the browser to POST a response:
return
self
.
client
.
post
(
TPA_TESTSHIB_COMPLETE_URL
,
content_type
=
'application/x-www-form-urlencoded'
,
data
=
self
.
_read_data_file
(
'testshib_response.txt'
),
)
common/djangoapps/third_party_auth/tests/test_views.py
0 → 100644
View file @
cd941ead
"""
Test the views served by third_party_auth.
"""
# pylint: disable=no-member
import
ddt
from
lxml
import
etree
import
unittest
from
.testutil
import
AUTH_FEATURE_ENABLED
,
SAMLTestCase
# Define some XML namespaces:
SAML_XML_NS
=
'urn:oasis:names:tc:SAML:2.0:metadata'
XMLDSIG_XML_NS
=
'http://www.w3.org/2000/09/xmldsig#'
@unittest.skipUnless
(
AUTH_FEATURE_ENABLED
,
'third_party_auth not enabled'
)
@ddt.ddt
class
SAMLMetadataTest
(
SAMLTestCase
):
"""
Test the SAML metadata view
"""
METADATA_URL
=
'/auth/saml/metadata.xml'
def
test_saml_disabled
(
self
):
""" When SAML is not enabled, the metadata view should return 404 """
self
.
enable_saml
(
enabled
=
False
)
response
=
self
.
client
.
get
(
self
.
METADATA_URL
)
self
.
assertEqual
(
response
.
status_code
,
404
)
@ddt.data
(
'saml_key'
,
'saml_key_alt'
)
# Test two slightly different key pair export formats
def
test_metadata
(
self
,
key_name
):
self
.
enable_saml
(
private_key
=
self
.
_get_private_key
(
key_name
),
public_key
=
self
.
_get_public_key
(
key_name
),
entity_id
=
"https://saml.example.none"
,
)
doc
=
self
.
_fetch_metadata
()
# Check the ACS URL:
acs_node
=
doc
.
find
(
".//{}"
.
format
(
etree
.
QName
(
SAML_XML_NS
,
'AssertionConsumerService'
)))
self
.
assertIsNotNone
(
acs_node
)
self
.
assertEqual
(
acs_node
.
attrib
[
'Location'
],
'http://example.none/auth/complete/tpa-saml/'
)
def
test_signed_metadata
(
self
):
self
.
enable_saml
(
private_key
=
self
.
_get_private_key
(),
public_key
=
self
.
_get_public_key
(),
entity_id
=
"https://saml.example.none"
,
other_config_str
=
'{"SECURITY_CONFIG": {"signMetadata": true} }'
,
)
doc
=
self
.
_fetch_metadata
()
sig_node
=
doc
.
find
(
".//{}"
.
format
(
etree
.
QName
(
XMLDSIG_XML_NS
,
'SignatureValue'
)))
self
.
assertIsNotNone
(
sig_node
)
def
_fetch_metadata
(
self
):
""" Fetch and parse the metadata XML at self.METADATA_URL """
response
=
self
.
client
.
get
(
self
.
METADATA_URL
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
[
'Content-Type'
],
'text/xml'
)
# The result should be valid XML:
try
:
metadata_doc
=
etree
.
fromstring
(
response
.
content
)
except
etree
.
LxmlError
:
self
.
fail
(
'SAML metadata must be valid XML'
)
self
.
assertEqual
(
metadata_doc
.
tag
,
etree
.
QName
(
SAML_XML_NS
,
'EntityDescriptor'
))
return
metadata_doc
common/djangoapps/third_party_auth/tests/testutil.py
View file @
cd941ead
...
@@ -8,6 +8,7 @@ from contextlib import contextmanager
...
@@ -8,6 +8,7 @@ from contextlib import contextmanager
from
django.conf
import
settings
from
django.conf
import
settings
import
django.test
import
django.test
import
mock
import
mock
import
os.path
from
third_party_auth.models
import
OAuth2ProviderConfig
,
SAMLProviderConfig
,
SAMLConfiguration
,
cache
as
config_cache
from
third_party_auth.models
import
OAuth2ProviderConfig
,
SAMLProviderConfig
,
SAMLConfiguration
,
cache
as
config_cache
...
@@ -87,6 +88,33 @@ class TestCase(ThirdPartyAuthTestMixin, django.test.TestCase):
...
@@ -87,6 +88,33 @@ class TestCase(ThirdPartyAuthTestMixin, django.test.TestCase):
pass
pass
class
SAMLTestCase
(
TestCase
):
"""
Base class for SAML-related third_party_auth tests
"""
def
setUp
(
self
):
super
(
SAMLTestCase
,
self
)
.
setUp
()
self
.
client
.
defaults
[
'SERVER_NAME'
]
=
'example.none'
# The SAML lib we use doesn't like testserver' as a domain
self
.
url_prefix
=
'http://example.none'
@classmethod
def
_get_public_key
(
cls
,
key_name
=
'saml_key'
):
""" Get a public key for use in the test. """
return
cls
.
_read_data_file
(
'{}.pub'
.
format
(
key_name
))
@classmethod
def
_get_private_key
(
cls
,
key_name
=
'saml_key'
):
""" Get a private key for use in the test. """
return
cls
.
_read_data_file
(
'{}.key'
.
format
(
key_name
))
@staticmethod
def
_read_data_file
(
filename
):
""" Read the contents of a file in the data folder """
with
open
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'data'
,
filename
))
as
f
:
return
f
.
read
()
@contextmanager
@contextmanager
def
simulate_running_pipeline
(
pipeline_target
,
backend
,
email
=
None
,
fullname
=
None
,
username
=
None
):
def
simulate_running_pipeline
(
pipeline_target
,
backend
,
email
=
None
,
fullname
=
None
,
username
=
None
):
"""Simulate that a pipeline is currently running.
"""Simulate that a pipeline is currently running.
...
...
lms/djangoapps/student_account/views.py
View file @
cd941ead
...
@@ -198,7 +198,7 @@ def _third_party_auth_context(request, redirect_to):
...
@@ -198,7 +198,7 @@ def _third_party_auth_context(request, redirect_to):
for
msg
in
messages
.
get_messages
(
request
):
for
msg
in
messages
.
get_messages
(
request
):
if
msg
.
extra_tags
.
split
()[
0
]
==
"social-auth"
:
if
msg
.
extra_tags
.
split
()[
0
]
==
"social-auth"
:
# msg may or may not be translated. Try translating [again] in case we are able to:
# msg may or may not be translated. Try translating [again] in case we are able to:
context
[
'errorMessage'
]
=
_
(
msg
)
# pylint: disable=translation-of-non-string
context
[
'errorMessage'
]
=
_
(
unicode
(
msg
)
)
# pylint: disable=translation-of-non-string
break
break
return
context
return
context
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment