provider/samlv2: more samlv2 progres
This commit is contained in:
		| @ -3,6 +3,11 @@ NS_SAML_PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol" | ||||
| NS_SAML_ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion" | ||||
| NS_SIGNATURE = "http://www.w3.org/2000/09/xmldsig#" | ||||
|  | ||||
| REQ_KEY_REQUEST = "SAMLRequest" | ||||
| REQ_KEY_SIGNATURE = "Signature" | ||||
|  | ||||
| SESSION_KEY = "passbook_saml_request" | ||||
|  | ||||
| SAML_ATTRIB_ACS_URL = "AssertionConsumerServiceURL" | ||||
| SAML_ATTRIB_DESTINATION = "Destination" | ||||
| SAML_ATTRIB_ID = "ID" | ||||
|  | ||||
							
								
								
									
										5
									
								
								passbook/providers/samlv2/saml/provider.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								passbook/providers/samlv2/saml/provider.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| """SAML Provider logic""" | ||||
|  | ||||
|  | ||||
| class SAMLProvider: | ||||
|     """SAML Provider""" | ||||
| @ -1,31 +1,34 @@ | ||||
| """passbook samlv2 URLs""" | ||||
| from django.urls import path | ||||
|  | ||||
| from passbook.providers.samlv2.views import idp_initiated, slo, sso | ||||
| from passbook.providers.samlv2.views import authorize, idp_initiated, slo, sso | ||||
|  | ||||
| urlpatterns = [ | ||||
|     path( | ||||
|         "<slug:application>/sso/redirect/", | ||||
|         "<slug:app_slug>/authorize/", | ||||
|         authorize.AuthorizeView.as_view(), | ||||
|         name="authorize", | ||||
|     ), | ||||
|     path( | ||||
|         "<slug:app_slug>/sso/redirect/", | ||||
|         sso.SAMLRedirectBindingView.as_view(), | ||||
|         name="sso-redirect", | ||||
|     ), | ||||
|     path( | ||||
|         "<slug:application>/sso/post/", | ||||
|         sso.SAMLPostBindingView.as_view(), | ||||
|         name="sso-post", | ||||
|         "<slug:app_slug>/sso/post/", sso.SAMLPostBindingView.as_view(), name="sso-post", | ||||
|     ), | ||||
|     path( | ||||
|         "<slug:application>/slo/redirect/", | ||||
|         "<slug:app_slug>/slo/redirect/", | ||||
|         slo.SAMLRedirectBindingView.as_view(), | ||||
|         name="slo-redirect", | ||||
|     ), | ||||
|     path( | ||||
|         "<slug:application>/slo/redirect/", | ||||
|         "<slug:app_slug>/slo/redirect/", | ||||
|         slo.SAMLPostBindingView.as_view(), | ||||
|         name="slo-post", | ||||
|     ), | ||||
|     path( | ||||
|         "<slug:application>/initiate/", | ||||
|         "<slug:app_slug>/initiate/", | ||||
|         idp_initiated.IDPInitiatedView.as_view(), | ||||
|         name="initiate", | ||||
|     ), | ||||
|  | ||||
							
								
								
									
										6
									
								
								passbook/providers/samlv2/views/authorize.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								passbook/providers/samlv2/views/authorize.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| """SAML Provider authorization view""" | ||||
| from django.views.generic import FormView | ||||
|  | ||||
|  | ||||
| class AuthorizeView(FormView): | ||||
|     """Authorization view""" | ||||
							
								
								
									
										31
									
								
								passbook/providers/samlv2/views/base.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								passbook/providers/samlv2/views/base.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| """SAML base views""" | ||||
| from typing import Optional | ||||
|  | ||||
| from django.http import HttpRequest, HttpResponse | ||||
| from django.shortcuts import get_object_or_404 | ||||
| from django.views import View | ||||
|  | ||||
| from passbook.core.models import Application | ||||
| from passbook.core.views.access import AccessMixin | ||||
| from passbook.providers.samlv2.saml.constants import SESSION_KEY | ||||
| from passbook.providers.samlv2.saml.parser import SAMLRequest | ||||
|  | ||||
|  | ||||
| class BaseSAMLView(AccessMixin, View): | ||||
|     """Base SAML View to resolve app_slug""" | ||||
|  | ||||
|     application: Application | ||||
|  | ||||
|     def setup(self, request: HttpRequest, *args, **kwargs): | ||||
|         View.setup(self, request, *args, **kwargs) | ||||
|         self.application = self.get_application(self.kwargs.get("app_slug")) | ||||
|  | ||||
|     def get_application(self, app_slug: str) -> Optional[Application]: | ||||
|         """Return application or raise 404""" | ||||
|         return get_object_or_404(Application, slug=app_slug) | ||||
|  | ||||
|     def handle_saml_request(self, request: SAMLRequest) -> HttpResponse: | ||||
|         """Handle SAML Request""" | ||||
|         self.request.SESSION[SESSION_KEY] = request | ||||
|         if self.application.skip_authorization: | ||||
|             pass | ||||
| @ -1,10 +1,41 @@ | ||||
| """Single Signon Views""" | ||||
| from django.views import View | ||||
| from django.http import HttpRequest, HttpResponse, HttpResponseBadRequest | ||||
|  | ||||
| from passbook.providers.samlv2.saml.constants import REQ_KEY_REQUEST, REQ_KEY_SIGNATURE | ||||
| from passbook.providers.samlv2.saml.parser import SAMLRequest | ||||
| from passbook.providers.samlv2.views.base import BaseSAMLView | ||||
|  | ||||
| # SAML Authentication flow in passbook | ||||
| # - Parse and Verify SAML Request | ||||
| # - Check access to application (this is done after parsing as it might take a few seconds) | ||||
| # - Ask for user authorization (if required from Application) | ||||
| # - Log Access to audit log | ||||
| # - Create response with unique ID to protect against replay | ||||
|  | ||||
|  | ||||
| class SAMLPostBindingView(View): | ||||
| class SAMLPostBindingView(BaseSAMLView): | ||||
|     """Handle SAML POST-type Requests""" | ||||
|  | ||||
|     # pylint: disable=unused-argument | ||||
|     def post(self, request: HttpRequest, app_slug: str) -> HttpResponse: | ||||
|         """Handle POST Requests""" | ||||
|         if REQ_KEY_REQUEST not in request.POST: | ||||
|             return HttpResponseBadRequest() | ||||
|         raw_saml_request = request.POST.get(REQ_KEY_REQUEST) | ||||
|         detached_signature = request.POST.get(REQ_KEY_SIGNATURE, None) | ||||
|         srq = SAMLRequest.parse(raw_saml_request, detached_signature) | ||||
|         return self.handle_saml_request(srq) | ||||
|  | ||||
| class SAMLRedirectBindingView(View): | ||||
|  | ||||
| class SAMLRedirectBindingView(BaseSAMLView): | ||||
|     """Handle SAML Redirect-type Requests""" | ||||
|  | ||||
|     # pylint: disable=unused-argument | ||||
|     def get(self, request: HttpRequest, app_slug: str) -> HttpResponse: | ||||
|         """Handle GET Requests""" | ||||
|         if REQ_KEY_REQUEST not in request.GET: | ||||
|             return HttpResponseBadRequest() | ||||
|         raw_saml_request = request.GET.get(REQ_KEY_REQUEST) | ||||
|         detached_signature = request.GET.get(REQ_KEY_SIGNATURE, None) | ||||
|         srq = SAMLRequest.parse(raw_saml_request, detached_signature) | ||||
|         return self.handle_saml_request(srq) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer