def test_authorized_true(self): def fake_token(token): def fake_send(r, **kwargs): resp = mock.MagicMock() resp.text = json.dumps(token) return resp return fake_send url = "https://example.com/token" for client in self.clients: sess = OAuth2Session(client=client) sess.send = fake_token(self.token) self.assertFalse(sess.authorized) if isinstance(client, LegacyApplicationClient): # this client requires a username+password # if unset, an error will be raised self.assertRaises(ValueError, sess.fetch_token, url) self.assertRaises(ValueError, sess.fetch_token, url, username="******") self.assertRaises(ValueError, sess.fetch_token, url, password="******") # otherwise it will pass sess.fetch_token(url, username="******", password="******") else: sess.fetch_token(url) self.assertTrue(sess.authorized)
def test_mtls(self): cert = ( "testsomething.example-client.pem", "testsomething.example-client-key.pem", ) def verifier(r, **kwargs): self.assertIn("cert", kwargs) self.assertEqual(cert, kwargs["cert"]) self.assertIn("client_id=" + self.client_id, r.body) resp = mock.MagicMock() resp.text = json.dumps(self.token) return resp for client in self.clients: sess = OAuth2Session(client=client) sess.send = verifier if isinstance(client, LegacyApplicationClient): sess.fetch_token( "https://i.b", include_client_id=True, cert=cert, username="******", password="******", ) else: sess.fetch_token("https://i.b", include_client_id=True, cert=cert)
async def _make_session(self, token: str = None, state: str = None, scope: list = None) -> OAuth2Session: """A low level method used for creating OAuth2 session. Parameters ---------- token : str, optional The authorization token to use which was previously received from authorization code grant. state : str, optional The state to use for OAuth2 session. scope : list, optional List of valid `Discord OAuth2 Scopes <https://discordapp.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes>`_. Returns ------- OAuth2Session An instance of OAuth2Session class. """ return OAuth2Session(client_id=self.client_id, token=token or await self.get_authorization_token(), state=state or session.get("DISCORD_OAUTH2_STATE"), scope=scope, redirect_uri=self.redirect_uri, auto_refresh_kwargs={ 'client_id': self.client_id, 'client_secret': self.__client_secret, }, auto_refresh_url=configs.DISCORD_TOKEN_URL, token_updater=self.save_authorization_token)
def test_authorization_url(self): url = "https://example.com/authorize?foo=bar" web = WebApplicationClient(self.client_id) s = OAuth2Session(client=web) auth_url, state = s.authorization_url(url) self.assertIn(state, auth_url) self.assertIn(self.client_id, auth_url) self.assertIn("response_type=code", auth_url) mobile = MobileApplicationClient(self.client_id) s = OAuth2Session(client=mobile) auth_url, state = s.authorization_url(url) self.assertIn(state, auth_url) self.assertIn(self.client_id, auth_url) self.assertIn("response_type=token", auth_url)
async def oauth_redirect(): twitch = OAuth2Session(OAUTH_CLIENT_ID, state=session["oauth_state"], redirect_uri=OAUTH_REDIRECT_URL) token: OAuth2Token = await twitch.fetch_token( "https://id.twitch.tv/oauth2/token", include_client_id=True, client_secret=OAUTH_CLIENT_SECRET, authorization_response=request.url.replace("http://", "https://"), ) resp = await twitch.get( "https://api.twitch.tv/helix/users", headers={ "client-id": OAUTH_CLIENT_ID, "authorization": f"Bearer " f"{token.get('access_token')}", }, ) if resp.status == 200: body = await resp.json() user = body["data"][0] username = user["login"] log.info(f"Logging in as user {username}") login_user(AuthUser(username)) return redirect(url_for("index"))
def test_access_token_proxy(self): sess = OAuth2Session("test-id") self.assertIsNone(sess.access_token) sess.access_token = "test-token" self.assertEqual(sess.access_token, "test-token") sess._client.access_token = "different-token" self.assertEqual(sess.access_token, "different-token") del sess.access_token self.assertIsNone(sess.access_token)
def test_client_id_proxy(self): sess = OAuth2Session("test-id") self.assertEqual(sess.client_id, "test-id") sess.client_id = "different-id" self.assertEqual(sess.client_id, "different-id") sess._client.client_id = "something-else" self.assertEqual(sess.client_id, "something-else") del sess.client_id self.assertIsNone(sess.client_id)
def test_web_app_fetch_token(self): # Ensure the state parameter is used, see issue #105. client = OAuth2Session("someclientid", state="somestate") self.assertRaises( MismatchingStateError, client.fetch_token, "https://i.b/token", authorization_response="https://i.b/no-state?code=abc", )
def setUp(self): mocker = requests_mock.Mocker() mocker.post( "https://api.weibo.com/oauth2/access_token", json={"access_token": "weibo"} ) mocker.start() self.addCleanup(mocker.stop) weibo = OAuth2Session("someclientid", redirect_uri="https://i.b") self.session = weibo_compliance_fix(weibo)
def setUp(self): self.mocker = requests_mock.Mocker() self.mocker.post( "https://api.fitbit.com/oauth2/token", json={"errors": [{"errorType": "invalid_grant"}]}, ) self.mocker.start() self.addCleanup(self.mocker.stop) fitbit = OAuth2Session("someclientid", redirect_uri="https://i.b") self.session = fitbit_compliance_fix(fitbit)
def setUp(self): mocker = requests_mock.Mocker() mocker.post( "https://login.mailchimp.com/oauth2/token", json={"access_token": "mailchimp", "expires_in": 0, "scope": None}, ) mocker.start() self.addCleanup(mocker.stop) mailchimp = OAuth2Session("someclientid", redirect_uri="https://i.b") self.session = mailchimp_compliance_fix(mailchimp)
def setUp(self): mocker = requests_mock.Mocker() mocker.post( "https://graph.facebook.com/oauth/access_token", text="access_token=urlencoded", headers={"Content-Type": "text/plain"}, ) mocker.start() self.addCleanup(mocker.stop) facebook = OAuth2Session("someclientid", redirect_uri="https://i.b") self.session = facebook_compliance_fix(facebook)
def test_add_token(self): token = "Bearer " + self.token["access_token"] def verifier(r, **kwargs): auth_header = r.headers.get(str("Authorization"), None) self.assertEqual(auth_header, token) resp = mock.MagicMock() resp.cookes = [] return resp for client in self.all_clients: sess = OAuth2Session(client=client, token=self.token) sess.send = verifier sess.get("https://i.b")
async def login_post(): form = LoginForm() if form["guest"].data: log.info("Logging in as a guest") login_user(AuthUser("guest")) return redirect(url_for("index")) else: github = OAuth2Session(OAUTH_CLIENT_ID, redirect_uri=OAUTH_REDIRECT_URL) authorization_url, state = github.authorization_url( "https://id.twitch.tv/oauth2/authorize") # State is used to prevent CSRF, keep this for later. session["oauth_state"] = state return redirect(authorization_url)
def test_token_proxy(self): token = {"access_token": "test-access"} sess = OAuth2Session("test-id", token=token) self.assertEqual(sess.access_token, "test-access") self.assertEqual(sess.token, token) token["access_token"] = "something-else" sess.token = token self.assertEqual(sess.access_token, "something-else") self.assertEqual(sess.token, token) sess._client.access_token = "different-token" token["access_token"] = "different-token" self.assertEqual(sess.access_token, "different-token") self.assertEqual(sess.token, token) # can't delete token attribute with self.assertRaises(AttributeError): del sess.token
def setUp(self): mocker = requests_mock.Mocker() mocker.post( "https://shop.plentymarkets-cloud02.com", json={ "accessToken": "ecUN1r8KhJewMCdLAmpHOdZ4O0ofXKB9zf6CXK61", "tokenType": "Bearer", "expiresIn": 86400, "refreshToken": "iG2kBGIjcXaRE4xmTVUnv7xwxX7XMcWCHqJmFaSX", }, headers={"Content-Type": "application/json"}, ) mocker.start() self.addCleanup(mocker.stop) plentymarkets = OAuth2Session("someclientid", redirect_uri="https://i.b") self.session = plentymarkets_compliance_fix(plentymarkets)
def test_cleans_previous_token_before_fetching_new_one(self): """Makes sure the previous token is cleaned before fetching a new one. The reason behind it is that, if the previous token is expired, this method shouldn't fail with a TokenExpiredError, since it's attempting to get a new one (which shouldn't be expired). """ new_token = deepcopy(self.token) past = time.time() - 7200 now = time.time() self.token["expires_at"] = past new_token["expires_at"] = now + 3600 url = "https://example.com/token" with mock.patch("time.time", lambda: now): for client in self.clients: sess = OAuth2Session(client=client, token=self.token) sess.send = fake_token(new_token) if isinstance(client, LegacyApplicationClient): # this client requires a username+password # if unset, an error will be raised self.assertRaises(ValueError, sess.fetch_token, url) self.assertRaises(ValueError, sess.fetch_token, url, username="******") self.assertRaises(ValueError, sess.fetch_token, url, password="******") # otherwise it will pass self.assertEqual( sess.fetch_token(url, username="******", password="******"), new_token, ) else: self.assertEqual(sess.fetch_token(url), new_token)
def setUp(self): mocker = requests_mock.Mocker() mocker.request( method="GET", url="https://api.instagram.com/v1/users/self", json={ "data": { "id": "1574083", "username": "******", "full_name": "Snoop Dogg", "profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1574083_75sq_1295469061.jpg", "bio": "This is my bio", "website": "http://snoopdogg.com", "is_business": False, "counts": {"media": 1320, "follows": 420, "followed_by": 3410}, } }, ) mocker.start() self.addCleanup(mocker.stop) instagram = OAuth2Session("someclientid", redirect_uri="https://i.b") self.session = instagram_compliance_fix(instagram)
def setUp(self): mocker = requests_mock.Mocker() mocker.post( "https://slack.com/api/oauth.access", json={"access_token": "xoxt-23984754863-2348975623103", "scope": "read"}, ) for method in ("GET", "POST"): mocker.request( method=method, url="https://slack.com/api/auth.test", json={ "ok": True, "url": "https://myteam.slack.com/", "team": "My Team", "user": "******", "team_id": "T12345", "user_id": "U12345", }, ) mocker.start() self.addCleanup(mocker.stop) slack = OAuth2Session("someclientid", redirect_uri="https://i.b") self.session = slack_compliance_fix(slack)
def __init__(self): self.client = GraphqlClient(FFLOGS_URL) token_client = BackendApplicationClient(client_id=config.__fflogs_client_id__) self.oauth = OAuth2Session(client=token_client)
def test_refresh_token_request(self): self.expired_token = dict(self.token) self.expired_token["expires_in"] = "-1" del self.expired_token["expires_at"] def fake_refresh(r, **kwargs): if "/refresh" in r.url: self.assertNotIn("Authorization", r.headers) resp = mock.MagicMock() resp.text = json.dumps(self.token) return resp # No auto refresh setup for client in self.clients: sess = OAuth2Session(client=client, token=self.expired_token) self.assertRaises(TokenExpiredError, sess.get, "https://i.b") # Auto refresh but no auto update for client in self.clients: sess = OAuth2Session( client=client, token=self.expired_token, auto_refresh_url="https://i.b/refresh", ) sess.send = fake_refresh self.assertRaises(TokenUpdated, sess.get, "https://i.b") # Auto refresh and auto update def token_updater(token): self.assertEqual(token, self.token) for client in self.clients: sess = OAuth2Session( client=client, token=self.expired_token, auto_refresh_url="https://i.b/refresh", token_updater=token_updater, ) sess.send = fake_refresh sess.get("https://i.b") def fake_refresh_with_auth(r, **kwargs): if "/refresh" in r.url: self.assertIn("Authorization", r.headers) encoded = b64encode("{client_id}:{client_secret}".format( client_id=self.client_id, client_secret=self.client_secret).encode("latin1")) content = "Basic {encoded}".format( encoded=encoded.decode("latin1")) self.assertEqual(r.headers["Authorization"], content) resp = mock.MagicMock() resp.text = json.dumps(self.token) return resp for client in self.clients: sess = OAuth2Session( client=client, token=self.expired_token, auto_refresh_url="https://i.b/refresh", token_updater=token_updater, ) sess.send = fake_refresh_with_auth sess.get( "https://i.b", client_id=self.client_id, client_secret=self.client_secret, )
def test_token_from_fragment(self): mobile = MobileApplicationClient(self.client_id) response_url = "https://i.b/callback#" + urlencode(self.token.items()) sess = OAuth2Session(client=mobile) self.assertEqual(sess.token_from_fragment(response_url), self.token)
def test_fetch_token(self): url = "https://example.com/token" for client in self.clients: sess = OAuth2Session(client=client, token=self.token) sess.send = fake_token(self.token) if isinstance(client, LegacyApplicationClient): # this client requires a username+password # if unset, an error will be raised self.assertRaises(ValueError, sess.fetch_token, url) self.assertRaises(ValueError, sess.fetch_token, url, username="******") self.assertRaises(ValueError, sess.fetch_token, url, password="******") # otherwise it will pass self.assertEqual( sess.fetch_token(url, username="******", password="******"), self.token, ) else: self.assertEqual(sess.fetch_token(url), self.token) error = {"error": "invalid_request"} for client in self.clients: sess = OAuth2Session(client=client, token=self.token) sess.send = fake_token(error) if isinstance(client, LegacyApplicationClient): # this client requires a username+password # if unset, an error will be raised self.assertRaises(ValueError, sess.fetch_token, url) self.assertRaises(ValueError, sess.fetch_token, url, username="******") self.assertRaises(ValueError, sess.fetch_token, url, password="******") # otherwise it will pass self.assertRaises( OAuth2Error, sess.fetch_token, url, username="******", password="******", ) else: self.assertRaises(OAuth2Error, sess.fetch_token, url) # there are different scenarios in which the `client_id` can be specified # reference `oauthlib.tests.oauth2.rfc6749.clients.test_web_application.WebApplicationClientTest.test_prepare_request_body` # this only needs to test WebApplicationClient client = self.client_WebApplication client.tester = True # this should be a tuple of (r.url, r.body, r.headers.get('Authorization')) _fetch_history = [] def fake_token_history(token): def fake_send(r, **kwargs): resp = mock.MagicMock() resp.text = json.dumps(token) _fetch_history.append( (r.url, r.body, r.headers.get("Authorization", None))) return resp return fake_send sess = OAuth2Session(client=client, token=self.token) sess.send = fake_token_history(self.token) expected_auth_header = _basic_auth_str(self.client_id, self.client_secret) # scenario 1 - default request # this should send the `client_id` in the headers, as that is recommended by the RFC self.assertEqual( sess.fetch_token(url, client_secret="someclientsecret"), self.token) self.assertEqual(len(_fetch_history), 1) self.assertNotIn("client_id", _fetch_history[0][1]) # no `client_id` in the body self.assertNotIn( "client_secret", _fetch_history[0][1]) # no `client_secret` in the body self.assertEqual( _fetch_history[0][2], expected_auth_header) # ensure a Basic Authorization header # scenario 2 - force the `client_id` into the body self.assertEqual( sess.fetch_token(url, client_secret="someclientsecret", include_client_id=True), self.token, ) self.assertEqual(len(_fetch_history), 2) self.assertIn("client_id=%s" % self.client_id, _fetch_history[1][1]) self.assertIn("client_secret=%s" % self.client_secret, _fetch_history[1][1]) self.assertEqual(_fetch_history[1][2], None) # ensure NO Basic Authorization header # scenario 3 - send in an auth object auth = requests.auth.HTTPBasicAuth(self.client_id, self.client_secret) self.assertEqual(sess.fetch_token(url, auth=auth), self.token) self.assertEqual(len(_fetch_history), 3) self.assertNotIn("client_id", _fetch_history[2][1]) # no `client_id` in the body self.assertNotIn( "client_secret", _fetch_history[2][1]) # no `client_secret` in the body self.assertEqual( _fetch_history[2][2], expected_auth_header) # ensure a Basic Authorization header # scenario 4 - send in a username/password combo # this should send the `client_id` in the headers, like scenario 1 self.assertEqual( sess.fetch_token(url, username=self.user_username, password=self.user_password), self.token, ) self.assertEqual(len(_fetch_history), 4) self.assertNotIn("client_id", _fetch_history[3][1]) # no `client_id` in the body self.assertNotIn( "client_secret", _fetch_history[3][1]) # no `client_secret` in the body self.assertEqual( _fetch_history[0][2], expected_auth_header) # ensure a Basic Authorization header self.assertIn("username=%s" % self.user_username, _fetch_history[3][1]) self.assertIn("password=%s" % self.user_password, _fetch_history[3][1]) # scenario 5 - send data in `params` and not in `data` for providers # that expect data in URL self.assertEqual( sess.fetch_token(url, client_secret="somesecret", force_querystring=True), self.token, ) self.assertIn("code=%s" % CODE, _fetch_history[4][0]) # some quick tests for valid ways of supporting `client_secret` # scenario 2b - force the `client_id` into the body; but the `client_secret` is `None` self.assertEqual( sess.fetch_token(url, client_secret=None, include_client_id=True), self.token, ) self.assertEqual(len(_fetch_history), 6) self.assertIn("client_id=%s" % self.client_id, _fetch_history[5][1]) self.assertNotIn( "client_secret=", _fetch_history[5][1]) # no `client_secret` in the body self.assertEqual(_fetch_history[5][2], None) # ensure NO Basic Authorization header # scenario 2c - force the `client_id` into the body; but the `client_secret` is an empty string self.assertEqual( sess.fetch_token(url, client_secret="", include_client_id=True), self.token) self.assertEqual(len(_fetch_history), 7) self.assertIn("client_id=%s" % self.client_id, _fetch_history[6][1]) self.assertIn("client_secret=", _fetch_history[6][1]) self.assertEqual(_fetch_history[6][2], None) # ensure NO Basic Authorization header
def test_authorized_false(self): sess = OAuth2Session("someclientid") self.assertFalse(sess.authorized)