Ejemplo n.º 1
0
    def disco_query(self, context, internal_req):
        """
        Makes a request to the discovery server

        :type context: satosa.context.Context
        :type internal_req: satosa.internal_data.InternalRequest
        :rtype: satosa.response.SeeOther

        :param context: The current context
        :param internal_req: The request
        :return: Response
        """
        state = context.state

        _cli = self.sp

        eid = _cli.config.entityid
        # returns list of 2-tuples
        disco_resp = _cli.config.getattr("endpoints",
                                         "sp")["discovery_response"]
        # The first value of the first tuple is the one I want
        ret = disco_resp[0][0]
        loc = _cli.create_discovery_service_request(self.discosrv, eid,
                                                    **{"return": ret})
        return SeeOther(loc)
Ejemplo n.º 2
0
    def disco_query(self, context):
        """
        Makes a request to the discovery server

        :type context: satosa.context.Context
        :type internal_req: satosa.internal.InternalData
        :rtype: satosa.response.SeeOther

        :param context: The current context
        :param internal_req: The request
        :return: Response
        """
        endpoints = self.sp.config.getattr("endpoints", "sp")
        return_url = endpoints["discovery_response"][0][0]

        disco_url = (context.get_decoration(
            SAMLBackend.KEY_SAML_DISCOVERY_SERVICE_URL) or self.discosrv)
        disco_policy = context.get_decoration(
            SAMLBackend.KEY_SAML_DISCOVERY_SERVICE_POLICY)

        args = {"return": return_url}
        if disco_policy:
            args["policy"] = disco_policy

        loc = self.sp.create_discovery_service_request(disco_url,
                                                       self.sp.config.entityid,
                                                       **args)
        return SeeOther(loc)
Ejemplo n.º 3
0
    def disco_query(self):
        """
        Makes a request to the discovery server

        :type context: satosa.context.Context
        :type internal_req: satosa.internal.InternalData
        :rtype: satosa.response.SeeOther

        :param context: The current context
        :param internal_req: The request
        :return: Response
        """
        return_url = self.sp.config.getattr("endpoints", "sp")["discovery_response"][0][0]
        loc = self.sp.create_discovery_service_request(self.discosrv, self.sp.config.entityid, **{"return": return_url})
        return SeeOther(loc)
Ejemplo n.º 4
0
    def handle_authn_response(self, context, internal_resp):
        auth_req = self._get_authn_request_from_state(context.state)
        affiliation_attribute = self.converter.from_internal(
            'openid', internal_resp.attributes)['affiliation']
        scope = auth_req['scope']
        matching_affiliation = get_matching_affiliation(
            scope, affiliation_attribute)

        if matching_affiliation:
            return super().handle_authn_response(
                context, internal_resp,
                {'auth_time': internal_resp.auth_info.timestamp})

        auth_error = AuthorizationErrorResponse(error='access_denied')
        del context.state[self.name]
        http_response = auth_error.request(auth_req['redirect_uri'],
                                           should_fragment_encode(auth_req))
        return SeeOther(http_response)
Ejemplo n.º 5
0
    def handle_authn_response(self, context, internal_resp):
        auth_req = self._get_authn_request_from_state(context.state)
        # User might not give us consent to release affiliation
        if 'affiliation' in internal_resp.attributes:
            affiliation_attribute = self.converter.from_internal('openid', internal_resp.attributes)['affiliation']
            scope = auth_req['scope']
            matching_affiliation = get_matching_affiliation(scope, affiliation_attribute)

            if matching_affiliation:
                return super().handle_authn_response(context, internal_resp,
                                                     {'auth_time': internal_resp.auth_info.timestamp,
                                                      'requested_scopes': {'values': scope}})
        # User's affiliation was not released or was not the one requested so return an error
        # If the client sent us a state parameter, we should reflect it back according to the spec
        if 'state' in auth_req:
            auth_error = AuthorizationErrorResponse(error='access_denied', state=auth_req['state'])
        else:
            auth_error = AuthorizationErrorResponse(error='access_denied')
        del context.state[self.name]
        http_response = auth_error.request(auth_req['redirect_uri'], should_fragment_encode(auth_req))
        return SeeOther(http_response)
Ejemplo n.º 6
0
    def handle_authn_response(self, context, internal_resp):
        auth_req = self._get_authn_request_from_state(context.state)
        resp_rp = auth_req.get('client_id')

        # User might not give us consent to release affiliation
        if 'affiliation' in internal_resp.attributes:
            affiliation_attribute = self.converter.from_internal('openid', internal_resp.attributes)['affiliation']
            scope = auth_req['scope']
            matching_affiliation = get_matching_affiliation(scope, affiliation_attribute)

            if matching_affiliation:
                transaction_log(context.state, self.config.get("response_exit_order", 1200),
                        "inacademia_frontend", "response", "exit", "success", resp_rp , '', 'Responding successful validation to RP')

                return super().handle_authn_response(context, internal_resp,
                                                     {'auth_time': parser.parse(internal_resp.auth_info.timestamp).timestamp(),
                                                      'requested_scopes': {'values': scope}})

        # User's affiliation was not released or was not the one requested so return an error
        # If the client sent us a state parameter, we should reflect it back according to the spec
        transaction_log(context.state, self.config.get("response_exit_order", 1210),
                        "inacademia_frontend", "response", "exit", "failed", resp_rp, '',
                        ErrorDescription.REQUESTED_AFFILIATION_MISMATCH[LOG_MSG])

        if 'state' in auth_req:
            auth_error = AuthorizationErrorResponse(error='access_denied', state=auth_req['state'],
                                                    error_description=ErrorDescription.REQUESTED_AFFILIATION_MISMATCH[
                                                        ERROR_DESC])
        else:
            auth_error = AuthorizationErrorResponse(error='access_denied',
                                                    error_description=ErrorDescription.REQUESTED_AFFILIATION_MISMATCH[
                                                        ERROR_DESC])
        del context.state[self.name]
        http_response = auth_error.request(auth_req['redirect_uri'], should_fragment_encode(auth_req))

        return SeeOther(http_response)
Ejemplo n.º 7
0
    def authn_request(self, context, entity_id, internal_req):
        """
        Do an authorization request on idp with given entity id.
        This is the start of the authorization.

        :type context: satosa.context.Context
        :type entity_id: str
        :type internal_req: satosa.internal_data.InternalRequest
        :rtype: satosa.response.Response

        :param context: The curretn context
        :param entity_id: Target IDP entity id
        :param internal_req: The request
        :return: Response
        """
        _cli = self.sp
        hash_type = UserIdHashType.persistent.name
        if "hash_type" in self.config:
            hash_type = self.config["hash_type"]
        req_args = {"name_id_policy": self.create_name_id_policy(hash_type)}

        state = context.state

        try:
            # Picks a binding to use for sending the Request to the IDP
            _binding, destination = _cli.pick_binding("single_sign_on_service",
                                                      self.bindings,
                                                      "idpsso",
                                                      entity_id=entity_id)
            satosa_logging(
                LOGGER, logging.DEBUG,
                "binding: %s, destination: %s" % (_binding, destination),
                state)
            # Binding here is the response binding that is which binding the
            # IDP should use to return the response.
            acs = _cli.config.getattr("endpoints",
                                      "sp")["assertion_consumer_service"]
            # just pick one
            endp, return_binding = acs[0]
            req_id, req = _cli.create_authn_request(destination,
                                                    binding=return_binding,
                                                    **req_args)
            relay_state = rndstr()
            ht_args = _cli.apply_binding(_binding,
                                         "%s" % req,
                                         destination,
                                         relay_state=relay_state)
            satosa_logging(LOGGER, logging.DEBUG, "ht_args: %s" % ht_args,
                           state)
        except Exception as exc:
            satosa_logging(LOGGER,
                           logging.DEBUG,
                           "Failed to construct the AuthnRequest for state",
                           state,
                           exc_info=True)
            raise SATOSAAuthenticationError(
                state, "Failed to construct the AuthnRequest") from exc

        state.add(self.state_id, relay_state)

        if _binding == BINDING_HTTP_REDIRECT:
            for param, value in ht_args["headers"]:
                if param == "Location":
                    resp = SeeOther(str(value))
                    break
            else:
                satosa_logging(LOGGER, logging.DEBUG,
                               "Parameter error for state", state)
                raise SATOSAAuthenticationError(state, "Parameter error")
        else:
            resp = Response(ht_args["data"], headers=ht_args["headers"])

        return resp