def get(self, request: HttpRequest, source_slug: str) -> HttpResponse: """Replies with an XHTML SSO Request.""" source: SAMLSource = get_object_or_404(SAMLSource, slug=source_slug) if not source.enabled: raise Http404 relay_state = request.GET.get("next", "") auth_n_req = RequestProcessor(source, request, relay_state) # If the source is configured for Redirect bindings, we can just redirect there if source.binding_type == SAMLBindingTypes.REDIRECT: # Parse the initial SSO URL sso_url = urlparse(source.sso_url) # Parse the querystring into a dict... url_kwargs = dict(parse_qsl(sso_url.query)) # ... and update it with the SAML args url_kwargs.update(auth_n_req.build_auth_n_detached()) # Encode it back into a string res = ParseResult( scheme=sso_url.scheme, netloc=sso_url.netloc, path=sso_url.path, params=sso_url.params, query=urlencode(url_kwargs), fragment=sso_url.fragment, ) # and merge it back into a URL final_url = urlunparse(res) return redirect(final_url) # As POST Binding we show a form try: saml_request = nice64(auth_n_req.build_auth_n()) except InternalError as exc: LOGGER.warning(str(exc)) return bad_request_message(request, str(exc)) injected_stages = [] plan_kwargs = { PLAN_CONTEXT_TITLE: _("Redirecting to %(app)s..." % {"app": source.name}), PLAN_CONTEXT_CONSENT_TITLE: _("Redirecting to %(app)s..." % {"app": source.name}), PLAN_CONTEXT_ATTRS: { "SAMLRequest": saml_request, "RelayState": relay_state, }, PLAN_CONTEXT_URL: source.sso_url, } # For just POST we add a consent stage, # otherwise we default to POST_AUTO, with direct redirect if source.binding_type == SAMLBindingTypes.POST: injected_stages.append(in_memory_stage(ConsentStageView)) plan_kwargs[ PLAN_CONTEXT_CONSENT_HEADER] = f"Continue to {source.name}" injected_stages.append(in_memory_stage(AutosubmitStageView)) return self.handle_login_flow( source, *injected_stages, **plan_kwargs, )
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: application: Application = self.executor.plan.context[ PLAN_CONTEXT_APPLICATION] provider: SAMLProvider = get_object_or_404(SAMLProvider, pk=application.provider_id) if SESSION_KEY_AUTH_N_REQUEST not in self.request.session: return self.executor.stage_invalid() auth_n_request: AuthNRequest = self.request.session.pop( SESSION_KEY_AUTH_N_REQUEST) try: response = AssertionProcessor(provider, request, auth_n_request).build_response() except SAMLException as exc: Event.new( EventAction.CONFIGURATION_ERROR, message=f"Failed to process SAML assertion: {str(exc)}", provider=provider, ).from_http(self.request) return self.executor.stage_invalid() # Log Application Authorization Event.new( EventAction.AUTHORIZE_APPLICATION, authorized_application=application, flow=self.executor.plan.flow_pk, ).from_http(self.request) if provider.sp_binding == SAMLBindings.POST: form_attrs = { "ACSUrl": provider.acs_url, REQUEST_KEY_SAML_RESPONSE: nice64(response), } if auth_n_request.relay_state: form_attrs[ REQUEST_KEY_RELAY_STATE] = auth_n_request.relay_state return super().get( self.request, **{ "type": ChallengeTypes.NATIVE.value, "component": "ak-stage-autosubmit", "title": "Redirecting to %(app)s..." % { "app": application.name }, "url": provider.acs_url, "attrs": form_attrs, }, ) if provider.sp_binding == SAMLBindings.REDIRECT: url_args = { REQUEST_KEY_SAML_RESPONSE: deflate_and_base64_encode(response), } if auth_n_request.relay_state: url_args[REQUEST_KEY_RELAY_STATE] = auth_n_request.relay_state querystring = urlencode(url_args) return redirect(f"{provider.acs_url}?{querystring}") return bad_request_message(request, "Invalid sp_binding specified")
def get(self, request: HttpRequest, source_slug: str) -> HttpResponse: """Replies with an XHTML SSO Request.""" source: SAMLSource = get_object_or_404(SAMLSource, slug=source_slug) if not source.enabled: raise Http404 relay_state = request.GET.get("next", "") auth_n_req = RequestProcessor(source, request, relay_state) # If the source is configured for Redirect bindings, we can just redirect there if source.binding_type == SAMLBindingTypes.REDIRECT: url_args = urlencode(auth_n_req.build_auth_n_detached()) return redirect(f"{source.sso_url}?{url_args}") # As POST Binding we show a form saml_request = nice64(auth_n_req.build_auth_n()) injected_stages = [] plan_kwargs = { PLAN_CONTEXT_TITLE: _("Redirecting to %(app)s..." % {"app": source.name}), PLAN_CONTEXT_CONSENT_TITLE: _( "Redirecting to %(app)s..." % {"app": source.name} ), PLAN_CONTEXT_ATTRS: { "SAMLRequest": saml_request, "RelayState": relay_state, }, PLAN_CONTEXT_URL: source.sso_url, } # For just POST we add a consent stage, # otherwise we default to POST_AUTO, with direct redirect if source.binding_type == SAMLBindingTypes.POST: injected_stages.append(in_memory_stage(ConsentStageView)) plan_kwargs[PLAN_CONTEXT_CONSENT_HEADER] = f"Continue to {source.name}" injected_stages.append(in_memory_stage(AutosubmitStageView)) return self.handle_login_flow( source, *injected_stages, **plan_kwargs, )