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)
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
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 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
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'])}, '')
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)