def _code_auth2(self, state): req = AuthorizationRequest( state=state, response_type="code", redirect_uri="{}cb".format(CLI2), scope=["openid"], client_id="client_2", ) _pr_resp = self.authn_endpoint.parse_request(req.to_dict()) return self.authn_endpoint.process_request(_pr_resp)
def test_do_request_uri(self): request = AuthorizationRequest( redirect_uri="https://rp.example.com/cb", request_uri="https://example.com/request", ) orig_request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token token"], state="state", nonce="nonce", scope="openid", ) _jwt = JWT(key_jar=self.rp_keyjar, iss="client_1", sign_alg="HS256") _jws = _jwt.pack( orig_request.to_dict(), aud=self.endpoint.server_get("endpoint_context").provider_info["issuer"], ) endpoint_context = self.endpoint.server_get("endpoint_context") endpoint_context.cdb["client_1"]["request_uris"] = [("https://example.com/request", {})] with responses.RequestsMock() as rsps: rsps.add( "GET", request["request_uri"], body=_jws, adding_headers={"Content-Type": "application/jose"}, status=200, ) self.endpoint._do_request_uri(request, "client_1", endpoint_context) request["request_uri"] = "https://example.com/request#1" with responses.RequestsMock() as rsps: rsps.add( "GET", request["request_uri"], body=_jws, adding_headers={"Content-Type": "application/jose"}, status=200, ) self.endpoint._do_request_uri(request, "client_1", endpoint_context) request["request_uri"] = "https://example.com/another" with pytest.raises(ValueError): self.endpoint._do_request_uri(request, "client_1", endpoint_context) endpoint_context.provider_info["request_uri_parameter_supported"] = False with pytest.raises(ServiceError): self.endpoint._do_request_uri(request, "client_1", endpoint_context)
def _auth_with_id_token(self, state): req = AuthorizationRequest( state=state, response_type="id_token", redirect_uri="{}cb".format(CLI1), scope=["openid"], client_id="client_1", nonce="_nonce_", ) _pr_resp = self.authn_endpoint.parse_request(req.to_dict()) _resp = self.authn_endpoint.process_request(_pr_resp) return _resp["response_args"]["id_token"]
def test_setup_auth_session_revoked(self): request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token"], state="state", nonce="nonce", scope="openid", ) redirect_uri = request["redirect_uri"] cinfo = { "client_id": "client_id", "redirect_uris": [("https://rp.example.com/cb", {})], "id_token_signed_response_alg": "RS256", } _ec = self.endpoint.endpoint_context _ec.sdb["session_id"] = SessionInfo( authn_req=request, uid="diana", sub="abcdefghijkl", authn_event={ "authn_info": "loa1", "uid": "diana", "authn_time": utc_time_sans_frac(), }, revoked=True, ) item = _ec.authn_broker.db["anon"] item["method"].user = b64e( as_bytes(json.dumps({"uid": "krall", "sid": "session_id"})) ) res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None) assert set(res.keys()) == {"args", "function"}
def test_do_request_user(self): request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token"], state="state", nonce="nonce", scope="openid", ) assert self.endpoint.do_request_user(request) == {} # With login_hint request["login_hint"] = "mail:[email protected]" assert self.endpoint.do_request_user(request) == {} endpoint_context = self.endpoint.server_get("endpoint_context") # userinfo _userinfo = init_user_info( {"class": "oidcop.user_info.UserInfo", "kwargs": {"db_file": full_path("users.json")},}, "", ) # login_hint endpoint_context.login_hint_lookup = init_service( {"class": "oidcop.login_hint.LoginHintLookup"}, None ) endpoint_context.login_hint_lookup.userinfo = _userinfo # With login_hint and login_hint_lookup assert self.endpoint.do_request_user(request) == {"req_user": "******"}
def test_response_mode(self, response_mode): request = AuthorizationRequest( client_id="client_1", response_type=["code"], redirect_uri="https://example.com/cb", state="state", scope="openid", response_mode=response_mode, ) response_args = AuthorizationResponse(scope="openid", code="abcdefghijklmnop") if response_mode == "fragment": info = self.endpoint.response_mode( request, response_args, request["redirect_uri"], fragment_enc=True ) else: info = self.endpoint.response_mode(request, response_args, request["redirect_uri"]) if response_mode == "form_post": assert set(info.keys()) == { "response_msg", "content_type", "response_placement", } elif response_mode == "fragment": assert set(info.keys()) == {"response_args", "return_uri", "fragment_enc"} elif response_mode == "query": assert set(info.keys()) == {"response_args", "return_uri"}
def test_post_parse_request(self): endpoint_context = self.endpoint.server_get("endpoint_context") msg = self.endpoint._post_parse_request(None, "client_1", endpoint_context) assert "error" in msg request = AuthorizationRequest( client_id="client_X", response_type=["code"], state="state", nonce="nonce", scope="openid", ) msg = self.endpoint._post_parse_request(request, "client_X", endpoint_context) assert "error" in msg assert msg["error_description"] == "unknown client" request["client_id"] = "client_1" endpoint_context.cdb["client_1"]["redirect_uris"] = [ ("https://example.com/cb", ""), ("https://example.com/2nd_cb", ""), ] msg = self.endpoint._post_parse_request(request, "client_1", endpoint_context) assert "error" in msg assert msg["error"] == "invalid_request"
def test_verify_response_type(self): request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token token"], state="state", nonce="nonce", scope="openid", ) client_info = { "client_id": "client_id", "redirect_uris": [("https://rp.example.com/cb", {})], "id_token_signed_response_alg": "RS256", "policy_uri": "https://example.com/policy.html", } assert self.endpoint.verify_response_type(request, client_info) is False client_info["response_types"] = [ "code", "code id_token", "id_token", "id_token token", ] assert self.endpoint.verify_response_type(request, client_info) is True
def test_setup_auth_session_revoked(self): request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token"], state="state", nonce="nonce", scope="openid", ) redirect_uri = request["redirect_uri"] cinfo = { "client_id": "client_id", "redirect_uris": [("https://rp.example.com/cb", {})], "id_token_signed_response_alg": "RS256", } _ec = self.endpoint.server_get("endpoint_context") session_id = self._create_session(request) item = _ec.authn_broker.db["anon"] item["method"].user = b64e(as_bytes(json.dumps({"uid": "krall", "sid": session_id}))) grant = _ec.session_manager[session_id] grant.revoked = True res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None) assert set(res.keys()) == {"args", "function"}
def test_create_authn_response(self): request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token"], state="state", nonce="nonce", scope="openid", ) _ec = self.endpoint.endpoint_context _ec.sdb["session_id"] = SessionInfo( authn_req=request, uid="diana", sub="abcdefghijkl", authn_event={ "authn_info": "loa1", "uid": "diana", "authn_time": utc_time_sans_frac(), }, ) _ec.cdb["client_id"] = { "client_id": "client_id", "redirect_uris": [("https://rp.example.com/cb", {})], "id_token_signed_response_alg": "ES256", } resp = create_authn_response(self.endpoint, request, "session_id") assert isinstance(resp["response_args"], AuthorizationErrorResponse)
def verify_user(request): """csrf is not needed because it uses oidc token in the post """ token = request.POST.get('token') if not token: return HttpResponse('Access forbidden: invalid token.', status=403) authn_method = oidcendpoint_app.endpoint_context.\ authn_broker.get_method_by_id('user') kwargs = dict([(k, v) for k, v in request.POST.items()]) user = authn_method.verify(**kwargs) if not user: return HttpResponse('Authentication failed', status=403) auth_args = authn_method.unpack_token(kwargs['token']) authz_request = AuthorizationRequest().from_urlencoded(auth_args['query']) # salt size can be customized in settings.OIDC_OP_AUTHN_SALT_SIZE salt_size = getattr(settings, 'OIDC_OP_AUTHN_SALT_SIZE', 4) authn_event = create_authn_event( uid=user.username, salt=base64.b64encode(os.urandom(salt_size)).decode(), authn_info=auth_args['authn_class_ref'], authn_time=auth_args['iat']) endpoint = oidcendpoint_app.endpoint_context.endpoint['authorization'] args = endpoint.authz_part2(user=user.username, request=authz_request, authn_event=authn_event) if isinstance(args, ResponseMessage) and 'error' in args: return HttpResponse(args.to_json(), status=400) response = do_response(endpoint, request, **args) return response
def verify_user(request): """csrf is not needed because it uses oidc token in the post """ _name = sys._getframe().f_code.co_name debug_request(f'{_name}', request) token = request.POST.get('token') if not token: # pragma: no cover return HttpResponse('Access forbidden: invalid token.', status=403) ec = oidcop_app.endpoint_context authn_method = ec.endpoint_context.authn_broker.get_method_by_id('user') kwargs = dict([(k, v) for k, v in request.POST.items()]) user = authn_method.verify(**kwargs) if not user: return HttpResponse('Authentication failed', status=403) auth_args = authn_method.unpack_token(kwargs['token']) authz_request = AuthorizationRequest().from_urlencoded(auth_args['query']) # salt size can be customized in settings.OIDC_OP_AUTHN_SALT_SIZE salt_size = getattr(settings, 'OIDC_OP_AUTHN_SALT_SIZE', 4) authn_event = create_authn_event(uid=user.username, salt=base64.b64encode( os.urandom(salt_size)).decode(), authn_info=auth_args['authn_class_ref'], authn_time=auth_args['iat']) endpoint = oidcop_app.endpoint_context.endpoint['authorization'] client_id = authz_request["client_id"] _token_usage_rules = endpoint.server_get( "endpoint_context").authn_broker.get_method_by_id('user') session_manager = ec.endpoint_context.session_manager _session_id = session_manager.create_session( authn_event=authn_event, auth_req=authz_request, user_id=user.username, client_id=client_id, token_usage_rules=_token_usage_rules) try: _args = endpoint.authz_part2(user=user.username, session_id=_session_id, request=authz_request, authn_event=authn_event) except ValueError as excp: msg = 'Something went wrong with your Session ... {}'.format(excp) return HttpResponse(msg, status=403) if isinstance(_args, ResponseMessage) and 'error' in _args: return HttpResponse(_args.to_json(), status=400) elif isinstance(_args.get('response_args'), AuthorizationErrorResponse): rargs = _args.get('response_args') logger.error(rargs) return HttpResponse(rargs.to_json(), status=400) response = do_response(request, endpoint, authz_request, **_args) return response
def test_dump_load(): b = ImpExpTest() b.string = "foo" b.list = ["a", "b", "c"] b.dict = {"a": 1, "b": 2} b.message = AuthorizationRequest( scope="openid", redirect_uri="https://example.com/cb", response_type="code", client_id="abcdefg", ) b.response_class = AuthorizationResponse b.key_bundle = build_key_bundle(key_conf=KEYSPEC) b.bundles = [build_key_bundle(key_conf=KEYSPEC)] b.bundles.append(build_key_bundle(key_conf=KEYSPEC)) dump = b.dump() b_copy = ImpExpTest().load(dump) assert b_copy assert b_copy.list == b.list assert b_copy.dict == b.dict # Message doesn't implement __eq__ assert b_copy.message.__class__ == b.message.__class__ assert b_copy.response_class == b.response_class # KeyBundle doesn't implement __eq__ assert b_copy.key_bundle.keys() == b.key_bundle.keys() assert len(b_copy.bundles) == 2 for kb in b_copy.bundles: assert isinstance(kb, KeyBundle)
def test_setup_auth_error(self): request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token"], state="state", nonce="nonce", scope="openid", ) redirect_uri = request["redirect_uri"] cinfo = { "client_id": "client_id", "redirect_uris": [("https://rp.example.com/cb", {})], "id_token_signed_response_alg": "RS256", } item = self.endpoint.endpoint_context.authn_broker.db["anon"] item["method"].fail = NoSuchAuthentication res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None) assert set(res.keys()) == {"function", "args"} item["method"].fail = ToOld res = self.endpoint.setup_auth(request, redirect_uri, cinfo, None) assert set(res.keys()) == {"function", "args"} item["method"].file = ""
def authn_verify(method): """ Authentication verification :param url_endpoint: Which endpoint to use :param kwargs: response arguments :return: HTTP redirect """ url_endpoint = 'verify/{}'.format(method) authn_method = current_app.endpoint_context.endpoint_to_authn_method[ url_endpoint] kwargs = dict([(k, v) for k, v in request.form.items()]) username = authn_method.verify(**kwargs) if not username: return make_response('Authentication failed', 403) auth_args = authn_method.unpack_token(kwargs['token']) authz_request = AuthorizationRequest().from_urlencoded(auth_args['query']) authn_event = create_authn_event(uid=username, salt='salt', authn_info=auth_args['authn_class_ref'], authn_time=auth_args['iat']) endpoint = current_app.endpoint_context.endpoint['authorization'] args = endpoint.authz_part2(user=username, request=authz_request, authn_event=authn_event) if isinstance(args, ResponseMessage) and 'error' in args: return make_response(args.to_json(), 400) return do_response(endpoint, request, **args)
def test_setup_auth_login_hint2acrs(self): request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token"], state="state", nonce="nonce", scope="openid", login_hint="email:foo@bar", ) redirect_uri = request["redirect_uri"] method_spec = { "acr": INTERNETPROTOCOLPASSWORD, "kwargs": { "user": "******" }, "class": NoAuthn, } self.endpoint.endpoint_context.authn_broker["foo"] = init_method( method_spec, None) item = self.endpoint.endpoint_context.authn_broker.db["anon"] item["method"].fail = NoSuchAuthentication item = self.endpoint.endpoint_context.authn_broker.db["foo"] item["method"].fail = NoSuchAuthentication res = self.endpoint.pick_authn_method(request, redirect_uri) assert set(res.keys()) == {"method", "acr"} assert res["acr"] == INTERNETPROTOCOLPASSWORD assert isinstance(res["method"], NoAuthn) assert res["method"].user == "knoll"
def verify(authn_method): """ Authentication verification :param url_endpoint: Which endpoint to use :param kwargs: response arguments :return: HTTP redirect """ kwargs = dict([(k, v) for k, v in request.form.items()]) username = authn_method.verify(**kwargs) if not username: return make_response('Authentication failed', 403) auth_args = authn_method.unpack_token(kwargs['token']) authz_request = AuthorizationRequest().from_urlencoded(auth_args['query']) endpoint = current_app.server.server_get("endpoint", 'authorization') _session_id = endpoint.create_session(authz_request, username, auth_args['authn_class_ref'], auth_args['iat'], authn_method) args = endpoint.authz_part2(request=authz_request, session_id=_session_id) if isinstance(args, ResponseMessage) and 'error' in args: return make_response(args.to_json(), 400) return do_response(endpoint, request, **args)
def auth(self): # Start with an authentication request # The client ID appears in the request AUTH_REQ = AuthorizationRequest( client_id="client_1", redirect_uri="https://example.com/cb", scope=["openid", "mail", "address", "offline_access"], state="STATE", response_type="code", ) # The authentication returns a user ID user_id = "diana" # User info is stored in the Session DB authn_event = create_authn_event( user_id, authn_info=INTERNETPROTOCOLPASSWORD, authn_time=time_sans_frac(), ) user_info = UserSessionInfo(user_id=user_id) self.session_manager.set([user_id], user_info) # Now for client session information client_id = AUTH_REQ["client_id"] client_info = ClientSessionInfo(client_id=client_id) self.session_manager.set([user_id, client_id], client_info) # The user consent module produces a Grant instance grant = Grant( scope=AUTH_REQ["scope"], resources=[client_id], authorization_request=AUTH_REQ, authentication_event=authn_event, ) # the grant is assigned to a session (user_id, client_id) self.session_manager.set([user_id, client_id, grant.id], grant) session_id = self.session_manager.encrypted_session_id( user_id, client_id, grant.id) # Constructing an authorization code is now done by code = grant.mint_token( session_id=session_id, endpoint_context=self.endpoint_context, token_class="authorization_code", token_handler=self.session_manager. token_handler["authorization_code"], expires_at=time_sans_frac() + 300, # 5 minutes from now ) # get user info user_info = self.session_manager.get_user_info(uid=user_id, ) return grant.id, code
def _auth_with_id_token(self, state): req = AuthorizationRequest( state=state, response_type="id_token", redirect_uri="{}cb".format(CLI1), scope=["openid"], client_id="client_1", nonce="_nonce_", ) _pr_resp = self.authn_endpoint.parse_request(req.to_dict()) _resp = self.authn_endpoint.process_request(_pr_resp) _info = self.session_endpoint.server_get( "endpoint_context").cookie_handler.parse_cookie( "oidc_op", _resp["cookie"]) # value is a JSON document _cookie_info = json.loads(_info[0]["value"]) return _resp["response_args"], _cookie_info["sid"]
def test_post_authentication(self): request = AuthorizationRequest( client_id="client_1", response_type=["code"], redirect_uri="https://example.com/cb", state="state", scope="openid", ) session_id = self._create_session(request) resp = self.endpoint.post_authentication(request, session_id) assert resp
def test_request_object_encryption(): msg = AuthorizationRequest(state='ABCDE', redirect_uri='https://example.com/cb', response_type='code') conf = { 'redirect_uris': ['https://example.com/cli/authz_cb'], 'client_id': 'client_1', 'client_secret': 'abcdefghijklmnop', } service_context = ServiceContext(keyjar=keyjar, config=conf) service_context.behaviour["request_object_encryption_alg"] = 'RSA1_5' service_context.behaviour[ "request_object_encryption_enc"] = "A128CBC-HS256" _jwe = request_object_encryption(msg.to_json(), service_context, target=RECEIVER) assert _jwe _decryptor = factory(_jwe) assert _decryptor.jwt.verify_headers(alg='RSA1_5', enc='A128CBC-HS256')
def test_authn_args_gather_message(): request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token"], state="state", nonce="nonce", scope="openid", ) client_info = { "client_id": "client_id", "redirect_uris": [("https://rp.example.com/cb", {})], "id_token_signed_response_alg": "RS256", "policy_uri": "https://example.com/policy.html", } args = authn_args_gather(request, INTERNETPROTOCOLPASSWORD, client_info) assert set(args.keys()) == {"query", "authn_class_ref", "return_uri", "policy_uri"} args = authn_args_gather(request.to_dict(), INTERNETPROTOCOLPASSWORD, client_info) assert set(args.keys()) == {"query", "authn_class_ref", "return_uri", "policy_uri"} with pytest.raises(ValueError): authn_args_gather(request.to_urlencoded(), INTERNETPROTOCOLPASSWORD, client_info)
def duplicate(self, sinfo): session_info = copy.copy(sinfo) areq = AuthorizationRequest().from_json(session_info["authzreq"]) sid = self.handler['code'].key(user=session_info["sub"], areq=areq) session_info["code"] = self.handler['code'](sid=sid, sinfo=sinfo) for key in ["access_token", "access_token_scope", "oauth_state", "token_type", "token_expires_at", "expires_in", "client_id_issued_at", "id_token", "oidreq", "refresh_token"]: try: del session_info[key] except KeyError: pass self[sid] = session_info self.sso_db.map_sid2sub(sid, session_info["sub"]) return sid
def test_create_authn_response(self): request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token"], state="state", nonce="nonce", scope="openid", ) _ec = self.endpoint.server_get("endpoint_context") _ec.cdb["client_id"] = { "client_id": "client_id", "redirect_uris": [("https://rp.example.com/cb", {})], "id_token_signed_response_alg": "ES256", } session_id = self._create_session(request) resp = self.endpoint.create_authn_response(request, session_id) assert isinstance(resp["response_args"], AuthorizationResponse)
def test_setup_auth(self): request = AuthorizationRequest( client_id="client_id", redirect_uri="https://rp.example.com/cb", response_type=["id_token"], state="state", nonce="nonce", scope="openid", ) redirect_uri = request["redirect_uri"] cinfo = { "client_id": "client_id", "redirect_uris": [("https://rp.example.com/cb", {})], "id_token_signed_response_alg": "RS256", } kaka = self.endpoint.endpoint_context.cookie_dealer.create_cookie( "value", "sso") res = self.endpoint.setup_auth(request, redirect_uri, cinfo, kaka) assert set(res.keys()) == {"authn_event", "identity", "user"}
def test_flush(): b = ImpExpTest() b.string = "foo" b.list = ["a", "b", "c"] b.dict = {"a": 1, "b": 2} b.message = AuthorizationRequest( scope="openid", redirect_uri="https://example.com/cb", response_type="code", client_id="abcdefg", ) b.response_class = AuthorizationResponse b.key_bundle = build_key_bundle(key_conf=KEYSPEC) b.bundles = [build_key_bundle(key_conf=KEYSPEC)] b.bundles.append(build_key_bundle(key_conf=KEYSPEC)) dump = b.dump() b.flush() assert b.string == "" assert b.list == [] assert b.dict == {} assert b.message is None assert b.response_class is None assert b.key_bundle is None assert b.bundles is None b.load(dump) assert b.string == "foo" assert b.list == ["a", "b", "c"] assert b.dict == {"a": 1, "b": 2} assert isinstance(b.message, AuthorizationRequest) assert b.response_class == AuthorizationResponse assert isinstance(b.key_bundle, KeyBundle) assert len(b.bundles) == 2 for kb in b.bundles: assert isinstance(kb, KeyBundle)
def authorization_request_deser(val, sformat="urlencoded"): if sformat in ["dict", "json"]: if not isinstance(val, str): val = json.dumps(val) sformat = "json" return AuthorizationRequest().deserialize(val, sformat)
"grant_types_supported": [ "authorization_code", "implicit", "urn:ietf:params:oauth:grant-type:jwt-bearer", "refresh_token" ], "claim_types_supported": ["normal", "aggregated", "distributed"], "claims_parameter_supported": True, "request_parameter_supported": True, "request_uri_parameter_supported": True, } AUTH_REQ = AuthorizationRequest(client_id='client_1', redirect_uri='https://example.com/cb', scope=['openid'], state='STATE', response_type='code') TOKEN_REQ = AccessTokenRequest(client_id='client_1', redirect_uri='https://example.com/cb', state='STATE', grant_type='authorization_code', client_secret='hemligt') TOKEN_REQ_DICT = TOKEN_REQ.to_dict() BASEDIR = os.path.abspath(os.path.dirname(__file__)) def full_path(local_file):
"urn:ietf:params:oauth:grant-type:jwt-bearer", "refresh_token", ], "claim_types_supported": ["normal", "aggregated", "distributed"], "claims_parameter_supported": True, "request_parameter_supported": True, "request_uri_parameter_supported": True, } AUTH_REQ = AuthorizationRequest( client_id="client_1", redirect_uri="https://example.com/cb", scope=["openid"], state="STATE", response_type="code id_token", ) TOKEN_REQ = AccessTokenRequest( client_id="client_1", redirect_uri="https://example.com/cb", state="STATE", grant_type="authorization_code", client_secret="hemligt", ) TOKEN_REQ_DICT = TOKEN_REQ.to_dict() BASEDIR = os.path.abspath(os.path.dirname(__file__))
"urn:ietf:params:oauth:grant-type:jwt-bearer", "refresh_token", ], "claim_types_supported": ["normal", "aggregated", "distributed"], "claims_parameter_supported": True, "request_parameter_supported": True, "request_uri_parameter_supported": True, } AUTH_REQ = AuthorizationRequest( client_id="client_1", redirect_uri="{}cb".format(ISS), scope=["openid"], state="STATE", response_type="code", client_secret="hemligt", ) AUTH_REQ_DICT = AUTH_REQ.to_dict() BASEDIR = os.path.abspath(os.path.dirname(__file__)) def full_path(local_file): return os.path.join(BASEDIR, local_file) USERINFO_db = json.loads(open(full_path("users.json")).read())