Пример #1
0
    def id_token(self, released_claims, idp_entity_id, transaction_id, transaction_session):
        """Make a JWT encoded id token and pass it to the redirect URI.

        :param released_claims: dictionary containing the following
            user_id: identifier for the user (as delivered by the IdP, dependent on whether transient or persistent
                        id was requested)
            auth_time: time of the authentication reported from the IdP
            idp_entity_id: entity id of the selected IdP
        :param transaction_id:
        :return: raises cherrypy.HTTPRedirect.
        """

        identifier = released_claims["Identifier"]
        auth_time = released_claims["Authentication time"]

        # have to convert text representation into seconds since epoch
        _time = time.mktime(str_to_time(auth_time))

        # construct the OIDC response
        transaction_session["sub"] = identifier

        extra_claims = {k.lower(): released_claims[k] for k in ["Country", "Domain"] if k in released_claims}
        _jwt = self.OP.id_token_as_signed_jwt(transaction_session, loa="", auth_time=_time, exp={"minutes": 30},
                                              extra_claims=extra_claims)

        _elapsed_transaction_time = get_timestamp() - transaction_session["start_time"]
        log_transaction_complete(logger, cherrypy.request, transaction_id,
                                 transaction_session["client_id"],
                                 idp_entity_id, _time, _elapsed_transaction_time,
                                 extra_claims, _jwt)

        try:
            _state = transaction_session["state"]
        except KeyError:
            _state = None
        authzresp = AuthorizationResponse(state=_state, id_token=_jwt)

        if "redirect_uri" in transaction_session:
            _ruri = transaction_session["redirect_uri"]
        else:
            _error_msg = _("We could not complete your validation because an error occurred while "
                           "handling your request. Please return to the service which initiated the "
                           "validation request and try again.")
            try:
                cinfo = self.OP.cdb[transaction_session["client_id"]]
                _ruri = cinfo["redirect_uris"][0]
            except KeyError as e:
                abort_with_enduser_error(transaction_id, transaction_session["client_id"], cherrypy.request, logger,
                                         _error_msg,
                                         "Unknown RP client id '{}': '{}'.".format(transaction_session["client_id"],
                                                                                   str(e)))

        location = authzresp.request(_ruri, True)
        logger.debug("Redirected to: '{}' ({})".format(location, type(location)))
        raise cherrypy.HTTPRedirect(location)
Пример #2
0
    def authorization_endpoint(self, query):
        req = self.parse_authorization_request(query=query)
        aevent = AuthnEvent("user", "salt", authn_info="acr")
        sid = self.sdb.create_authz_session(aevent, areq=req)
        self.sdb.do_sub(sid, 'client_salt')
        _info = self.sdb[sid]

        if "code" in req["response_type"]:
            if "token" in req["response_type"]:
                grant = _info["code"]
                _dict = self.sdb.upgrade_to_token(grant)
                _dict["oauth_state"] = "authz",

                _dict = by_schema(AuthorizationResponse(), **_dict)
                resp = AuthorizationResponse(**_dict)
                # resp.code = grant
            else:
                _state = req["state"]
                resp = AuthorizationResponse(state=_state, code=_info["code"])

        else:  # "implicit" in req.response_type:
            grant = _info["code"]
            params = AccessTokenResponse.c_param.keys()

            if "token" in req["response_type"]:
                _dict = dict([
                    (k, v)
                    for k, v in self.sdb.upgrade_to_token(grant).items()
                    if k in params
                ])
                try:
                    del _dict["refresh_token"]
                except KeyError:
                    pass
            else:
                _dict = {"state": req["state"]}

            if "id_token" in req["response_type"]:
                _idt = self.make_id_token(_info, issuer=self.name)
                alg = "RS256"
                ckey = self.keyjar.get_signing_key(alg2keytype(alg),
                                                   _info["client_id"])
                _signed_jwt = _idt.to_jwt(key=ckey, algorithm=alg)
                p = _signed_jwt.split(".")
                p[2] = "aaa"
                _dict["id_token"] = ".".join(p)

            resp = AuthorizationResponse(**_dict)

        location = resp.request(req["redirect_uri"])
        response = Response()
        response.headers = {"location": location}
        response.status_code = 302
        response.text = ""
        return response
Пример #3
0
    def handle_authn_response(self, context, internal_resp):
        """
        See super class method satosa.frontends.base.FrontendModule#handle_authn_response
        :type context: satosa.context.Context
        :type internal_response: satosa.internal_data.InternalResponse
        :rtype oic.utils.http_util.Response
        """
        auth_req = self._get_authn_request_from_state(context.state)

        # filter attributes to return in ID Token as claims
        attributes = self.converter.from_internal(
            "openid", internal_resp.get_attributes())
        satosa_logging(
            LOGGER, logging.DEBUG,
            "Attributes delivered by backend to OIDC frontend: {}".format(
                json.dumps(attributes)), context.state)
        flattened_attributes = {k: v[0] for k, v in attributes.items()}
        requested_id_token_claims = auth_req.get("claims", {}).get("id_token")
        user_claims = self._get_user_info(flattened_attributes,
                                          requested_id_token_claims,
                                          auth_req["scope"])
        satosa_logging(
            LOGGER, logging.DEBUG,
            "Attributes filtered by requested claims/scope: {}".format(
                json.dumps(user_claims)), context.state)

        # construct epoch timestamp of reported authentication time
        auth_time = datetime.datetime.strptime(
            internal_resp.auth_info.timestamp, "%Y-%m-%dT%H:%M:%SZ")
        epoch_timestamp = (auth_time -
                           datetime.datetime(1970, 1, 1)).total_seconds()

        base_claims = {
            "client_id": auth_req["client_id"],
            "sub": internal_resp.get_user_id(),
            "nonce": auth_req["nonce"]
        }
        id_token = self.provider.id_token_as_signed_jwt(
            base_claims,
            user_info=user_claims,
            auth_time=epoch_timestamp,
            loa="",
            alg=self.sign_alg)

        oidc_client_state = auth_req.get("state")
        kwargs = {}
        if oidc_client_state:  # inlcude any optional 'state' sent by the client in the authn req
            kwargs["state"] = oidc_client_state

        auth_resp = AuthorizationResponse(id_token=id_token, **kwargs)
        http_response = auth_resp.request(
            auth_req["redirect_uri"], self._should_fragment_encode(auth_req))
        return SeeOther(http_response)
Пример #4
0
    def authorization_endpoint(self, query):
        req = self.parse_authorization_request(query=query)
        aevent = AuthnEvent("user", "salt", authn_info="acr")
        sid = self.sdb.create_authz_session(aevent, areq=req)
        self.sdb.do_sub(sid, 'client_salt')
        _info = self.sdb[sid]

        if "code" in req["response_type"]:
            if "token" in req["response_type"]:
                grant = _info["code"]
                _dict = self.sdb.upgrade_to_token(grant)
                _dict["oauth_state"] = "authz",

                _dict = by_schema(AuthorizationResponse(), **_dict)
                resp = AuthorizationResponse(**_dict)
            else:
                _state = req["state"]
                resp = AuthorizationResponse(state=_state,
                                             code=_info["code"])

        else:  # "implicit" in req.response_type:
            grant = _info["code"]
            params = AccessTokenResponse.c_param.keys()

            if "token" in req["response_type"]:
                _dict = dict([(k, v) for k, v in
                              self.sdb.upgrade_to_token(grant).items() if k in
                              params])
                try:
                    del _dict["refresh_token"]
                except KeyError:
                    pass
            else:
                _dict = {"state": req["state"]}

            if "id_token" in req["response_type"]:
                _idt = self.make_id_token(_info, issuer=self.name)
                alg = "RS256"
                ckey = self.keyjar.get_signing_key(alg2keytype(alg),
                                                   _info["client_id"])
                _signed_jwt = _idt.to_jwt(key=ckey, algorithm=alg)
                p = _signed_jwt.split(".")
                p[2] = "aaa"
                _dict["id_token"] = ".".join(p)

            resp = AuthorizationResponse(**_dict)

        location = resp.request(req["redirect_uri"])
        response = Response()
        response.headers = {"location": location}
        response.status_code = 302
        response.text = ""
        return response
Пример #5
0
    def handle_authn_response(self, context, internal_resp):
        """
        See super class method satosa.frontends.base.FrontendModule#handle_authn_response
        :type context: satosa.context.Context
        :type internal_response: satosa.internal_data.InternalResponse
        :rtype oic.utils.http_util.Response
        """
        auth_req = self._get_authn_request_from_state(context.state)

        # filter attributes to return in ID Token as claims
        attributes = self.converter.from_internal("openid", internal_resp.get_attributes())
        satosa_logging(LOGGER, logging.DEBUG,
                       "Attributes delivered by backend to OIDC frontend: {}".format(
                               json.dumps(attributes)), context.state)
        flattened_attributes = {k: v[0] for k, v in attributes.items()}
        requested_id_token_claims = auth_req.get("claims", {}).get("id_token")
        user_claims = self._get_user_info(flattened_attributes,
                                          requested_id_token_claims,
                                          auth_req["scope"])
        satosa_logging(LOGGER, logging.DEBUG,
                       "Attributes filtered by requested claims/scope: {}".format(
                               json.dumps(user_claims)), context.state)

        # construct epoch timestamp of reported authentication time
        auth_time = datetime.datetime.strptime(internal_resp.auth_info.timestamp,
                                               "%Y-%m-%dT%H:%M:%SZ")
        epoch_timestamp = (auth_time - datetime.datetime(1970, 1, 1)).total_seconds()

        base_claims = {"client_id": auth_req["client_id"],
                       "sub": internal_resp.get_user_id(),
                       "nonce": auth_req["nonce"]}
        id_token = self.provider.id_token_as_signed_jwt(base_claims, user_info=user_claims,
                                                        auth_time=epoch_timestamp,
                                                        loa="",
                                                        alg=self.sign_alg)

        oidc_client_state = auth_req.get("state")
        kwargs = {}
        if oidc_client_state:  # inlcude any optional 'state' sent by the client in the authn req
            kwargs["state"] = oidc_client_state

        auth_resp = AuthorizationResponse(id_token=id_token, **kwargs)
        http_response = auth_resp.request(auth_req["redirect_uri"],
                                          self._should_fragment_encode(auth_req))
        return SeeOther(http_response)
    def __call__(self, request):
        query = urlparse(request.url).query

        req = self.provider.parse_authorization_request(query=query)

        resp = AuthorizationResponse()

        if 'code' in req['response_type']:
            authz_code = rndstr(10)
            authz_info = {
                'used': False,
                'exp': time.time() + self.provider.authorization_code_lifetime,
                'sub': 'test-sub',
                'granted_scope': ' '.join(req['scope']),
                'auth_req': req.to_dict()
            }
            self.provider.authz_codes[authz_code] = authz_info

            resp['code'] = authz_code

        if 'state' in req:
            resp['state'] = req['state']

        return (302, {'Location': resp.request(req['redirect_uri'])}, '')
    def __call__(self, request):
        query = urlparse(request.url).query

        req = self.provider.parse_authorization_request(query=query)

        resp = AuthorizationResponse()

        if 'code' in req['response_type']:
            authz_code = rndstr(10)
            authz_info = {
                'used': False,
                'exp': time.time() + self.provider.authorization_code_lifetime,
                'sub': 'test-sub',
                'granted_scope': ' '.join(req['scope']),
                'auth_req': req.to_dict()
            }
            self.provider.authz_codes[authz_code] = authz_info

            resp['code'] = authz_code

        if 'state' in req:
            resp['state'] = req['state']

        return (302, {'Location': resp.request(req['redirect_uri'])}, '')
Пример #8
0
            if len(rtype):
                resp = BadRequest("Unknown response type")
                return resp(environ, start_response)

        if "redirect_uri" in areq:
#            try:
#                self._verify_redirect_uri(areq)
#            except Exception:
#                return self._authz_error(environ, start_response,
#                                         "invalid_request_redirect_uri")
            redirect_uri = areq["redirect_uri"]
        else:
            redirect_uri = self.cdb[areq["client_id"]]["redirect_uris"][0]

        location = aresp.request(redirect_uri)

        logger.debug("Redirected to: '%s' (%s)" % (location, type(location)))

        if self.cookie_func and not "active_auth" in kwargs:
            (key, timestamp) = kwargs["handle"]
            self.re_link_log(key, b64scode)
            cookie = self.cookie_func(self.cookie_name, b64scode, self.seed,
                                      self.cookie_ttl)
            redirect = Redirect(str(location), headers=[cookie])
        else:
            redirect = Redirect(str(location))

        return redirect(environ, start_response)