diff --git a/.gitignore b/.gitignore
index 0756aee..fab525f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,5 @@ nginx.conf
# Docker Compose
docker-compose.yml
.env.local
+
+saml2
\ No newline at end of file
diff --git a/README.md b/README.md
index f3c26d5..ed04459 100644
--- a/README.md
+++ b/README.md
@@ -134,7 +134,7 @@ Turn on background environment (if you have the application already running on t
docker-compose up -d
```
- Access in the browser:
+Access in the browser:
- Frontend:
- Django Admin:
- Django REST:
@@ -233,6 +233,64 @@ run single test method
docker-compose exec backend pytest core/test/test_product_file.py::ProductFileListCreateAPIViewTestCase::test_list_product_file
```
+## Enable authentication via LIneA Satosa (Github)
+
+### Keys and certificates
+
+Edit the `.env` to include the path to the certificates for signing and encrypting SAML assertions:
+(It is possible to use the same certificate for both signing and encryption.)
+
+```bash
+# Keys and certificates
+SIG_KEY_PEM=
+SIG_CERT_PEM=
+ENCRYP_KEY_PEM=
+ENCRYP_CERT_PEM=
+```
+
+If you do not have valid certificates (not recommended in production), generate a self-signed certificate using the command below:
+
+Create the `certificates` directory with the following command:
+
+```bash
+mkdir -p saml2/certificates
+
+openssl genrsa -out pz.key 2048
+openssl req -new -key pz.key -out pz.csr
+openssl x509 -req -days 365 -in pz.csr -signkey pz.key -out pz.crt
+
+cp pz.key pzkey.pem
+cp pz.crt pzcert.pem
+```
+
+Next we must uncomment the volume that represents the saml2 directory in docker-compose.yml:
+
+```yml
+- ./archive/log/backend:/archive/log
+- ./archive/data:/archive/data
+- ./saml2:/saml2 # uncomment if authentication with github is required
+```
+
+### IDP Metadata (Github)
+
+Edit the `.env` and tell where the metadata can be found:
+(Contact the infrastructure team to find out more details about the metadata.)
+
+```bash
+# IDP metadata
+IDP_METADATA=
+```
+
+And finally, just uncomment the `AUTH_SHIB_URL` variable in the `.env`:
+
+```bash
+# Saml2 / Satosa Auth
+# URL to login using satosa
+AUTH_SHIB_URL=${URI}/saml2/login/
+```
+
+With everything configured and the services started, we must access the URL `${URI}/saml2/metadata/` and send the content (xml) to the infrastructure team to create a trust relationship between the application and satosa.
+
## Setup Production Enviroment
In the production environment **NO** it is necessary to clone the repository.
@@ -320,3 +378,4 @@ Procedure to update the production environment or any other that uses built imag
- Edit the `.env` file to add new variables or change them if necessary.
- Pull the new images with the `docker-compose pull` command.
- Restart services `docker-compose stop && docker-compose up -d`.
+
diff --git a/backend/.gitignore b/backend/.gitignore
index feb11a4..78c1299 100644
--- a/backend/.gitignore
+++ b/backend/.gitignore
@@ -163,4 +163,6 @@ cython_debug/
# Django
django_static/
-archive/
\ No newline at end of file
+archive/
+
+saml2/
\ No newline at end of file
diff --git a/backend/Dockerfile b/backend/Dockerfile
index 6c24b5c..53cd1cb 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -15,6 +15,9 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
build-essential \
libpcre3 \
libpcre3-dev \
+ xmlsec1 \
+ libssl-dev \
+ libsasl2-dev \
&& apt-get clean \
&& apt-get autoclean \
&& apt-get autoremove --purge -y \
@@ -48,4 +51,4 @@ COPY --chmod=0775 ./start.sh /start.sh
# Switch to non-priviliged user and run app
USER $USERNAME
-ENTRYPOINT [ "/entrypoint.sh" ]
\ No newline at end of file
+ENTRYPOINT [ "/entrypoint.sh" ]
diff --git a/backend/attribute-maps/__init__.py b/backend/attribute-maps/__init__.py
new file mode 100644
index 0000000..d041d3f
--- /dev/null
+++ b/backend/attribute-maps/__init__.py
@@ -0,0 +1,2 @@
+__author__ = 'rohe0002'
+__all__ = ["adfs_v1x", "adfs_v20", "basic", "saml_uri", "shibboleth_uri"]
diff --git a/backend/attribute-maps/adfs_v1x.py b/backend/attribute-maps/adfs_v1x.py
new file mode 100644
index 0000000..0f8d01a
--- /dev/null
+++ b/backend/attribute-maps/adfs_v1x.py
@@ -0,0 +1,18 @@
+CLAIMS = 'http://schemas.xmlsoap.org/claims/'
+
+
+MAP = {
+ "identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified",
+ 'fro': {
+ CLAIMS+'commonname': 'commonName',
+ CLAIMS+'emailaddress': 'emailAddress',
+ CLAIMS+'group': 'group',
+ CLAIMS+'upn': 'upn',
+ },
+ 'to': {
+ 'commonName': CLAIMS+'commonname',
+ 'emailAddress': CLAIMS+'emailaddress',
+ 'group': CLAIMS+'group',
+ 'upn': CLAIMS+'upn',
+ }
+}
diff --git a/backend/attribute-maps/adfs_v20.py b/backend/attribute-maps/adfs_v20.py
new file mode 100644
index 0000000..94150d0
--- /dev/null
+++ b/backend/attribute-maps/adfs_v20.py
@@ -0,0 +1,49 @@
+CLAIMS = 'http://schemas.xmlsoap.org/claims/'
+COM_WS_CLAIMS = 'http://schemas.xmlsoap.com/ws/2005/05/identity/claims/'
+MS_CLAIMS = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/'
+ORG_WS_CLAIMS = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/'
+
+
+MAP = {
+ "identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified",
+ 'fro': {
+ CLAIMS+'commonname': 'commonName',
+ CLAIMS+'group': 'group',
+ COM_WS_CLAIMS+'denyonlysid': 'denyOnlySid',
+ MS_CLAIMS+'authenticationmethod': 'authenticationMethod',
+ MS_CLAIMS+'denyonlyprimarygroupsid': 'denyOnlyPrimaryGroupSid',
+ MS_CLAIMS+'denyonlyprimarysid': 'denyOnlyPrimarySid',
+ MS_CLAIMS+'groupsid': 'groupSid',
+ MS_CLAIMS+'primarygroupsid': 'primaryGroupSid',
+ MS_CLAIMS+'primarysid': 'primarySid',
+ MS_CLAIMS+'role': 'role',
+ MS_CLAIMS+'windowsaccountname': 'windowsAccountName',
+ ORG_WS_CLAIMS+'emailaddress': 'emailAddress',
+ ORG_WS_CLAIMS+'givenname': 'givenName',
+ ORG_WS_CLAIMS+'name': 'name',
+ ORG_WS_CLAIMS+'nameidentifier': 'nameId',
+ ORG_WS_CLAIMS+'privatepersonalidentifier': 'privatePersonalId',
+ ORG_WS_CLAIMS+'surname': 'surname',
+ ORG_WS_CLAIMS+'upn': 'upn',
+ },
+ 'to': {
+ 'authenticationMethod': MS_CLAIMS+'authenticationmethod',
+ 'commonName': CLAIMS+'commonname',
+ 'denyOnlyPrimaryGroupSid': MS_CLAIMS+'denyonlyprimarygroupsid',
+ 'denyOnlyPrimarySid': MS_CLAIMS+'denyonlyprimarysid',
+ 'denyOnlySid': COM_WS_CLAIMS+'denyonlysid',
+ 'emailAddress': ORG_WS_CLAIMS+'emailaddress',
+ 'givenName': ORG_WS_CLAIMS+'givenname',
+ 'group': CLAIMS+'group',
+ 'groupSid': MS_CLAIMS+'groupsid',
+ 'name': ORG_WS_CLAIMS+'name',
+ 'nameId': ORG_WS_CLAIMS+'nameidentifier',
+ 'primaryGroupSid': MS_CLAIMS+'primarygroupsid',
+ 'primarySid': MS_CLAIMS+'primarysid',
+ 'privatePersonalId': ORG_WS_CLAIMS+'privatepersonalidentifier',
+ 'role': MS_CLAIMS+'role',
+ 'surname': ORG_WS_CLAIMS+'surname',
+ 'upn': ORG_WS_CLAIMS+'upn',
+ 'windowsAccountName': MS_CLAIMS+'windowsaccountname',
+ }
+}
diff --git a/backend/attribute-maps/basic.py b/backend/attribute-maps/basic.py
new file mode 100644
index 0000000..c05b6e9
--- /dev/null
+++ b/backend/attribute-maps/basic.py
@@ -0,0 +1,340 @@
+DEF = 'urn:mace:dir:attribute-def:'
+
+
+MAP = {
+ "identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:basic",
+ 'fro': {
+ DEF+'aRecord': 'aRecord',
+ DEF+'aliasedEntryName': 'aliasedEntryName',
+ DEF+'aliasedObjectName': 'aliasedObjectName',
+ DEF+'associatedDomain': 'associatedDomain',
+ DEF+'associatedName': 'associatedName',
+ DEF+'audio': 'audio',
+ DEF+'authorityRevocationList': 'authorityRevocationList',
+ DEF+'buildingName': 'buildingName',
+ DEF+'businessCategory': 'businessCategory',
+ DEF+'c': 'c',
+ DEF+'cACertificate': 'cACertificate',
+ DEF+'cNAMERecord': 'cNAMERecord',
+ DEF+'carLicense': 'carLicense',
+ DEF+'certificateRevocationList': 'certificateRevocationList',
+ DEF+'cn': 'cn',
+ DEF+'co': 'co',
+ DEF+'commonName': 'commonName',
+ DEF+'countryName': 'countryName',
+ DEF+'crossCertificatePair': 'crossCertificatePair',
+ DEF+'dITRedirect': 'dITRedirect',
+ DEF+'dSAQuality': 'dSAQuality',
+ DEF+'dc': 'dc',
+ DEF+'deltaRevocationList': 'deltaRevocationList',
+ DEF+'departmentNumber': 'departmentNumber',
+ DEF+'description': 'description',
+ DEF+'destinationIndicator': 'destinationIndicator',
+ DEF+'displayName': 'displayName',
+ DEF+'distinguishedName': 'distinguishedName',
+ DEF+'dmdName': 'dmdName',
+ DEF+'dnQualifier': 'dnQualifier',
+ DEF+'documentAuthor': 'documentAuthor',
+ DEF+'documentIdentifier': 'documentIdentifier',
+ DEF+'documentLocation': 'documentLocation',
+ DEF+'documentPublisher': 'documentPublisher',
+ DEF+'documentTitle': 'documentTitle',
+ DEF+'documentVersion': 'documentVersion',
+ DEF+'domainComponent': 'domainComponent',
+ DEF+'drink': 'drink',
+ DEF+'eduOrgHomePageURI': 'eduOrgHomePageURI',
+ DEF+'eduOrgIdentityAuthNPolicyURI': 'eduOrgIdentityAuthNPolicyURI',
+ DEF+'eduOrgLegalName': 'eduOrgLegalName',
+ DEF+'eduOrgSuperiorURI': 'eduOrgSuperiorURI',
+ DEF+'eduOrgWhitePagesURI': 'eduOrgWhitePagesURI',
+ DEF+'eduCourseOffering': 'eduCourseOffering',
+ DEF+'eduCourseMember': 'eduCourseMember',
+ DEF+'eduPersonAffiliation': 'eduPersonAffiliation',
+ DEF+'eduPersonEntitlement': 'eduPersonEntitlement',
+ DEF+'eduPersonNickname': 'eduPersonNickname',
+ DEF+'eduPersonOrgDN': 'eduPersonOrgDN',
+ DEF+'eduPersonOrgUnitDN': 'eduPersonOrgUnitDN',
+ DEF+'eduPersonPrimaryAffiliation': 'eduPersonPrimaryAffiliation',
+ DEF+'eduPersonPrimaryOrgUnitDN': 'eduPersonPrimaryOrgUnitDN',
+ DEF+'eduPersonPrincipalName': 'eduPersonPrincipalName',
+ DEF+'eduPersonPrincipalNamePrior': 'eduPersonPrincipalNamePrior',
+ DEF+'eduPersonScopedAffiliation': 'eduPersonScopedAffiliation',
+ DEF+'eduPersonTargetedID': 'eduPersonTargetedID',
+ DEF+'eduPersonAssurance': 'eduPersonAssurance',
+ DEF+'eduPersonUniqueId': 'eduPersonUniqueId',
+ DEF+'eduPersonOrcid': 'eduPersonOrcid',
+ DEF+'email': 'email',
+ DEF+'emailAddress': 'emailAddress',
+ DEF+'employeeNumber': 'employeeNumber',
+ DEF+'employeeType': 'employeeType',
+ DEF+'enhancedSearchGuide': 'enhancedSearchGuide',
+ DEF+'facsimileTelephoneNumber': 'facsimileTelephoneNumber',
+ DEF+'favouriteDrink': 'favouriteDrink',
+ DEF+'fax': 'fax',
+ DEF+'federationFeideSchemaVersion': 'federationFeideSchemaVersion',
+ DEF+'friendlyCountryName': 'friendlyCountryName',
+ DEF+'generationQualifier': 'generationQualifier',
+ DEF+'givenName': 'givenName',
+ DEF+'gn': 'gn',
+ DEF+'homePhone': 'homePhone',
+ DEF+'homePostalAddress': 'homePostalAddress',
+ DEF+'homeTelephoneNumber': 'homeTelephoneNumber',
+ DEF+'host': 'host',
+ DEF+'houseIdentifier': 'houseIdentifier',
+ DEF+'info': 'info',
+ DEF+'initials': 'initials',
+ DEF+'internationaliSDNNumber': 'internationaliSDNNumber',
+ DEF+'janetMailbox': 'janetMailbox',
+ DEF+'jpegPhoto': 'jpegPhoto',
+ DEF+'knowledgeInformation': 'knowledgeInformation',
+ DEF+'l': 'l',
+ DEF+'labeledURI': 'labeledURI',
+ DEF+'localityName': 'localityName',
+ DEF+'mDRecord': 'mDRecord',
+ DEF+'mXRecord': 'mXRecord',
+ DEF+'mail': 'mail',
+ DEF+'mailPreferenceOption': 'mailPreferenceOption',
+ DEF+'manager': 'manager',
+ DEF+'member': 'member',
+ DEF+'mobile': 'mobile',
+ DEF+'mobileTelephoneNumber': 'mobileTelephoneNumber',
+ DEF+'nSRecord': 'nSRecord',
+ DEF+'name': 'name',
+ DEF+'norEduOrgAcronym': 'norEduOrgAcronym',
+ DEF+'norEduOrgNIN': 'norEduOrgNIN',
+ DEF+'norEduOrgSchemaVersion': 'norEduOrgSchemaVersion',
+ DEF+'norEduOrgUniqueIdentifier': 'norEduOrgUniqueIdentifier',
+ DEF+'norEduOrgUniqueNumber': 'norEduOrgUniqueNumber',
+ DEF+'norEduOrgUnitUniqueIdentifier': 'norEduOrgUnitUniqueIdentifier',
+ DEF+'norEduOrgUnitUniqueNumber': 'norEduOrgUnitUniqueNumber',
+ DEF+'norEduPersonBirthDate': 'norEduPersonBirthDate',
+ DEF+'norEduPersonLIN': 'norEduPersonLIN',
+ DEF+'norEduPersonNIN': 'norEduPersonNIN',
+ DEF+'o': 'o',
+ DEF+'objectClass': 'objectClass',
+ DEF+'organizationName': 'organizationName',
+ DEF+'organizationalStatus': 'organizationalStatus',
+ DEF+'organizationalUnitName': 'organizationalUnitName',
+ DEF+'otherMailbox': 'otherMailbox',
+ DEF+'ou': 'ou',
+ DEF+'owner': 'owner',
+ DEF+'pager': 'pager',
+ DEF+'pagerTelephoneNumber': 'pagerTelephoneNumber',
+ DEF+'personalSignature': 'personalSignature',
+ DEF+'personalTitle': 'personalTitle',
+ DEF+'photo': 'photo',
+ DEF+'physicalDeliveryOfficeName': 'physicalDeliveryOfficeName',
+ DEF+'pkcs9email': 'pkcs9email',
+ DEF+'postOfficeBox': 'postOfficeBox',
+ DEF+'postalAddress': 'postalAddress',
+ DEF+'postalCode': 'postalCode',
+ DEF+'preferredDeliveryMethod': 'preferredDeliveryMethod',
+ DEF+'preferredLanguage': 'preferredLanguage',
+ DEF+'presentationAddress': 'presentationAddress',
+ DEF+'protocolInformation': 'protocolInformation',
+ DEF+'pseudonym': 'pseudonym',
+ DEF+'registeredAddress': 'registeredAddress',
+ DEF+'rfc822Mailbox': 'rfc822Mailbox',
+ DEF+'roleOccupant': 'roleOccupant',
+ DEF+'roomNumber': 'roomNumber',
+ DEF+'sOARecord': 'sOARecord',
+ DEF+'searchGuide': 'searchGuide',
+ DEF+'secretary': 'secretary',
+ DEF+'seeAlso': 'seeAlso',
+ DEF+'serialNumber': 'serialNumber',
+ DEF+'singleLevelQuality': 'singleLevelQuality',
+ DEF+'sn': 'sn',
+ DEF+'st': 'st',
+ DEF+'stateOrProvinceName': 'stateOrProvinceName',
+ DEF+'street': 'street',
+ DEF+'streetAddress': 'streetAddress',
+ DEF+'subtreeMaximumQuality': 'subtreeMaximumQuality',
+ DEF+'subtreeMinimumQuality': 'subtreeMinimumQuality',
+ DEF+'supportedAlgorithms': 'supportedAlgorithms',
+ DEF+'supportedApplicationContext': 'supportedApplicationContext',
+ DEF+'surname': 'surname',
+ DEF+'telephoneNumber': 'telephoneNumber',
+ DEF+'teletexTerminalIdentifier': 'teletexTerminalIdentifier',
+ DEF+'telexNumber': 'telexNumber',
+ DEF+'textEncodedORAddress': 'textEncodedORAddress',
+ DEF+'title': 'title',
+ DEF+'uid': 'uid',
+ DEF+'uniqueIdentifier': 'uniqueIdentifier',
+ DEF+'uniqueMember': 'uniqueMember',
+ DEF+'userCertificate': 'userCertificate',
+ DEF+'userClass': 'userClass',
+ DEF+'userPKCS12': 'userPKCS12',
+ DEF+'userPassword': 'userPassword',
+ DEF+'userSMIMECertificate': 'userSMIMECertificate',
+ DEF+'userid': 'userid',
+ DEF+'x121Address': 'x121Address',
+ DEF+'x500UniqueIdentifier': 'x500UniqueIdentifier',
+ },
+ 'to': {
+ 'aRecord': DEF+'aRecord',
+ 'aliasedEntryName': DEF+'aliasedEntryName',
+ 'aliasedObjectName': DEF+'aliasedObjectName',
+ 'associatedDomain': DEF+'associatedDomain',
+ 'associatedName': DEF+'associatedName',
+ 'audio': DEF+'audio',
+ 'authorityRevocationList': DEF+'authorityRevocationList',
+ 'buildingName': DEF+'buildingName',
+ 'businessCategory': DEF+'businessCategory',
+ 'c': DEF+'c',
+ 'cACertificate': DEF+'cACertificate',
+ 'cNAMERecord': DEF+'cNAMERecord',
+ 'carLicense': DEF+'carLicense',
+ 'certificateRevocationList': DEF+'certificateRevocationList',
+ 'cn': DEF+'cn',
+ 'co': DEF+'co',
+ 'commonName': DEF+'commonName',
+ 'countryName': DEF+'countryName',
+ 'crossCertificatePair': DEF+'crossCertificatePair',
+ 'dITRedirect': DEF+'dITRedirect',
+ 'dSAQuality': DEF+'dSAQuality',
+ 'dc': DEF+'dc',
+ 'deltaRevocationList': DEF+'deltaRevocationList',
+ 'departmentNumber': DEF+'departmentNumber',
+ 'description': DEF+'description',
+ 'destinationIndicator': DEF+'destinationIndicator',
+ 'displayName': DEF+'displayName',
+ 'distinguishedName': DEF+'distinguishedName',
+ 'dmdName': DEF+'dmdName',
+ 'dnQualifier': DEF+'dnQualifier',
+ 'documentAuthor': DEF+'documentAuthor',
+ 'documentIdentifier': DEF+'documentIdentifier',
+ 'documentLocation': DEF+'documentLocation',
+ 'documentPublisher': DEF+'documentPublisher',
+ 'documentTitle': DEF+'documentTitle',
+ 'documentVersion': DEF+'documentVersion',
+ 'domainComponent': DEF+'domainComponent',
+ 'drink': DEF+'drink',
+ 'eduOrgHomePageURI': DEF+'eduOrgHomePageURI',
+ 'eduOrgIdentityAuthNPolicyURI': DEF+'eduOrgIdentityAuthNPolicyURI',
+ 'eduOrgLegalName': DEF+'eduOrgLegalName',
+ 'eduOrgSuperiorURI': DEF+'eduOrgSuperiorURI',
+ 'eduOrgWhitePagesURI': DEF+'eduOrgWhitePagesURI',
+ 'eduCourseMember': DEF+'eduCourseMember',
+ 'eduCourseOffering': DEF+'eduCourseOffering',
+ 'eduPersonAffiliation': DEF+'eduPersonAffiliation',
+ 'eduPersonEntitlement': DEF+'eduPersonEntitlement',
+ 'eduPersonNickname': DEF+'eduPersonNickname',
+ 'eduPersonOrgDN': DEF+'eduPersonOrgDN',
+ 'eduPersonOrgUnitDN': DEF+'eduPersonOrgUnitDN',
+ 'eduPersonPrimaryAffiliation': DEF+'eduPersonPrimaryAffiliation',
+ 'eduPersonPrimaryOrgUnitDN': DEF+'eduPersonPrimaryOrgUnitDN',
+ 'eduPersonPrincipalName': DEF+'eduPersonPrincipalName',
+ 'eduPersonPrincipalNamePrior': DEF+'eduPersonPrincipalNamePrior',
+ 'eduPersonScopedAffiliation': DEF+'eduPersonScopedAffiliation',
+ 'eduPersonTargetedID': DEF+'eduPersonTargetedID',
+ 'eduPersonAssurance': DEF+'eduPersonAssurance',
+ 'eduPersonUniqueId': DEF+'eduPersonUniqueId',
+ 'eduPersonOrcid': DEF+'eduPersonOrcid',
+ 'email': DEF+'email',
+ 'emailAddress': DEF+'emailAddress',
+ 'employeeNumber': DEF+'employeeNumber',
+ 'employeeType': DEF+'employeeType',
+ 'enhancedSearchGuide': DEF+'enhancedSearchGuide',
+ 'facsimileTelephoneNumber': DEF+'facsimileTelephoneNumber',
+ 'favouriteDrink': DEF+'favouriteDrink',
+ 'fax': DEF+'fax',
+ 'federationFeideSchemaVersion': DEF+'federationFeideSchemaVersion',
+ 'friendlyCountryName': DEF+'friendlyCountryName',
+ 'generationQualifier': DEF+'generationQualifier',
+ 'givenName': DEF+'givenName',
+ 'gn': DEF+'gn',
+ 'homePhone': DEF+'homePhone',
+ 'homePostalAddress': DEF+'homePostalAddress',
+ 'homeTelephoneNumber': DEF+'homeTelephoneNumber',
+ 'host': DEF+'host',
+ 'houseIdentifier': DEF+'houseIdentifier',
+ 'info': DEF+'info',
+ 'initials': DEF+'initials',
+ 'internationaliSDNNumber': DEF+'internationaliSDNNumber',
+ 'janetMailbox': DEF+'janetMailbox',
+ 'jpegPhoto': DEF+'jpegPhoto',
+ 'knowledgeInformation': DEF+'knowledgeInformation',
+ 'l': DEF+'l',
+ 'labeledURI': DEF+'labeledURI',
+ 'localityName': DEF+'localityName',
+ 'mDRecord': DEF+'mDRecord',
+ 'mXRecord': DEF+'mXRecord',
+ 'mail': DEF+'mail',
+ 'mailPreferenceOption': DEF+'mailPreferenceOption',
+ 'manager': DEF+'manager',
+ 'member': DEF+'member',
+ 'mobile': DEF+'mobile',
+ 'mobileTelephoneNumber': DEF+'mobileTelephoneNumber',
+ 'nSRecord': DEF+'nSRecord',
+ 'name': DEF+'name',
+ 'norEduOrgAcronym': DEF+'norEduOrgAcronym',
+ 'norEduOrgNIN': DEF+'norEduOrgNIN',
+ 'norEduOrgSchemaVersion': DEF+'norEduOrgSchemaVersion',
+ 'norEduOrgUniqueIdentifier': DEF+'norEduOrgUniqueIdentifier',
+ 'norEduOrgUniqueNumber': DEF+'norEduOrgUniqueNumber',
+ 'norEduOrgUnitUniqueIdentifier': DEF+'norEduOrgUnitUniqueIdentifier',
+ 'norEduOrgUnitUniqueNumber': DEF+'norEduOrgUnitUniqueNumber',
+ 'norEduPersonBirthDate': DEF+'norEduPersonBirthDate',
+ 'norEduPersonLIN': DEF+'norEduPersonLIN',
+ 'norEduPersonNIN': DEF+'norEduPersonNIN',
+ 'o': DEF+'o',
+ 'objectClass': DEF+'objectClass',
+ 'organizationName': DEF+'organizationName',
+ 'organizationalStatus': DEF+'organizationalStatus',
+ 'organizationalUnitName': DEF+'organizationalUnitName',
+ 'otherMailbox': DEF+'otherMailbox',
+ 'ou': DEF+'ou',
+ 'owner': DEF+'owner',
+ 'pager': DEF+'pager',
+ 'pagerTelephoneNumber': DEF+'pagerTelephoneNumber',
+ 'personalSignature': DEF+'personalSignature',
+ 'personalTitle': DEF+'personalTitle',
+ 'photo': DEF+'photo',
+ 'physicalDeliveryOfficeName': DEF+'physicalDeliveryOfficeName',
+ 'pkcs9email': DEF+'pkcs9email',
+ 'postOfficeBox': DEF+'postOfficeBox',
+ 'postalAddress': DEF+'postalAddress',
+ 'postalCode': DEF+'postalCode',
+ 'preferredDeliveryMethod': DEF+'preferredDeliveryMethod',
+ 'preferredLanguage': DEF+'preferredLanguage',
+ 'presentationAddress': DEF+'presentationAddress',
+ 'protocolInformation': DEF+'protocolInformation',
+ 'pseudonym': DEF+'pseudonym',
+ 'registeredAddress': DEF+'registeredAddress',
+ 'rfc822Mailbox': DEF+'rfc822Mailbox',
+ 'roleOccupant': DEF+'roleOccupant',
+ 'roomNumber': DEF+'roomNumber',
+ 'sOARecord': DEF+'sOARecord',
+ 'searchGuide': DEF+'searchGuide',
+ 'secretary': DEF+'secretary',
+ 'seeAlso': DEF+'seeAlso',
+ 'serialNumber': DEF+'serialNumber',
+ 'singleLevelQuality': DEF+'singleLevelQuality',
+ 'sn': DEF+'sn',
+ 'st': DEF+'st',
+ 'stateOrProvinceName': DEF+'stateOrProvinceName',
+ 'street': DEF+'street',
+ 'streetAddress': DEF+'streetAddress',
+ 'subtreeMaximumQuality': DEF+'subtreeMaximumQuality',
+ 'subtreeMinimumQuality': DEF+'subtreeMinimumQuality',
+ 'supportedAlgorithms': DEF+'supportedAlgorithms',
+ 'supportedApplicationContext': DEF+'supportedApplicationContext',
+ 'surname': DEF+'surname',
+ 'telephoneNumber': DEF+'telephoneNumber',
+ 'teletexTerminalIdentifier': DEF+'teletexTerminalIdentifier',
+ 'telexNumber': DEF+'telexNumber',
+ 'textEncodedORAddress': DEF+'textEncodedORAddress',
+ 'title': DEF+'title',
+ 'uid': DEF+'uid',
+ 'uniqueIdentifier': DEF+'uniqueIdentifier',
+ 'uniqueMember': DEF+'uniqueMember',
+ 'userCertificate': DEF+'userCertificate',
+ 'userClass': DEF+'userClass',
+ 'userPKCS12': DEF+'userPKCS12',
+ 'userPassword': DEF+'userPassword',
+ 'userSMIMECertificate': DEF+'userSMIMECertificate',
+ 'userid': DEF+'userid',
+ 'x121Address': DEF+'x121Address',
+ 'x500UniqueIdentifier': DEF+'x500UniqueIdentifier',
+ }
+}
diff --git a/backend/attribute-maps/saml_uri.py b/backend/attribute-maps/saml_uri.py
new file mode 100644
index 0000000..3a61726
--- /dev/null
+++ b/backend/attribute-maps/saml_uri.py
@@ -0,0 +1,316 @@
+EDUCOURSE_OID = 'urn:oid:1.3.6.1.4.1.5923.1.6.1.'
+EDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.5923.1.1.1.'
+EDUMEMBER1_OID = 'urn:oid:1.3.6.1.4.1.5923.1.5.1.'
+LDAPGVAT_OID = 'urn:oid:1.2.40.0.10.2.1.1.' # ldap.gv.at definitions as specified in http://www.ref.gv.at/AG-IZ-PVP2-Version-2-1-0-2.2754.0.html
+UCL_DIR_PILOT = 'urn:oid:0.9.2342.19200300.100.1.'
+X500ATTR_OID = 'urn:oid:2.5.4.'
+LDAPGVAT_UCL_DIR_PILOT = UCL_DIR_PILOT
+LDAPGVAT_X500ATTR_OID = X500ATTR_OID
+NETSCAPE_LDAP = 'urn:oid:2.16.840.1.113730.3.1.'
+NOREDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.2428.90.1.'
+PKCS_9 = 'urn:oid:1.2.840.113549.1.9.1.'
+SCHAC = 'urn:oid:1.3.6.1.4.1.25178.1.2.'
+SIS = 'urn:oid:1.2.752.194.10.2.'
+UMICH = 'urn:oid:1.3.6.1.4.1.250.1.57.'
+OPENOSI_OID = 'urn:oid:1.3.6.1.4.1.27630.2.1.1.' #openosi-0.82.schema http://www.openosi.org/osi/display/ldap/Home
+BREDUPERSON_OID_1 = 'urn:oid:1.3.6.1.4.1.15996.100.1.1.1.' # from rnp brPersonCPF
+BREDUPERSON_OID_2 = 'urn:oid:1.3.6.1.4.1.15996.100.1.1.2.' # from rnp brEduAffiliationType
+LDAPELEMENTS = 'urn:oid:1.3.6.1.4.1.1466.115.121.1.' # from ldap elementes http://www.oid-info.com/get/1.3.6.1.4.1.1466.115.121.1
+
+MAP = {
+ 'identifier': 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
+ 'fro': {
+ LDAPELEMENTS+'36': 'schacDateOfBirth',
+ BREDUPERSON_OID_1+'1': 'brPersonCPF',
+ BREDUPERSON_OID_2+'1': 'brEduAffiliationType',
+ EDUCOURSE_OID+'1': 'eduCourseOffering',
+ EDUCOURSE_OID+'2': 'eduCourseMember',
+ EDUMEMBER1_OID+'1': 'isMemberOf',
+ EDUPERSON_OID+'1': 'eduPersonAffiliation',
+ EDUPERSON_OID+'2': 'eduPersonNickname',
+ EDUPERSON_OID+'3': 'eduPersonOrgDN',
+ EDUPERSON_OID+'4': 'eduPersonOrgUnitDN',
+ EDUPERSON_OID+'5': 'eduPersonPrimaryAffiliation',
+ EDUPERSON_OID+'6': 'eduPersonPrincipalName',
+ EDUPERSON_OID+'7': 'eduPersonEntitlement',
+ EDUPERSON_OID+'8': 'eduPersonPrimaryOrgUnitDN',
+ EDUPERSON_OID+'9': 'eduPersonScopedAffiliation',
+ EDUPERSON_OID+'10': 'eduPersonTargetedID',
+ EDUPERSON_OID+'11': 'eduPersonAssurance',
+ EDUPERSON_OID+'12': 'eduPersonPrincipalNamePrior',
+ EDUPERSON_OID+'13': 'eduPersonUniqueId',
+ EDUPERSON_OID+'16': 'eduPersonOrcid',
+ LDAPGVAT_OID+'1': 'PVP-GID',
+ LDAPGVAT_OID+'149': 'PVP-BPK',
+ LDAPGVAT_OID+'153': 'PVP-OU-OKZ',
+ LDAPGVAT_OID+'261.10': 'PVP-VERSION',
+ LDAPGVAT_OID+'261.20': 'PVP-PRINCIPAL-NAME',
+ LDAPGVAT_OID+'261.24': 'PVP-PARTICIPANT-OKZ',
+ LDAPGVAT_OID+'261.30': 'PVP-ROLES',
+ LDAPGVAT_OID+'261.40': 'PVP-INVOICE-RECPT-ID',
+ LDAPGVAT_OID+'261.50': 'PVP-COST-CENTER-ID',
+ LDAPGVAT_OID+'261.60': 'PVP-CHARGE-CODE',
+ LDAPGVAT_OID+'3': 'PVP-OU-GV-OU-ID',
+ LDAPGVAT_OID+'33': 'PVP-FUNCTION',
+ LDAPGVAT_OID+'55': 'PVP-BIRTHDATE',
+ LDAPGVAT_OID+'71': 'PVP-PARTICIPANT-ID',
+ LDAPGVAT_UCL_DIR_PILOT+'1': 'PVP-USERID',
+ LDAPGVAT_UCL_DIR_PILOT+'3': 'PVP-MAIL',
+ LDAPGVAT_X500ATTR_OID+'11': 'PVP-OU',
+ LDAPGVAT_X500ATTR_OID+'20': 'PVP-TEL',
+ LDAPGVAT_X500ATTR_OID+'42': 'PVP-GIVENNAME',
+ NETSCAPE_LDAP+'1': 'carLicense',
+ NETSCAPE_LDAP+'2': 'departmentNumber',
+ NETSCAPE_LDAP+'3': 'employeeNumber',
+ NETSCAPE_LDAP+'4': 'employeeType',
+ NETSCAPE_LDAP+'39': 'preferredLanguage',
+ NETSCAPE_LDAP+'40': 'userSMIMECertificate',
+ NETSCAPE_LDAP+'216': 'userPKCS12',
+ NETSCAPE_LDAP+'241': 'displayName',
+ NOREDUPERSON_OID+'1': 'norEduOrgUniqueNumber',
+ NOREDUPERSON_OID+'2': 'norEduOrgUnitUniqueNumber',
+ NOREDUPERSON_OID+'3': 'norEduPersonBirthDate',
+ NOREDUPERSON_OID+'4': 'norEduPersonLIN',
+ NOREDUPERSON_OID+'5': 'norEduPersonNIN',
+ NOREDUPERSON_OID+'6': 'norEduOrgAcronym',
+ NOREDUPERSON_OID+'7': 'norEduOrgUniqueIdentifier',
+ NOREDUPERSON_OID+'8': 'norEduOrgUnitUniqueIdentifier',
+ NOREDUPERSON_OID+'9': 'federationFeideSchemaVersion',
+ NOREDUPERSON_OID+'10': 'norEduPersonLegalName',
+ NOREDUPERSON_OID+'11': 'norEduOrgSchemaVersion',
+ NOREDUPERSON_OID+'12': 'norEduOrgNIN',
+ OPENOSI_OID+'17': 'osiHomeUrl',
+ OPENOSI_OID+'19': 'osiPreferredTZ',
+ OPENOSI_OID+'72': 'osiICardTimeLastUpdated',
+ OPENOSI_OID+'104': 'osiMiddleName',
+ OPENOSI_OID+'107': 'osiOtherEmail',
+ OPENOSI_OID+'109': 'osiOtherHomePhone',
+ OPENOSI_OID+'120': 'osiWorkURL',
+ PKCS_9+'1': 'email',
+ SCHAC+'1': 'schacMotherTongue',
+ SCHAC+'2': 'schacGender',
+ SCHAC+'3': 'schacDateOfBirth',
+ SCHAC+'4': 'schacPlaceOfBirth',
+ SCHAC+'5': 'schacCountryOfCitizenship',
+ SCHAC+'6': 'schacSn1',
+ SCHAC+'7': 'schacSn2',
+ SCHAC+'8': 'schacPersonalTitle',
+ SCHAC+'9': 'schacHomeOrganization',
+ SCHAC+'10': 'schacHomeOrganizationType',
+ SCHAC+'11': 'schacCountryOfResidence',
+ SCHAC+'12': 'schacUserPresenceID',
+ SCHAC+'13': 'schacPersonalPosition',
+ SCHAC+'14': 'schacPersonalUniqueCode',
+ SCHAC+'15': 'schacPersonalUniqueID',
+ SCHAC+'17': 'schacExpiryDate',
+ SCHAC+'18': 'schacUserPrivateAttribute',
+ SCHAC+'19': 'schacUserStatus',
+ SCHAC+'20': 'schacProjectMembership',
+ SCHAC+'21': 'schacProjectSpecificRole',
+ SIS+'1': 'sisLegalGuardianFor',
+ SIS+'2': 'sisSchoolGrade',
+ UCL_DIR_PILOT+'1': 'uid',
+ UCL_DIR_PILOT+'3': 'mail',
+ UCL_DIR_PILOT+'25': 'dc',
+ UCL_DIR_PILOT+'37': 'associatedDomain',
+ UCL_DIR_PILOT+'43': 'co',
+ UCL_DIR_PILOT+'60': 'jpegPhoto',
+ UMICH+'57': 'labeledURI',
+ X500ATTR_OID+'2': 'knowledgeInformation',
+ X500ATTR_OID+'3': 'cn',
+ X500ATTR_OID+'4': 'sn',
+ X500ATTR_OID+'5': 'serialNumber',
+ X500ATTR_OID+'6': 'c',
+ X500ATTR_OID+'7': 'l',
+ X500ATTR_OID+'8': 'st',
+ X500ATTR_OID+'9': 'street',
+ X500ATTR_OID+'10': 'o',
+ X500ATTR_OID+'11': 'ou',
+ X500ATTR_OID+'12': 'title',
+ X500ATTR_OID+'14': 'searchGuide',
+ X500ATTR_OID+'15': 'businessCategory',
+ X500ATTR_OID+'16': 'postalAddress',
+ X500ATTR_OID+'17': 'postalCode',
+ X500ATTR_OID+'18': 'postOfficeBox',
+ X500ATTR_OID+'19': 'physicalDeliveryOfficeName',
+ X500ATTR_OID+'20': 'telephoneNumber',
+ X500ATTR_OID+'21': 'telexNumber',
+ X500ATTR_OID+'22': 'teletexTerminalIdentifier',
+ X500ATTR_OID+'23': 'facsimileTelephoneNumber',
+ X500ATTR_OID+'24': 'x121Address',
+ X500ATTR_OID+'25': 'internationaliSDNNumber',
+ X500ATTR_OID+'26': 'registeredAddress',
+ X500ATTR_OID+'27': 'destinationIndicator',
+ X500ATTR_OID+'28': 'preferredDeliveryMethod',
+ X500ATTR_OID+'29': 'presentationAddress',
+ X500ATTR_OID+'30': 'supportedApplicationContext',
+ X500ATTR_OID+'31': 'member',
+ X500ATTR_OID+'32': 'owner',
+ X500ATTR_OID+'33': 'roleOccupant',
+ X500ATTR_OID+'36': 'userCertificate',
+ X500ATTR_OID+'37': 'cACertificate',
+ X500ATTR_OID+'38': 'authorityRevocationList',
+ X500ATTR_OID+'39': 'certificateRevocationList',
+ X500ATTR_OID+'40': 'crossCertificatePair',
+ X500ATTR_OID+'42': 'givenName',
+ X500ATTR_OID+'43': 'initials',
+ X500ATTR_OID+'44': 'generationQualifier',
+ X500ATTR_OID+'45': 'x500UniqueIdentifier',
+ X500ATTR_OID+'46': 'dnQualifier',
+ X500ATTR_OID+'47': 'enhancedSearchGuide',
+ X500ATTR_OID+'48': 'protocolInformation',
+ X500ATTR_OID+'50': 'uniqueMember',
+ X500ATTR_OID+'51': 'houseIdentifier',
+ X500ATTR_OID+'52': 'supportedAlgorithms',
+ X500ATTR_OID+'53': 'deltaRevocationList',
+ X500ATTR_OID+'54': 'dmdName',
+ X500ATTR_OID+'65': 'pseudonym',
+ },
+ 'to': {
+ 'schacDateOfBirth': LDAPELEMENTS+'36',
+ 'associatedDomain': UCL_DIR_PILOT+'37',
+ 'authorityRevocationList': X500ATTR_OID+'38',
+ 'brEduAffiliationType': BREDUPERSON_OID_2+'1',
+ 'brPersonCPF': BREDUPERSON_OID_1+'1',
+ 'businessCategory': X500ATTR_OID+'15',
+ 'c': X500ATTR_OID+'6',
+ 'cACertificate': X500ATTR_OID+'37',
+ 'carLicense': NETSCAPE_LDAP+'1',
+ 'certificateRevocationList': X500ATTR_OID+'39',
+ 'cn': X500ATTR_OID+'3',
+ 'co': UCL_DIR_PILOT+'43',
+ 'crossCertificatePair': X500ATTR_OID+'40',
+ 'dc': UCL_DIR_PILOT+'25',
+ 'deltaRevocationList': X500ATTR_OID+'53',
+ 'departmentNumber': NETSCAPE_LDAP+'2',
+ 'destinationIndicator': X500ATTR_OID+'27',
+ 'displayName': NETSCAPE_LDAP+'241',
+ 'dmdName': X500ATTR_OID+'54',
+ 'dnQualifier': X500ATTR_OID+'46',
+ 'eduCourseMember': EDUCOURSE_OID+'2',
+ 'eduCourseOffering': EDUCOURSE_OID+'1',
+ 'eduPersonAffiliation': EDUPERSON_OID+'1',
+ 'eduPersonEntitlement': EDUPERSON_OID+'7',
+ 'eduPersonNickname': EDUPERSON_OID+'2',
+ 'eduPersonOrgDN': EDUPERSON_OID+'3',
+ 'eduPersonOrgUnitDN': EDUPERSON_OID+'4',
+ 'eduPersonPrimaryAffiliation': EDUPERSON_OID+'5',
+ 'eduPersonPrimaryOrgUnitDN': EDUPERSON_OID+'8',
+ 'eduPersonPrincipalName': EDUPERSON_OID+'6',
+ 'eduPersonPrincipalNamePrior': EDUPERSON_OID+'12',
+ 'eduPersonScopedAffiliation': EDUPERSON_OID+'9',
+ 'eduPersonTargetedID': EDUPERSON_OID+'10',
+ 'eduPersonAssurance': EDUPERSON_OID+'11',
+ 'eduPersonUniqueId': EDUPERSON_OID+'13',
+ 'eduPersonOrcid': EDUPERSON_OID+'16',
+ 'email': PKCS_9+'1',
+ 'employeeNumber': NETSCAPE_LDAP+'3',
+ 'employeeType': NETSCAPE_LDAP+'4',
+ 'enhancedSearchGuide': X500ATTR_OID+'47',
+ 'facsimileTelephoneNumber': X500ATTR_OID+'23',
+ 'federationFeideSchemaVersion': NOREDUPERSON_OID+'9',
+ 'generationQualifier': X500ATTR_OID+'44',
+ 'givenName': X500ATTR_OID+'42',
+ 'houseIdentifier': X500ATTR_OID+'51',
+ 'initials': X500ATTR_OID+'43',
+ 'internationaliSDNNumber': X500ATTR_OID+'25',
+ 'isMemberOf': EDUMEMBER1_OID+'1',
+ 'jpegPhoto': UCL_DIR_PILOT+'60',
+ 'knowledgeInformation': X500ATTR_OID+'2',
+ 'l': X500ATTR_OID+'7',
+ 'labeledURI': UMICH+'57',
+ 'mail': UCL_DIR_PILOT+'3',
+ 'member': X500ATTR_OID+'31',
+ 'norEduOrgAcronym': NOREDUPERSON_OID+'6',
+ 'norEduOrgNIN': NOREDUPERSON_OID+'12',
+ 'norEduOrgSchemaVersion': NOREDUPERSON_OID+'11',
+ 'norEduOrgUniqueIdentifier': NOREDUPERSON_OID+'7',
+ 'norEduOrgUniqueNumber': NOREDUPERSON_OID+'1',
+ 'norEduOrgUnitUniqueIdentifier': NOREDUPERSON_OID+'8',
+ 'norEduOrgUnitUniqueNumber': NOREDUPERSON_OID+'2',
+ 'norEduPersonBirthDate': NOREDUPERSON_OID+'3',
+ 'norEduPersonLIN': NOREDUPERSON_OID+'4',
+ 'norEduPersonLegalName': NOREDUPERSON_OID+'10',
+ 'norEduPersonNIN': NOREDUPERSON_OID+'5',
+ 'o': X500ATTR_OID+'10',
+ 'osiHomeUrl': OPENOSI_OID+'17',
+ 'osiPreferredTZ': OPENOSI_OID+'19',
+ 'osiICardTimeLastUpdated': OPENOSI_OID+'72',
+ 'osiMiddleName': OPENOSI_OID+'104',
+ 'osiOtherEmail': OPENOSI_OID+'107',
+ 'osiOtherHomePhone': OPENOSI_OID+'109',
+ 'osiWorkURL': OPENOSI_OID+'120',
+ 'ou': X500ATTR_OID+'11',
+ 'owner': X500ATTR_OID+'32',
+ 'physicalDeliveryOfficeName': X500ATTR_OID+'19',
+ 'postOfficeBox': X500ATTR_OID+'18',
+ 'postalAddress': X500ATTR_OID+'16',
+ 'postalCode': X500ATTR_OID+'17',
+ 'preferredDeliveryMethod': X500ATTR_OID+'28',
+ 'preferredLanguage': NETSCAPE_LDAP+'39',
+ 'presentationAddress': X500ATTR_OID+'29',
+ 'protocolInformation': X500ATTR_OID+'48',
+ 'pseudonym': X500ATTR_OID+'65',
+ 'PVP-USERID': LDAPGVAT_UCL_DIR_PILOT+'1',
+ 'PVP-MAIL': LDAPGVAT_UCL_DIR_PILOT+'3',
+ 'PVP-GID': LDAPGVAT_OID+'1',
+ 'PVP-BPK': LDAPGVAT_OID+'149',
+ 'PVP-OU-OKZ': LDAPGVAT_OID+'153',
+ 'PVP-VERSION': LDAPGVAT_OID+'261.10',
+ 'PVP-PRINCIPAL-NAME': LDAPGVAT_OID+'261.20',
+ 'PVP-PARTICIPANT-OKZ': LDAPGVAT_OID+'261.24',
+ 'PVP-ROLES': LDAPGVAT_OID+'261.30',
+ 'PVP-INVOICE-RECPT-ID': LDAPGVAT_OID+'261.40',
+ 'PVP-COST-CENTER-ID': LDAPGVAT_OID+'261.50',
+ 'PVP-CHARGE-CODE': LDAPGVAT_OID+'261.60',
+ 'PVP-OU-GV-OU-ID': LDAPGVAT_OID+'3',
+ 'PVP-FUNCTION': LDAPGVAT_OID+'33',
+ 'PVP-BIRTHDATE': LDAPGVAT_OID+'55',
+ 'PVP-PARTICIPANT-ID': LDAPGVAT_OID+'71',
+ 'PVP-OU': LDAPGVAT_X500ATTR_OID+'11',
+ 'PVP-TEL': LDAPGVAT_X500ATTR_OID+'20',
+ 'PVP-GIVENNAME': LDAPGVAT_X500ATTR_OID+'42',
+ 'registeredAddress': X500ATTR_OID+'26',
+ 'roleOccupant': X500ATTR_OID+'33',
+ 'schacCountryOfCitizenship': SCHAC+'5',
+ 'schacCountryOfResidence': SCHAC+'11',
+ 'schacDateOfBirth': SCHAC+'3',
+ 'schacExpiryDate': SCHAC+'17',
+ 'schacGender': SCHAC+'2',
+ 'schacHomeOrganization': SCHAC+'9',
+ 'schacHomeOrganizationType': SCHAC+'10',
+ 'schacMotherTongue': SCHAC+'1',
+ 'schacPersonalPosition': SCHAC+'13',
+ 'schacPersonalTitle': SCHAC+'8',
+ 'schacPersonalUniqueCode': SCHAC+'14',
+ 'schacPersonalUniqueID': SCHAC+'15',
+ 'schacPlaceOfBirth': SCHAC+'4',
+ 'schacProjectMembership': SCHAC+'20',
+ 'schacProjectSpecificRole': SCHAC+'21',
+ 'schacSn1': SCHAC+'6',
+ 'schacSn2': SCHAC+'7',
+ 'schacUserPresenceID': SCHAC+'12',
+ 'schacUserPrivateAttribute': SCHAC+'18',
+ 'schacUserStatus': SCHAC+'19',
+ 'searchGuide': X500ATTR_OID+'14',
+ 'serialNumber': X500ATTR_OID+'5',
+ 'sisLegalGuardianFor': SIS+'1',
+ 'sisSchoolGrade': SIS+'2',
+ 'sn': X500ATTR_OID+'4',
+ 'st': X500ATTR_OID+'8',
+ 'street': X500ATTR_OID+'9',
+ 'supportedAlgorithms': X500ATTR_OID+'52',
+ 'supportedApplicationContext': X500ATTR_OID+'30',
+ 'telephoneNumber': X500ATTR_OID+'20',
+ 'teletexTerminalIdentifier': X500ATTR_OID+'22',
+ 'telexNumber': X500ATTR_OID+'21',
+ 'title': X500ATTR_OID+'12',
+ 'uid': UCL_DIR_PILOT+'1',
+ 'uniqueMember': X500ATTR_OID+'50',
+ 'userCertificate': X500ATTR_OID+'36',
+ 'userPKCS12': NETSCAPE_LDAP+'216',
+ 'userSMIMECertificate': NETSCAPE_LDAP+'40',
+ 'x121Address': X500ATTR_OID+'24',
+ 'x500UniqueIdentifier': X500ATTR_OID+'45',
+ }
+}
diff --git a/backend/attribute-maps/shibboleth_uri.py b/backend/attribute-maps/shibboleth_uri.py
new file mode 100644
index 0000000..54de473
--- /dev/null
+++ b/backend/attribute-maps/shibboleth_uri.py
@@ -0,0 +1,197 @@
+EDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.5923.1.1.1.'
+NETSCAPE_LDAP = 'urn:oid:2.16.840.1.113730.3.1.'
+NOREDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.2428.90.1.'
+PKCS_9 = 'urn:oid:1.2.840.113549.1.9.'
+UCL_DIR_PILOT = 'urn:oid:0.9.2342.19200300.100.1.'
+UMICH = 'urn:oid:1.3.6.1.4.1.250.1.57.'
+X500ATTR = 'urn:oid:2.5.4.'
+
+
+MAP = {
+ "identifier": "urn:mace:shibboleth:1.0:attributeNamespace:uri",
+ 'fro': {
+ EDUPERSON_OID+'1': 'eduPersonAffiliation',
+ EDUPERSON_OID+'2': 'eduPersonNickname',
+ EDUPERSON_OID+'3': 'eduPersonOrgDN',
+ EDUPERSON_OID+'4': 'eduPersonOrgUnitDN',
+ EDUPERSON_OID+'5': 'eduPersonPrimaryAffiliation',
+ EDUPERSON_OID+'6': 'eduPersonPrincipalName',
+ EDUPERSON_OID+'7': 'eduPersonEntitlement',
+ EDUPERSON_OID+'8': 'eduPersonPrimaryOrgUnitDN',
+ EDUPERSON_OID+'9': 'eduPersonScopedAffiliation',
+ EDUPERSON_OID+'10': 'eduPersonTargetedID',
+ EDUPERSON_OID+'11': 'eduPersonAssurance',
+ EDUPERSON_OID+'12': 'eduPersonPrincipalNamePrior',
+ EDUPERSON_OID+'13': 'eduPersonUniqueId',
+ EDUPERSON_OID+'16': 'eduPersonOrcid',
+ NETSCAPE_LDAP+'1': 'carLicense',
+ NETSCAPE_LDAP+'2': 'departmentNumber',
+ NETSCAPE_LDAP+'3': 'employeeNumber',
+ NETSCAPE_LDAP+'4': 'employeeType',
+ NETSCAPE_LDAP+'39': 'preferredLanguage',
+ NETSCAPE_LDAP+'40': 'userSMIMECertificate',
+ NETSCAPE_LDAP+'216': 'userPKCS12',
+ NETSCAPE_LDAP+'241': 'displayName',
+ NOREDUPERSON_OID+'1': 'norEduOrgUniqueNumber',
+ NOREDUPERSON_OID+'2': 'norEduOrgUnitUniqueNumber',
+ NOREDUPERSON_OID+'3': 'norEduPersonBirthDate',
+ NOREDUPERSON_OID+'4': 'norEduPersonLIN',
+ NOREDUPERSON_OID+'5': 'norEduPersonNIN',
+ NOREDUPERSON_OID+'6': 'norEduOrgAcronym',
+ NOREDUPERSON_OID+'7': 'norEduOrgUniqueIdentifier',
+ NOREDUPERSON_OID+'8': 'norEduOrgUnitUniqueIdentifier',
+ NOREDUPERSON_OID+'9': 'federationFeideSchemaVersion',
+ PKCS_9+'1': 'email',
+ UCL_DIR_PILOT+'3': 'mail',
+ UCL_DIR_PILOT+'25': 'dc',
+ UCL_DIR_PILOT+'37': 'associatedDomain',
+ UCL_DIR_PILOT+'60': 'jpegPhoto',
+ X500ATTR+'2': 'knowledgeInformation',
+ X500ATTR+'4': 'sn',
+ X500ATTR+'5': 'serialNumber',
+ X500ATTR+'6': 'c',
+ X500ATTR+'7': 'l',
+ X500ATTR+'8': 'st',
+ X500ATTR+'9': 'street',
+ X500ATTR+'10': 'o',
+ X500ATTR+'11': 'ou',
+ X500ATTR+'12': 'title',
+ X500ATTR+'14': 'searchGuide',
+ X500ATTR+'15': 'businessCategory',
+ X500ATTR+'16': 'postalAddress',
+ X500ATTR+'17': 'postalCode',
+ X500ATTR+'18': 'postOfficeBox',
+ X500ATTR+'19': 'physicalDeliveryOfficeName',
+ X500ATTR+'20': 'telephoneNumber',
+ X500ATTR+'21': 'telexNumber',
+ X500ATTR+'22': 'teletexTerminalIdentifier',
+ X500ATTR+'23': 'facsimileTelephoneNumber',
+ X500ATTR+'24': 'x121Address',
+ X500ATTR+'25': 'internationaliSDNNumber',
+ X500ATTR+'26': 'registeredAddress',
+ X500ATTR+'27': 'destinationIndicator',
+ X500ATTR+'28': 'preferredDeliveryMethod',
+ X500ATTR+'29': 'presentationAddress',
+ X500ATTR+'30': 'supportedApplicationContext',
+ X500ATTR+'31': 'member',
+ X500ATTR+'32': 'owner',
+ X500ATTR+'33': 'roleOccupant',
+ X500ATTR+'36': 'userCertificate',
+ X500ATTR+'37': 'cACertificate',
+ X500ATTR+'38': 'authorityRevocationList',
+ X500ATTR+'39': 'certificateRevocationList',
+ X500ATTR+'40': 'crossCertificatePair',
+ X500ATTR+'42': 'givenName',
+ X500ATTR+'43': 'initials',
+ X500ATTR+'44': 'generationQualifier',
+ X500ATTR+'45': 'x500UniqueIdentifier',
+ X500ATTR+'46': 'dnQualifier',
+ X500ATTR+'47': 'enhancedSearchGuide',
+ X500ATTR+'48': 'protocolInformation',
+ X500ATTR+'50': 'uniqueMember',
+ X500ATTR+'51': 'houseIdentifier',
+ X500ATTR+'52': 'supportedAlgorithms',
+ X500ATTR+'53': 'deltaRevocationList',
+ X500ATTR+'54': 'dmdName',
+ X500ATTR+'65': 'pseudonym',
+ },
+ 'to': {
+ 'associatedDomain': UCL_DIR_PILOT+'37',
+ 'authorityRevocationList': X500ATTR+'38',
+ 'businessCategory': X500ATTR+'15',
+ 'c': X500ATTR+'6',
+ 'cACertificate': X500ATTR+'37',
+ 'carLicense': NETSCAPE_LDAP+'1',
+ 'certificateRevocationList': X500ATTR+'39',
+ 'countryName': X500ATTR+'6',
+ 'crossCertificatePair': X500ATTR+'40',
+ 'dc': UCL_DIR_PILOT+'25',
+ 'deltaRevocationList': X500ATTR+'53',
+ 'departmentNumber': NETSCAPE_LDAP+'2',
+ 'destinationIndicator': X500ATTR+'27',
+ 'displayName': NETSCAPE_LDAP+'241',
+ 'dmdName': X500ATTR+'54',
+ 'dnQualifier': X500ATTR+'46',
+ 'domainComponent': UCL_DIR_PILOT+'25',
+ 'eduPersonAffiliation': EDUPERSON_OID+'1',
+ 'eduPersonEntitlement': EDUPERSON_OID+'7',
+ 'eduPersonNickname': EDUPERSON_OID+'2',
+ 'eduPersonOrgDN': EDUPERSON_OID+'3',
+ 'eduPersonOrgUnitDN': EDUPERSON_OID+'4',
+ 'eduPersonPrimaryAffiliation': EDUPERSON_OID+'5',
+ 'eduPersonPrimaryOrgUnitDN': EDUPERSON_OID+'8',
+ 'eduPersonPrincipalName': EDUPERSON_OID+'6',
+ 'eduPersonPrincipalNamePrior': EDUPERSON_OID+'12',
+ 'eduPersonScopedAffiliation': EDUPERSON_OID+'9',
+ 'eduPersonTargetedID': EDUPERSON_OID+'10',
+ 'eduPersonAssurance': EDUPERSON_OID+'11',
+ 'eduPersonUniqueId': EDUPERSON_OID+'13',
+ 'eduPersonOrcid': EDUPERSON_OID+'16',
+ 'email': PKCS_9+'1',
+ 'emailAddress': PKCS_9+'1',
+ 'employeeNumber': NETSCAPE_LDAP+'3',
+ 'employeeType': NETSCAPE_LDAP+'4',
+ 'enhancedSearchGuide': X500ATTR+'47',
+ 'facsimileTelephoneNumber': X500ATTR+'23',
+ 'fax': X500ATTR+'23',
+ 'federationFeideSchemaVersion': NOREDUPERSON_OID+'9',
+ 'generationQualifier': X500ATTR+'44',
+ 'givenName': X500ATTR+'42',
+ 'gn': X500ATTR+'42',
+ 'houseIdentifier': X500ATTR+'51',
+ 'initials': X500ATTR+'43',
+ 'internationaliSDNNumber': X500ATTR+'25',
+ 'jpegPhoto': UCL_DIR_PILOT+'60',
+ 'knowledgeInformation': X500ATTR+'2',
+ 'l': X500ATTR+'7',
+ 'localityName': X500ATTR+'7',
+ 'mail': UCL_DIR_PILOT+'3',
+ 'member': X500ATTR+'31',
+ 'norEduOrgAcronym': NOREDUPERSON_OID+'6',
+ 'norEduOrgUniqueIdentifier': NOREDUPERSON_OID+'7',
+ 'norEduOrgUniqueNumber': NOREDUPERSON_OID+'1',
+ 'norEduOrgUnitUniqueIdentifier': NOREDUPERSON_OID+'8',
+ 'norEduOrgUnitUniqueNumber': NOREDUPERSON_OID+'2',
+ 'norEduPersonBirthDate': NOREDUPERSON_OID+'3',
+ 'norEduPersonLIN': NOREDUPERSON_OID+'4',
+ 'norEduPersonNIN': NOREDUPERSON_OID+'5',
+ 'o': X500ATTR+'10',
+ 'organizationName': X500ATTR+'10',
+ 'organizationalUnitName': X500ATTR+'11',
+ 'ou': X500ATTR+'11',
+ 'owner': X500ATTR+'32',
+ 'physicalDeliveryOfficeName': X500ATTR+'19',
+ 'pkcs9email': PKCS_9+'1',
+ 'postOfficeBox': X500ATTR+'18',
+ 'postalAddress': X500ATTR+'16',
+ 'postalCode': X500ATTR+'17',
+ 'preferredDeliveryMethod': X500ATTR+'28',
+ 'preferredLanguage': NETSCAPE_LDAP+'39',
+ 'presentationAddress': X500ATTR+'29',
+ 'protocolInformation': X500ATTR+'48',
+ 'pseudonym': X500ATTR+'65',
+ 'registeredAddress': X500ATTR+'26',
+ 'rfc822Mailbox': UCL_DIR_PILOT+'3',
+ 'roleOccupant': X500ATTR+'33',
+ 'searchGuide': X500ATTR+'14',
+ 'serialNumber': X500ATTR+'5',
+ 'sn': X500ATTR+'4',
+ 'st': X500ATTR+'8',
+ 'stateOrProvinceName': X500ATTR+'8',
+ 'street': X500ATTR+'9',
+ 'streetAddress': X500ATTR+'9',
+ 'supportedAlgorithms': X500ATTR+'52',
+ 'supportedApplicationContext': X500ATTR+'30',
+ 'surname': X500ATTR+'4',
+ 'telephoneNumber': X500ATTR+'20',
+ 'teletexTerminalIdentifier': X500ATTR+'22',
+ 'telexNumber': X500ATTR+'21',
+ 'title': X500ATTR+'12',
+ 'uniqueMember': X500ATTR+'50',
+ 'userCertificate': X500ATTR+'36',
+ 'userPKCS12': NETSCAPE_LDAP+'216',
+ 'userSMIMECertificate': NETSCAPE_LDAP+'40',
+ 'x121Address': X500ATTR+'24',
+ 'x500UniqueIdentifier': X500ATTR+'45',
+ }
+}
diff --git a/backend/core/saml2.py b/backend/core/saml2.py
new file mode 100644
index 0000000..c1998b0
--- /dev/null
+++ b/backend/core/saml2.py
@@ -0,0 +1,40 @@
+import logging
+
+from django.contrib.auth.models import Group
+from djangosaml2.backends import Saml2Backend
+
+
+class ModifiedSaml2Backend(Saml2Backend):
+
+ def _update_user(self, user, attributes: dict, attribute_mapping: dict, force_save: bool = False):
+
+ log = logging.getLogger("saml")
+
+ log.debug("USER: ", user)
+ log.debug("ATTRIBUTES: ", attributes)
+
+ display_name = attributes.get('cn', [""])[0]
+
+ if display_name:
+ names = display_name.split()
+ user.first_name = names[0]
+ user.last_name = names[-1]
+ user.profile.display_name = display_name
+ user.save()
+
+ return super()._update_user(user, attributes, attribute_mapping, force_save)
+
+ def save_user(self, user, *args, **kwargs):
+ log = logging.getLogger("saml")
+ user.save()
+
+ try:
+ if not user.groups.filter(name="Saml2").exists():
+ group, _ = Group.objects.get_or_create(name="Saml2")
+ group.user_set.add(user)
+ group.save()
+ log.debug("Added user to Saml2 group")
+ except Exception as _er:
+ log.error("Failed on add user to group Saml2. Error: %s" % _er)
+
+ return super().save_user(user, *args, **kwargs)
diff --git a/backend/core/shibboleth.py b/backend/core/shibboleth.py
deleted file mode 100644
index b755521..0000000
--- a/backend/core/shibboleth.py
+++ /dev/null
@@ -1,62 +0,0 @@
-import logging
-
-from django.contrib.auth.models import Group
-from shibboleth.middleware import ShibbolethRemoteUserMiddleware
-
-
-class ShibbolethMiddleware(ShibbolethRemoteUserMiddleware):
- def make_profile(self, user, shib_meta):
- """
- This is here as a stub to allow subclassing of ShibbolethRemoteUserMiddleware
- to include a make_profile method that will create a Django user profile
- from the Shib provided attributes. By default it does nothing.
- """
- log = logging.getLogger("shibboleth")
- log.debug("Shib Meta:")
- log.debug(shib_meta)
-
- log.debug("User:")
- log.debug(user)
-
- # Guardar o email do usuario
- if shib_meta.get("email", None):
- user.email = shib_meta.get("email")
- log.debug("Updated user email")
-
- if shib_meta.get("first_name", None):
- fullname = shib_meta.get("first_name")
- user.first_name = fullname.split()[0]
- user.last_name = fullname.split()[-1]
-
- if user.profile.display_name != shib_meta.get("display_name", None):
- user.profile.display_name = shib_meta.get("display_name", user.username)
- log.debug("Added user profile display name")
- user.profile.save()
-
- # Adiciona um display name para o usuario
- if user.profile.display_name is None:
- user.profile.display_name = user.username
- user.profile.save()
-
- user.save()
-
- # Adicionar o usuario ao grupo Shibboleth
- try:
- if not user.groups.filter(name="Shibboleth").exists():
- group, created = Group.objects.get_or_create(name="Shibboleth")
- group.user_set.add(user)
- log.debug("Added user to Shibboleth group")
- except Exception as e:
- log.error("Failed on add user to group shibboleth. Error: %s" % e)
-
- return
-
- def setup_session(self, request):
- """
- If you want to add custom code to setup user sessions, you
- can extend this.
- """
- log = logging.getLogger("shibboleth")
- log.debug("---------- Setup Session ----------")
-
- return
diff --git a/backend/core/shibboleth_urls.py b/backend/core/shibboleth_urls.py
deleted file mode 100644
index 52c81ce..0000000
--- a/backend/core/shibboleth_urls.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import django
-from django.urls import re_path
-
-from shibboleth.views import ShibbolethView, ShibbolethLogoutView, ShibbolethLoginView
-
-app_name = "shibboleth"
-
-urlpatterns = [
- re_path(r"^login/$", ShibbolethLoginView.as_view(), name="login"),
- re_path(r"^logout/$", ShibbolethLogoutView.as_view(), name="logout"),
- re_path(r"^$", ShibbolethView.as_view(), name="info"),
-]
diff --git a/backend/pzserver/settings.py b/backend/pzserver/settings.py
index 2e4ae38..b2643c6 100644
--- a/backend/pzserver/settings.py
+++ b/backend/pzserver/settings.py
@@ -12,6 +12,10 @@
import os
+import saml2.saml
+
+import saml2
+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
# BASE_DIR = Path(__file__).resolve().parent.parent
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -37,7 +41,6 @@
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
- # "django.contrib.sites",
# Third-party
"corsheaders",
"django_filters",
@@ -48,7 +51,7 @@
"oauth2_provider",
"social_django",
"drf_social_oauth2",
- "shibboleth",
+ "djangosaml2",
# Apps
"core",
]
@@ -59,7 +62,6 @@
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
- "core.shibboleth.ShibbolethMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
@@ -114,7 +116,6 @@
{"NAME": f"{auth_pass_str}.NumericPasswordValidator"},
]
-
# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/
@@ -135,7 +136,6 @@
MEDIA_URL = "/archive/data/"
MEDIA_ROOT = "/archive/data/"
-
# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
@@ -162,6 +162,7 @@
"drf_social_oauth2.authentication.SocialAuthentication",
"rest_framework.authentication.TokenAuthentication",
"rest_framework.authentication.SessionAuthentication",
+ # 'djangosaml2.backends.Saml2Backend',
),
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
"DEFAULT_FILTER_BACKENDS": [
@@ -184,45 +185,18 @@
JSON_EDITOR = True
AUTHENTICATION_BACKENDS = (
- # "social_core.backends.github.GithubOAuth2",
- # "social_core.backends.github.GithubOrganizationOAuth2",
"drf_social_oauth2.backends.DjangoOAuth2",
"django.contrib.auth.backends.ModelBackend",
- "shibboleth.backends.ShibbolethRemoteUserBackend",
+ "core.saml2.ModifiedSaml2Backend",
)
-# if os.getenv("GITHUB_CLIENT_ID", None) is not None:
-# SOCIAL_AUTH_GITHUB_ORG_KEY = os.getenv("GITHUB_CLIENT_ID")
-# SOCIAL_AUTH_GITHUB_ORG_SECRET = os.getenv("GITHUB_CLIENT_SECRET")
-# SOCIAL_AUTH_GITHUB_ORG_NAME = os.getenv("GITHUB_ORG_NAME", "linea-it")
-# SOCIAL_AUTH_GITHUB_ORG_SCOPE = ["user:email", "read:org"]
-# SOCIAL_AUTH_JSONFIELD_ENABLED = True
-
ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS = True
LOGIN_REDIRECT_URL = "/"
-# Shibboleth Authentication
-SHIBBOLETH_ENABLED = False
-if os.getenv("AUTH_SHIB_URL", None) is not None:
- # https://github.com/Brown-University-Library/django-shibboleth-remoteuser
- SHIBBOLETH_ATTRIBUTE_MAP = {
- "eppn": (True, "username"),
- "cn": (False, "first_name"),
- "sn": (False, "display_name"),
- "Shib-inetOrgPerson-mail": (False, "email"),
- }
- SHIBBOLETH_GROUP_ATTRIBUTES = "Shibboleth"
- # Including Shibboleth authentication:
- AUTHENTICATION_BACKENDS += (
- "shibboleth.backends.ShibbolethRemoteUserBackend",)
-
- SHIBBOLETH_ENABLED = True
-
OAUTH2_PROVIDER = {
"ACCESS_TOKEN_EXPIRE_SECONDS": 36000,
}
-
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
@@ -254,10 +228,10 @@
"backupCount": 5,
"formatter": "standard",
},
- "shibboleth": {
+ "saml": {
"level": LOGGING_LEVEL,
"class": "logging.handlers.RotatingFileHandler",
- "filename": os.path.join(LOG_DIR, "shibboleth.log"),
+ "filename": os.path.join(LOG_DIR, "saml2.log"),
"maxBytes": 1024 * 1024 * 5, # 5 MB
"backupCount": 5,
"formatter": "standard",
@@ -287,8 +261,8 @@
"level": LOGGING_LEVEL,
"propagate": True,
},
- "shibboleth": {
- "handlers": ["shibboleth"],
+ "saml": {
+ "handlers": ["saml"],
"level": LOGGING_LEVEL,
"propagate": True,
},
@@ -299,3 +273,133 @@
},
},
}
+
+if os.getenv("AUTH_SHIB_URL", None):
+ FQDN = os.getenv("URI", "http://localhost")
+ CERT_DIR = "/saml2/certificates"
+ SIG_KEY_PEM = os.getenv("SIG_KEY_PEM", os.path.join(CERT_DIR, 'pzkey.pem'))
+ SIG_CERT_PEM = os.getenv("SIG_CERT_PEM", os.path.join(CERT_DIR, 'pzcert.pem'))
+ ENCRYP_KEY_PEM = os.getenv("ENCRYP_KEY_PEM", SIG_KEY_PEM)
+ ENCRYP_CERT_PEM = os.getenv("ENCRYP_CERT_PEM", SIG_CERT_PEM)
+
+ MIDDLEWARE.append('djangosaml2.middleware.SamlSessionMiddleware')
+
+ # configurações relativas ao session cookie
+ SAML_SESSION_COOKIE_NAME = 'saml_session'
+ SESSION_COOKIE_SECURE = True
+
+ # Qualquer view que requer um usuário autenticado deve redirecionar o navegador para esta url
+ LOGIN_URL = '/saml2/login/'
+
+ # Encerra a sessão quando o usuário fecha o navegador
+ SESSION_EXPIRE_AT_BROWSER_CLOSE = True
+
+ # Tipo de binding utilizado
+ SAML_DEFAULT_BINDING = saml2.BINDING_HTTP_POST
+ SAML_IGNORE_LOGOUT_ERRORS = True
+
+ # Serviço de descoberta da cafeexpresso
+ # SAML2_DISCO_URL = 'https://ds.cafeexpresso.rnp.br/WAYF.php'
+
+ # Cria usuário Django a partir da asserção SAML caso o mesmo não exista
+ SAML_CREATE_UNKNOWN_USER = True
+
+ # https://djangosaml2.readthedocs.io/contents/security.html#content-security-policy
+ SAML_CSP_HANDLER = ""
+
+ # URL para redirecionamento após a autenticação
+ LOGIN_REDIRECT_URL = '/'
+
+ SAML_ATTRIBUTE_MAPPING = {
+ "eduPersonPrincipalName": ("username",),
+ "sn": ("name",),
+ "cn": ("full_name",),
+ "email": ("email",)
+ }
+
+ SAML_CONFIG = {
+ # Biblioteca usada para assinatura e criptografia
+ 'xmlsec_binary': '/usr/bin/xmlsec1',
+ 'entityid': FQDN + '/saml2/metadata/',
+ # Diretório contendo os esquemas de mapeamento de atributo
+ 'attribute_map_dir': os.path.join(BASE_DIR, 'attribute-maps'),
+ 'description': 'SP Pz Server',
+ 'service': {
+ 'sp' : {
+ 'name': 'sp_pzserver',
+ 'ui_info': {
+ 'display_name': {'text':'SP Pz', 'lang':'en'},
+ 'description': {'text':'Pz Service Provider', 'lang':'en'},
+ 'information_url': {'text': f"{FQDN}/about", 'lang':'en'},
+ 'privacy_statement_url': {'text': FQDN, 'lang':'en'}
+ },
+ 'name_id_format': [
+ "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
+ "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
+ ],
+ # Indica os endpoints dos serviços fornecidos
+ 'endpoints': {
+ 'assertion_consumer_service': [
+ (FQDN +'/saml2/acs/',
+ saml2.BINDING_HTTP_POST),
+ ],
+ 'single_logout_service': [
+ (FQDN + '/saml2/ls/',
+ saml2.BINDING_HTTP_REDIRECT),
+ (FQDN + '/saml2/ls/post',
+ saml2.BINDING_HTTP_POST),
+ ],
+ },
+ # Algoritmos utilizados
+ #'signing_algorithm': saml2.xmldsig.SIG_RSA_SHA256,
+ #'digest_algorithm': saml2.xmldsig.DIGEST_SHA256,
+
+ 'force_authn': False,
+ 'name_id_format_allow_create': False,
+
+ # Indica que as respostas de autenticação para este SP devem ser assinadas
+ 'want_response_signed': True,
+
+ # Indica se as solicitações de autenticação enviadas por este SP devem ser assinadas
+ 'authn_requests_signed': True,
+
+ # Indica se este SP deseja que o IdP envie as asserções assinadas
+ 'want_assertions_signed': False,
+
+ 'only_use_keys_in_metadata': True,
+ 'allow_unsolicited': False,
+ },
+ },
+
+ # Indica onde os metadados podem ser encontrados
+ 'metadata': {
+ 'local': [os.getenv("IDP_METADATA")],
+ },
+
+ 'debug': os.getenv("DEBUG", 1),
+
+ # Signature
+ 'key_file': SIG_KEY_PEM, # private part
+ 'cert_file': SIG_CERT_PEM, # public part
+
+ # Encriptation
+ 'encryption_keypairs': [{
+ 'key_file': ENCRYP_KEY_PEM, # private part
+ 'cert_file': ENCRYP_CERT_PEM, # public part
+ }],
+
+ 'contact_person': [
+ {'given_name': 'LIneA',
+ 'sur_name': 'Team',
+ 'company': 'LIneA',
+ 'email_address': 'itteam@linea.org.br',
+ 'contact_type': 'technical'},
+ ],
+
+ # Descreve a organização responsável pelo serviço
+ 'organization': {
+ 'name': [('LIneA', 'pt-br')],
+ 'display_name': [('LIneA', 'pt-br')],
+ 'url': [('https://linea.org.br/', 'pt-br')],
+ },
+ }
\ No newline at end of file
diff --git a/backend/pzserver/urls.py b/backend/pzserver/urls.py
index 9bbc18f..751f3c0 100644
--- a/backend/pzserver/urls.py
+++ b/backend/pzserver/urls.py
@@ -14,25 +14,14 @@
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
# from core.api import viewsets as products_viewsets
-from core.views import (
- CsrfToOauth,
- GetToken,
- LoggedUserView,
- Logout,
- ProductContentViewSet,
- ProductFileViewSet,
- ProductTypeViewSet,
- ProductViewSet,
- ReleaseViewSet,
- UserViewSet,
-)
+from core.views import (CsrfToOauth, GetToken, LoggedUserView, Logout,
+ ProductContentViewSet, ProductFileViewSet,
+ ProductTypeViewSet, ProductViewSet, ReleaseViewSet,
+ UserViewSet)
from django.contrib import admin
from django.urls import include, path
-from drf_spectacular.views import (
- SpectacularAPIView,
- SpectacularRedocView,
- SpectacularSwaggerView,
-)
+from drf_spectacular.views import (SpectacularAPIView, SpectacularRedocView,
+ SpectacularSwaggerView)
from rest_framework import routers
route = routers.DefaultRouter()
@@ -57,7 +46,6 @@
path("api/csrf_oauth/", CsrfToOauth.as_view()),
path("api/logged_user/", LoggedUserView.as_view(), name="logged_user"),
path("api/logout/", Logout.as_view(), name="logout"),
- path("api/shib/", include("core.shibboleth_urls", namespace="shibboleth")),
# API DOCs
path("api/schema/", SpectacularAPIView.as_view(), name="schema"),
path(
@@ -66,4 +54,5 @@
name="swagger",
),
path("api/redoc/", SpectacularRedocView.as_view(url_name="schema"), name="redoc"),
+ path(r"saml2/", include('djangosaml2.urls')),
]
diff --git a/backend/requirements.txt b/backend/requirements.txt
index b785cb4..0dd48f8 100644
--- a/backend/requirements.txt
+++ b/backend/requirements.txt
@@ -5,6 +5,8 @@ django-cors-headers==4.3.1
django-filebrowser-no-grappelli==4.0.2
django-filter==24.2
django-oauth-toolkit==2.3.0
+djangosaml2==1.9.3
+xmlsec==1.3.14
django-shibboleth-remoteuser==0.12
djangorestframework==3.15.1
drf-social-oauth2==2.2.0
diff --git a/docker-compose-development.yml b/docker-compose-development.yml
index 3696fdd..734e43a 100644
--- a/docker-compose-development.yml
+++ b/docker-compose-development.yml
@@ -27,6 +27,7 @@ services:
- ./backend:/app
- ./archive/log/backend:/archive/log
- ./archive/data:/archive/data
+ # - ./saml2:/saml2 # uncomment if authentication with github is required
depends_on:
- database
diff --git a/env_template b/env_template
index 37e913f..6e44ba0 100644
--- a/env_template
+++ b/env_template
@@ -1,4 +1,4 @@
-# Postgres
+# Postgres
POSTGRES_USER=pzadmin
POSTGRES_PASSWORD=adminpz
POSTGRES_DB=pzdev
@@ -14,7 +14,7 @@ POSTGRES_DB=pzdev
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG=1
LOGGING_LEVEL=DEBUG
-# AUTORELOAD: Select 1 to enable auto reload and 0 to turn off. In production we must
+# AUTORELOAD: Select 1 to enable auto reload and 0 to turn off. In production we must
# disable it.
AUTORELOAD=1
# SECURITY WARNING: keep the secret key used in production secret!
@@ -28,9 +28,13 @@ DB_DATABASE=pzdev
DB_HOST=database
DB_PORT=5432
+# URI
+DOMAIN=localhost
+URI=http://${DOMAIN}
+
# CORS
-DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
-DJANGO_CSRF_TRUSTED_ORIGINS=http://localhost http://127.0.0.1
+DJANGO_ALLOWED_HOSTS=${DOMAIN} 127.0.0.1 [::1]
+DJANGO_CSRF_TRUSTED_ORIGINS=${URI} http://127.0.0.1
# Frontend
# Client ID e Client Secret devem ser cadastradas no Django Admin
@@ -38,13 +42,15 @@ DJANGO_CSRF_TRUSTED_ORIGINS=http://localhost http://127.0.0.1
# DJANGO_OAUTH_CLIENT_ID=
# DJANGO_OAUTH_CLIENT_SECRET=
-# Github OAuth
-# To enable Github OAuth authentication,
-# uncomment and fill in the following variables.
-#GITHUB_CLIENT_ID=
-#GITHUB_CLIENT_SECRET=
-#GITHUB_ORG_NAME=linea-it
+# Saml2 / Satosa Auth
+# URL to login using satosa
+# AUTH_SHIB_URL=${URI}/saml2/login/
+
+# Keys and Certificates
+# SIG_KEY_PEM=
+# SIG_CERT_PEM=
+# ENCRYP_KEY_PEM=
+# ENCRYP_CERT_PEM=
-# Shibboleth / Satosa Auth
-# Url para login utilizando Shibboleth
-# AUTH_SHIB_URL=
\ No newline at end of file
+# IDP metadata
+# IDP_METADATA=
\ No newline at end of file
diff --git a/nginx_development.conf b/nginx_development.conf
index 49d0f9c..1e75522 100644
--- a/nginx_development.conf
+++ b/nginx_development.conf
@@ -57,6 +57,11 @@ server {
uwsgi_pass pzapi;
}
+ location /saml2 {
+ include uwsgi_params;
+ uwsgi_pass pzapi;
+ }
+
location /admin {
include uwsgi_params;
uwsgi_pass pzapi;
diff --git a/nginx_production.conf b/nginx_production.conf
index a5a45af..8e02101 100644
--- a/nginx_production.conf
+++ b/nginx_production.conf
@@ -6,11 +6,6 @@ upstream pzfrontend {
server frontend:3000;
}
-upstream shibserver {
- ip_hash;
- server gidlab:80;
-}
-
server {
@@ -69,23 +64,9 @@ server {
autoindex off;
}
- # Shibboleth
- location /Shibboleth.sso/ {
- proxy_pass http://shibserver$request_uri;
- proxy_set_header Host $host;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Host $server_name;
- proxy_set_header X-Real-IP $remote_addr;
- }
-
- # Shibboleth middleware
- location /api/shib/ {
- proxy_pass http://shibserver$request_uri;
- proxy_set_header Host $host;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Host $server_name;
- proxy_set_header X-Real-IP $remote_addr;
+ location /saml2 {
+ include uwsgi_params;
+ uwsgi_pass pzapi;
}
-
}