def registration_endpoint(self, environ, start_response, **kwargs): logger.debug("@registration_endpoint") try: query = kwargs["query"] except KeyError: try: query = get_or_post(environ) except UnsupportedMethod: resp = BadRequest("Unsupported method") return resp(environ, start_response) request = RegistrationRequest().deserialize(query, "urlencoded") logger.info("registration_request:%s" % request.to_dict()) _keystore = self.server.keystore if request["type"] == "client_associate": # create new id och secret client_id = rndstr(12) while client_id in self.cdb: client_id = rndstr(12) client_secret = secret(self.seed, client_id) self.cdb[client_id] = { "client_secret":client_secret } _cinfo = self.cdb[client_id] if "redirect_uris" in request: for uri in request["redirect_uris"]: if urlparse.urlparse(uri).fragment: err = ClientRegistrationErrorResponse( error="invalid_configuration_parameter", error_description="redirect_uri contains fragment") resp = Response(err.to_json(), content="application/json", status="400 Bad Request") return resp(environ, start_response) for key,val in request.items(): _cinfo[key] = val try: self.keystore.load_keys(request, client_id) except Exception, err: logger.error("Failed to load client keys: %s" % request.to_dict()) err = ClientRegistrationErrorResponse( error="invalid_configuration_parameter", error_description="%s" % err) resp = Response(err.to_json(), content="application/json", status="400 Bad Request") return resp(environ, start_response) response = RegistrationResponseCARS(client_id=client_id)
def test_full_flow(self, context, frontend_with_extra_scopes): redirect_uri = "https://client.example.com/redirect" response_type = "code id_token token" mock_callback = Mock() frontend_with_extra_scopes.auth_req_callback_func = mock_callback # discovery http_response = frontend_with_extra_scopes.provider_config(context) provider_config = ProviderConfigurationResponse().deserialize(http_response.message, "json") # client registration registration_request = RegistrationRequest(redirect_uris=[redirect_uri], response_types=[response_type]) context.request = registration_request.to_dict() http_response = frontend_with_extra_scopes.client_registration(context) registration_response = RegistrationResponse().deserialize(http_response.message, "json") # authentication request authn_req = AuthorizationRequest( redirect_uri=redirect_uri, client_id=registration_response["client_id"], response_type=response_type, scope="openid email eduperson", state="state", nonce="nonce", ) context.request = dict(parse_qsl(authn_req.to_urlencoded())) frontend_with_extra_scopes.handle_authn_request(context) assert mock_callback.call_count == 1 # fake authentication response from backend internal_response = self.setup_for_authn_response( context, frontend_with_extra_scopes, authn_req ) http_response = frontend_with_extra_scopes.handle_authn_response( context, internal_response ) authn_resp = AuthorizationResponse().deserialize(urlparse(http_response.message).fragment, "urlencoded") assert "code" in authn_resp assert "access_token" in authn_resp assert "id_token" in authn_resp # token request context.request = AccessTokenRequest(redirect_uri=authn_req["redirect_uri"], code=authn_resp["code"]).to_dict() credentials = "{}:{}".format(registration_response["client_id"], registration_response["client_secret"]) basic_auth = urlsafe_b64encode(credentials.encode("utf-8")).decode("utf-8") context.request_authorization = "Basic {}".format(basic_auth) http_response = frontend_with_extra_scopes.token_endpoint(context) parsed = AccessTokenResponse().deserialize(http_response.message, "json") assert "access_token" in parsed assert "id_token" in parsed # userinfo request context.request = {} context.request_authorization = "Bearer {}".format(parsed["access_token"]) http_response = frontend_with_extra_scopes.userinfo_endpoint(context) parsed = OpenIDSchema().deserialize(http_response.message, "json") assert "email" in parsed assert "eduperson_principal_name" in parsed assert "eduperson_scoped_affiliation" in parsed
def test_register_client_with_wrong_response_type(self, context, frontend): redirect_uri = "https://client.example.com" registration_request = RegistrationRequest(redirect_uris=[redirect_uri], response_types=["id_token token"]) context.request = registration_request.to_dict() registration_response = frontend.client_registration(context) assert registration_response.status == "400 Bad Request" error_response = ClientRegistrationErrorResponse().deserialize(registration_response.message, "json") assert error_response["error"] == "invalid_request" assert "response_type" in error_response["error_description"]
def test_register_client_with_wrong_response_type(self, context, frontend): redirect_uri = "https://client.example.com" registration_request = RegistrationRequest( redirect_uris=[redirect_uri], response_types=["id_token token"]) context.request = registration_request.to_dict() registration_response = frontend.client_registration(context) assert registration_response.status == "400 Bad Request" error_response = ClientRegistrationErrorResponse().deserialize( registration_response.message, "json") assert error_response["error"] == "invalid_request" assert "response_type" in error_response["error_description"]
def test_register_client(self, context, frontend): redirect_uri = "https://client.example.com" registration_request = RegistrationRequest(redirect_uris=[redirect_uri], response_types=["id_token"]) context.request = registration_request.to_dict() registration_response = frontend.client_registration(context) assert registration_response.status == "201 Created" reg_resp = RegistrationResponse().deserialize(registration_response.message, "json") assert "client_id" in reg_resp assert reg_resp["redirect_uris"] == [redirect_uri] assert reg_resp["response_types"] == ["id_token"]
def test_full_flow(self, context, frontend): redirect_uri = "https://client.example.com/redirect" response_type = "code id_token token" mock_callback = Mock() frontend.auth_req_callback_func = mock_callback # discovery http_response = frontend.provider_config(context) provider_config = ProviderConfigurationResponse().deserialize(http_response.message, "json") # client registration registration_request = RegistrationRequest(redirect_uris=[redirect_uri], response_types=[response_type]) context.request = registration_request.to_dict() http_response = frontend.client_registration(context) registration_response = RegistrationResponse().deserialize(http_response.message, "json") # authentication request authn_req = AuthorizationRequest( redirect_uri=redirect_uri, client_id=registration_response["client_id"], response_type=response_type, scope="openid email", state="state", nonce="nonce", ) context.request = dict(parse_qsl(authn_req.to_urlencoded())) frontend.handle_authn_request(context) assert mock_callback.call_count == 1 # fake authentication response from backend internal_response = self.setup_for_authn_response(context, frontend, authn_req) http_response = frontend.handle_authn_response(context, internal_response) authn_resp = AuthorizationResponse().deserialize(urlparse(http_response.message).fragment, "urlencoded") assert "code" in authn_resp assert "access_token" in authn_resp assert "id_token" in authn_resp # token request context.request = AccessTokenRequest(redirect_uri=authn_req["redirect_uri"], code=authn_resp["code"]).to_dict() credentials = "{}:{}".format(registration_response["client_id"], registration_response["client_secret"]) basic_auth = urlsafe_b64encode(credentials.encode("utf-8")).decode("utf-8") context.request_authorization = "Basic {}".format(basic_auth) http_response = frontend.token_endpoint(context) parsed = AccessTokenResponse().deserialize(http_response.message, "json") assert "access_token" in parsed assert "id_token" in parsed # userinfo request context.request = {} context.request_authorization = "Bearer {}".format(parsed["access_token"]) http_response = frontend.userinfo_endpoint(context) parsed = OpenIDSchema().deserialize(http_response.message, "json") assert "email" in parsed
def test_register_client(self, context, frontend): redirect_uri = "https://client.example.com" registration_request = RegistrationRequest(redirect_uris=[redirect_uri], response_types=["id_token"]) context.request = registration_request.to_dict() registration_response = frontend.client_registration(context) assert registration_response.status == "201 Created" reg_resp = RegistrationResponse().deserialize(registration_response.message, "json") assert "client_id" in reg_resp assert reg_resp["redirect_uris"] == [redirect_uri] assert reg_resp["response_types"] == ["id_token"]
def test_registration_endpoint(self): req = RegistrationRequest() req["application_type"] = "web" req["client_name"] = "My super service" req["redirect_uris"] = ["http://example.com/authz"] req["contacts"] = ["*****@*****.**"] req["response_types"] = ["code"] print req.to_dict() resp = self.server.registration_endpoint(request=req.to_json()) print resp.message regresp = RegistrationResponse().deserialize(resp.message, "json") print regresp.keys() assert _eq(regresp.keys(), ['redirect_uris', 'contacts', 'application_type', 'client_name', 'registration_client_uri', 'client_secret_expires_at', 'registration_access_token', 'client_id', 'client_secret', 'client_id_issued_at', 'response_types'])
def test_registration_endpoint(self): req = RegistrationRequest() req["application_type"] = "web" req["client_name"] = "My super service" req["redirect_uris"] = ["http://example.com/authz"] req["contacts"] = ["*****@*****.**"] req["response_types"] = ["code"] print req.to_dict() resp = self.server.registration_endpoint(request=req.to_json()) print resp.message regresp = RegistrationResponse().deserialize(resp.message, "json") print regresp.keys() assert _eq(regresp.keys(), [ 'redirect_uris', 'contacts', 'application_type', 'client_name', 'registration_client_uri', 'client_secret_expires_at', 'registration_access_token', 'client_id', 'client_secret', 'client_id_issued_at', 'response_types' ])
def test_register_client(self): redirect_uri = "https://client.example.com" registration_request = RegistrationRequest(redirect_uris=[redirect_uri], response_types=["id_token"]) context = Context() context.request = registration_request.to_dict() registration_response = self.instance._register_client(context) assert registration_response.status == "201 Created" reg_resp = RegistrationResponse().deserialize(registration_response.message, "json") assert "client_id" in reg_resp assert reg_resp["client_id"] in self.instance.provider.cdb # no need to issue client secret since to token endpoint is published assert "client_secret" not in reg_resp assert reg_resp["redirect_uris"] == [redirect_uri] assert reg_resp["response_types"] == ["id_token"] assert reg_resp["id_token_signed_response_alg"] == "RS256"
def l_registration_endpoint(self, request, authn=None, **kwargs): _log_debug = logger.debug _log_info = logger.info _log_debug("@registration_endpoint") request = RegistrationRequest().deserialize(request, "json") _log_info("registration_request:%s" % request.to_dict()) resp_keys = request.keys() try: request.verify() except MessageException, err: if "type" not in request: return self._error(error="invalid_type", descr="%s" % err) else: return self._error(error="invalid_configuration_parameter", descr="%s" % err)
# ----------------------------------------------------------------------------- # -- construct Registration Request to be signed by Developer # ----------------------------------------------------------------------------- rreq = RegistrationRequest( redirect_uris=['https://example.com/rp1/callback'], application_type='web', response_types=['code'], signing_key=rp_jwks['keys'][0], jwks_uri_signed='https://example.com/rp1/jwks.jws' ) print(70 * "-") print('Client Registration request') print(70 * "-") print_lines(json.dumps(rreq.to_dict(), sort_keys=True, indent=2, separators=(',', ': '))) # ----------------------------------------------------------------------------- # Developer signs Registration Request once per federation # ----------------------------------------------------------------------------- # adds the developers software statement rreq.update({ "software_statements": [dev_swamid_sost], }) print(70 * "-") print('Developer adds software_statement to the Client Registration request') print(70 * "-")
# ----------------------------------------------------------------------------- # -- construct Registration Request to be signed by Developer # ----------------------------------------------------------------------------- rreq = RegistrationRequest(redirect_uris=['https://example.com/rp1/callback'], application_type='web', response_types=['code'], signing_key=rp_jwks['keys'][0], jwks_uri_signed='https://example.com/rp1/jwks.jws') print(70 * "-") print('Client Registration request') print(70 * "-") print_lines( json.dumps(rreq.to_dict(), sort_keys=True, indent=2, separators=(',', ': '))) # ----------------------------------------------------------------------------- # Developer signs Registration Request once per federation # ----------------------------------------------------------------------------- # adds the developers software statement rreq.update({ "software_statements": [dev_swamid_sost], }) print(70 * "-") print('Developer adds software_statement to the Client Registration request')