def test_parse_open_id_request(self): userinfo_claims = Claims(name={"essential": True}, nickname=None, email={"essential": True}, email_verified={"essential": True}, picture=None) id_token_claims = Claims(auth_time={"essential": True, "acr": {"values": [ "urn:mace:incommon:iap:silver"]}}) claims_req = ClaimsRequest(userinfo=userinfo_claims, id_token=id_token_claims) oidreq = OpenIDRequest(response_type=["code", "id_token"], client_id=CLIENT_ID, redirect_uri="https://client.example.com/cb", scope="openid profile", state="n-0S6_WzA2Mj", nonce="af0ifjsldkj", max_age=86400, claims=claims_req) request = self.srv.parse_open_id_request(data=oidreq.to_json(), sformat="json") assert isinstance(request, OpenIDRequest) assert _eq(request.keys(), ['nonce', 'claims', 'state', 'redirect_uri', 'response_type', 'client_id', 'scope', 'max_age']) assert request["nonce"] == "af0ifjsldkj" assert "email" in request["claims"]["userinfo"]
def test_parse_open_id_request(self): userinfo_claims = Claims(name={"essential": True}, nickname=None, email={"essential": True}, email_verified={"essential": True}, picture=None) id_token_claims = Claims(auth_time={ "essential": True, "acr": { "values": ["urn:mace:incommon:iap:silver"] } }) claims_req = ClaimsRequest(userinfo=userinfo_claims, id_token=id_token_claims) oidreq = OpenIDRequest(response_type=["code", "id_token"], client_id=CLIENT_ID, redirect_uri="https://client.example.com/cb", scope="openid profile", state="n-0S6_WzA2Mj", nonce="af0ifjsldkj", max_age=86400, claims=claims_req) request = self.srv.parse_open_id_request(data=oidreq.to_json(), sformat="json") assert isinstance(request, OpenIDRequest) assert _eq(request.keys(), [ 'nonce', 'claims', 'state', 'redirect_uri', 'response_type', 'client_id', 'scope', 'max_age' ]) assert request["nonce"] == "af0ifjsldkj" assert "email" in request["claims"]["userinfo"]
def make_openid_request(arq, keys, userinfo_claims=None, idtoken_claims=None, algorithm=OIC_DEF_SIGN_ALG, **kwargs): """ Construct the specification of what I want returned. The request will be signed """ oir_args = {} if userinfo_claims is not None: # UserInfoClaims claim = Claims(**userinfo_claims["claims"]) uic_args = {} for prop, val in userinfo_claims.items(): if prop == "claims": continue if prop in UserInfoClaim.c_param.keys(): uic_args[prop] = val uic = UserInfoClaim(claims=claim, **uic_args) else: uic = None if uic: oir_args["userinfo"] = uic if idtoken_claims is not None: #IdTokenClaims try: _max_age = idtoken_claims["max_age"] except KeyError: _max_age=MAX_AUTHENTICATION_AGE id_token = IDTokenClaim(max_age=_max_age) if "claims" in idtoken_claims: idtclaims = Claims(**idtoken_claims["claims"]) id_token["claims"] = idtclaims else: # uic must be != None id_token = IDTokenClaim(max_age=MAX_AUTHENTICATION_AGE) if id_token: oir_args["id_token"] = id_token for prop in OpenIDRequest.c_param.keys(): try: oir_args[prop] = arq[prop] except KeyError: pass for attr in ["scope", "response_type"]: if attr in oir_args: oir_args[attr] = " ".join(oir_args[attr]) oir = OpenIDRequest(**oir_args) return oir.to_jwt(key=keys, algorithm=algorithm)
def _parse_openid_request(self, request, redirect_uri, jwt_key): try: return OpenIDRequest().from_jwt(request, jwt_key) except Exception, err: logger.error("Faulty request: %s" % request) logger.error("Verfied with JWT_keys: %s" % jwt_key) logger.error("Exception: %s" % (err.__class__.__name__,)) openid_req = OpenIDRequest().from_jwt(request, jwt_key, verify=False) logger.error("Request: %s" % openid_req.to_dict()) return self._redirect_authz_error("invalid_openid_request_object", redirect_uri)
def test_openid_request_with_request_2(self): areq = self.client.construct_OpenIDRequest(idtoken_claims={"claims": {"user_id": {"value": "248289761001"}}}) print areq assert areq assert areq.request _keys = self.client.keystore.get_keys("ver", owner=None) jwtreq = OpenIDRequest().deserialize(areq["request"], "jwt", key=_keys) print print jwtreq print jwtreq.keys() assert _eq(jwtreq.keys(), ["id_token", "state", "redirect_uri", "response_type", "client_id"])
def _collect_user_info(self, session, userinfo_claims=None): """ Collect information about a user. This can happen in two cases, either when constructing an IdToken or when returning user info through the UserInfo endpoint :param session: Session information :param userinfo_claims: user info claims :return: User info """ if userinfo_claims is None: uic = {} for scope in session["scope"]: try: claims = dict([(name, None) for name in SCOPE2CLAIMS[scope]]) uic.update(claims) except KeyError: pass if "oidreq" in session: oidreq = OpenIDRequest().deserialize(session["oidreq"], "json") logger.debug("OIDREQ: %s" % oidreq.to_dict()) try: _claims = oidreq["claims"]["userinfo"] except KeyError: pass else: for key, val in uic.items(): if key not in _claims: _claims[key] = val uic = _claims if uic: userinfo_claims = Claims(**uic) else: userinfo_claims = None elif uic: userinfo_claims = Claims(**uic) else: userinfo_claims = None logger.debug("userinfo_claim: %s" % userinfo_claims.to_dict()) logger.debug("Session info: %s" % session) info = self.userinfo(session["local_sub"], userinfo_claims) info["sub"] = session["sub"] logger.debug("user_info_response: %s" % (info,)) return info
def test_openid_request_with_id_token_claims_request(self): areq = self.client.construct_AuthorizationRequest( request_args={"scope": "openid", "response_type": ["code"], "claims": { "id_token": {"sub": {"value": "248289761001"}}}}, request_param="request" ) jwtreq = OpenIDRequest().deserialize(areq["request"], "jwt", keyjar=self.client.keyjar) assert _eq(jwtreq.keys(), ['claims', 'redirect_uri', 'response_type', 'client_id', 'scope'])
def id_token_claims(session): """ Pick the IdToken claims from the request :param session: Session information :return: The IdToken claims """ itc = None try: authzreq = AuthorizationRequest().deserialize( session["authzreq"], 'json') itc = authzreq["claims"]["id_token"] logger.debug("ID Token claims: %s" % itc) except KeyError: pass try: oidreq = OpenIDRequest().deserialize(session["oidreq"], "json") itc_or = oidreq["claims"]["id_token"] if itc: itc.update(itc_or) logger.debug("ID Token claims: %s" % itc) except KeyError: pass return itc
def test_openid_request_with_id_token_claims_request(self): areq = self.client.construct_AuthorizationRequest( request_args={ "scope": "openid", "response_type": ["code"], "claims": {"id_token": {"sub": {"value": "248289761001"}}}, }, request_param="request", ) jwtreq = OpenIDRequest().deserialize( areq["request"], "jwt", keyjar=self.client.keyjar ) assert _eq( jwtreq.keys(), ["claims", "redirect_uri", "response_type", "client_id", "scope"], )
def test_openid_request_with_request_2(self): areq = self.client.construct_AuthorizationRequest( request_args={"scope":"openid", "response_type":["code"]}, idtoken_claims={"claims": {"sub": {"value":"248289761001"}}}, ) print areq assert areq assert areq.request jwtreq = OpenIDRequest().deserialize(areq["request"], "jwt", keyjar=self.client.keyjar) print print jwtreq print jwtreq.keys() assert _eq(jwtreq.keys(), ['id_token', 'state', 'redirect_uri', 'response_type', 'client_id', 'scope'])
def make_openid_request(arq, keys=None, userinfo_claims=None, idtoken_claims=None, algorithm=None, **kwargs): """ Construct the specification of what I want returned. The request will be signed :param arq: The Authorization request :param keys: Keys to use for signing/encrypting :param userinfo_claims: UserInfo claims :param idtoken_claims: IdToken claims :param algorithm: Which signing/encrypting algorithm to use :return: JWT encoded OpenID request """ oir_args = {} for prop in OpenIDRequest.c_param.keys(): try: oir_args[prop] = arq[prop] except KeyError: pass for attr in ["scope", "response_type"]: if attr in oir_args: oir_args[attr] = " ".join(oir_args[attr]) c_args = {} if userinfo_claims is not None: # UserInfoClaims c_args["userinfo"] = Claims(**userinfo_claims) if idtoken_claims is not None: #IdTokenClaims c_args["id_token"] = Claims(**idtoken_claims) if c_args: oir_args["claims"] = ClaimsRequest(**c_args) oir = OpenIDRequest(**oir_args) return oir.to_jwt(key=keys, algorithm=algorithm)
def update_claims(session, where, about, old_claims=None): """ :param session: :param where: Which request :param about: userinfo or id_token :param old_claims: :return: claims or None """ if old_claims is None: old_claims = {} req = None if where == "oidreq": try: req = OpenIDRequest().deserialize(session[where], "json") except KeyError: pass else: # where == "authzreq" try: req = AuthorizationRequest().deserialize(session[where], "json") except KeyError: pass if req: logger.debug("%s: %s" % (where, req.to_dict())) try: _claims = req["claims"][about] if _claims: # update with old claims, do not overwrite for key, val in old_claims.items(): if key not in _claims: _claims[key] = val return _claims except KeyError: pass return old_claims
def id_token_claims(self, session): """ Pick the IdToken claims from the request :param session: Session information :return: The IdToken claims """ try: oidreq = OpenIDRequest().deserialize(session["oidreq"], "json") itc = oidreq["claims"]["id_token"] logger.debug("ID Token claims: %s" % itc) return itc except KeyError: return None
def end_session_endpoint(self, request="", cookie=None, **kwargs): areq = None redirect_uri = None try: areq = urlparse.parse_qs(request) redirect_uri = self.verify_post_logout_redirect_uri(areq, cookie) authn = self.pick_auth(areq) identity = authn.authenticated_as(cookie) if "uid" not in identity: return self._error_response("Not allowed!") except: return self._error_response("Not allowed!") verify = self.sdb.getVerifyLogout(identity["uid"]) if (verify is None or "key" not in areq or verify != areq["key"][0]) and \ (self.template_lookup is not None and self.verify_login_template is not None): if cookie: headers = [cookie] else: headers = [] mte = self.template_lookup.get_template(self.verify_login_template) self.sdb.setVerifyLogout(identity["uid"]) if redirect_uri is not None: redirect = redirect_uri else: redirect = "/" try: tmp_id_token_hint = areq["id_token_hint"][0] except: tmp_id_token_hint = "" argv = { "id_token_hint": tmp_id_token_hint, "post_logout_redirect_uri": areq["post_logout_redirect_uri"][0], "key": self.sdb.getVerifyLogout(identity["uid"]), "redirect": redirect, "action": "/"+EndSessionEndpoint("").etype } #resp.message = mte.render(**argv) return Response(mte.render(**argv), headers=[]) id_token = None try: id_token = self.sdb.getToken_id(identity["uid"]) except: pass if id_token is not None and "id_token_hint" in areq: try: id_token_hint = OpenIDRequest().from_jwt(areq["id_token_hint"][0], keyjar=self.keyjar, verify=True) id_token = OpenIDRequest().from_jwt(id_token, keyjar=self.keyjar, verify=True) id_token_hint_dict = id_token_hint.to_dict() id_token_dict = id_token.to_dict() for key in id_token_dict: if key in id_token_hint_dict: if id_token_dict[key] != id_token_hint_dict[key]: return self._error_response("Not allowed!") else: return self._error_response("Not allowed!") for key in id_token_hint_dict: if key in id_token_dict: if id_token_dict[key] != id_token_hint_dict[key]: return self._error_response("Not allowed!") else: return self._error_response("Not allowed!") except: self._error_response("Not allowed!") elif id_token is not None: self._error_response("Not allowed!") try: self.sdb.revoke_uid(identity["uid"]) except: pass #If cleanup cannot be performed we will still invalidate the cookie. if redirect_uri is not None: return Redirect(str(redirect_uri), headers=[authn.delete_cookie()]) return Response("", headers=[authn.delete_cookie()])