@@ -17,61 +17,41 @@ plan on distributing your app, or if you plan on running it on a server and
1717allowing access to other users, these login flows are not for you.
1818
1919
20- ---------------
21- OAuth Refresher
22- ---------------
20+ ------------------------
21+ The Quick and Easy Route
22+ ------------------------
2323
24- *This section is purely for the curious. If you already understand OAuth (wow,
25- congrats) or if you don't care and just want to use this package as fast as
26- possible, feel free to skip this section. If you encounter any weird behavior,
27- this section may help you understand what's going on. *
24+ If all you want to do is create a client, you should use
25+ :func: `~schwab.auth.easy_client `. This method will attempt to create a client in
26+ a way that's appropriate to the context in which you're running:
2827
29- Webapp authentication is a complex beast. The OAuth protocol was created to
30- allow applications to access one anothers' APIs securely and with the minimum
31- level of trust possible. A full treatise on this topic is well beyond the scope
32- of this guide, but in order to alleviate some of the complexity that seems to
33- surround this part of the API, let's give a quick explanation of how OAuth works
34- in the context of Schwab's API.
28+ * If you've already got a token at ``token_path ``,
29+ :func: `load it <schwab.auth.client_from_token_file> ` and continue. Otherwise
30+ create a new one.
31+ * In desktop environments, :func: `start a web browser
32+ <schwab.auth.client_from_login_flow> ` in which you can sign in, and
33+ automatically capture the created token.
34+ * In a notebook like Google Colab or Jupyter, instead run the :func: `manual
35+ flow <schwab.auth.client_from_manual_flow> `.
3536
36- The first thing to understand is that the OAuth webapp flow was created to allow
37- client-side applications consisting of a webapp frontend and a remotely hosted
38- backend to interact with a third party API. Unlike the `backend application flow
39- <https://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html
40- #backend-application-flow> `__, in which the remotely hosted backend has a secret
41- which allows it to access the API on its own behalf, the webapp flow allows
42- either the webapp frontend or the remotely host backend to access the API *on
43- behalf of its users *.
37+ Here's how you can use it. If for some reason this doesn't work, please report
38+ your issues in the `Discord server <https://discord.gg/BEr6y6Xqyv >`__. See
39+ :func: `~schwab.auth.easy_client ` for details:
4440
45- If you've ever installed a GitHub, Facebook, Twitter, GMail, etc. app, you've
46- seen this flow. You click on the "install" link, a login window pops up, you
47- enter your password, and you're presented with a page that asks whether you want
48- to grant the app access to your account.
41+ .. code-block :: python
4942
50- Here's what's happening under the hood. The window that pops up is the
51- authentication URL, which opens a login page for the target API. The aim is to
52- allow the user to input their username and password without the webapp frontend
53- or the remotely hosted backend seeing it. On web browsers, this is accomplished
54- using the browser's refusal to send credentials from one domain to another.
55-
56- Once login here is successful, the API replies with a redirect to a URL that the
57- remotely hosted backend controls. This is the callback URL. This redirect will
58- contain a code which securely identifies the user to the API, embedded in the
59- query of the request.
60-
61- You might think that code is enough to access the API, and it would be if the
62- API author were willing to sacrifice long-term security. The exact reasons why
63- it doesn't work involve some deep security topics like robustness against replay
64- attacks and session duration limitation, but we'll skip them here.
43+ from schwab.auth import easy_client
6544
66- This code is useful only for fetching a token from the authentication endpoint.
67- *This token * is what we want: a secure secret which the client can use to access
68- API endpoints, and can be refreshed over time.
45+ # Follow the instructions on the screen to authenticate your client.
46+ c = easy_client(
47+ api_key = ' APIKEY' ,
48+ app_secret = ' APP_SECRET' ,
49+ callback_url = ' https://127.0.0.1' ,
50+ token_path = ' /tmp/token.json' )
6951
70- If you've gotten this far and your head isn't spinning, you haven't been paying
71- attention. Security-sensitive protocols can be very complicated, and you should
72- **never ** build your own implementation. Fortunately there exist very robust
73- implementations of this flow, and ``schwab-py ``'s authentication module makes
74- using them easy.
52+ resp = c.get_price_history_every_day(' AAPL' )
53+ assert resp.status_code == httpx.codes.OK
54+ history = resp.json()
7555
7656
7757 .. _login_flow :
8868.. _manual_login :
8969
9070If for some reason you cannot open a web browser, such as when running in a
91- cloud environment, this function will guide you through the process of manually
92- creating a token by copy-pasting relevant URLs.
71+ cloud environment or a notebook , this function will guide you through the
72+ process of manually creating a token by copy-pasting relevant URLs.
9373
9474.. autofunction :: schwab.auth.client_from_manual_flow
9575
@@ -204,6 +184,64 @@ seeing this error, you have no choice but to delete your old token file and
204184create a new one.
205185
206186
187+ ---------------
188+ OAuth Refresher
189+ ---------------
190+
191+ *This section is purely for the curious. If you already understand OAuth (wow,
192+ congrats) or if you don't care and just want to use this package as fast as
193+ possible, feel free to skip this section. If you encounter any weird behavior,
194+ this section may help you understand what's going on. *
195+
196+ Webapp authentication is a complex beast. The OAuth protocol was created to
197+ allow applications to access one anothers' APIs securely and with the minimum
198+ level of trust possible. A full treatise on this topic is well beyond the scope
199+ of this guide, but in order to alleviate some of the complexity that seems to
200+ surround this part of the API, let's give a quick explanation of how OAuth works
201+ in the context of Schwab's API.
202+
203+ The first thing to understand is that the OAuth webapp flow was created to allow
204+ client-side applications consisting of a webapp frontend and a remotely hosted
205+ backend to interact with a third party API. Unlike the `backend application flow
206+ <https://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html
207+ #backend-application-flow> `__, in which the remotely hosted backend has a secret
208+ which allows it to access the API on its own behalf, the webapp flow allows
209+ either the webapp frontend or the remotely host backend to access the API *on
210+ behalf of its users *.
211+
212+ If you've ever installed a GitHub, Facebook, Twitter, GMail, etc. app, you've
213+ seen this flow. You click on the "install" link, a login window pops up, you
214+ enter your password, and you're presented with a page that asks whether you want
215+ to grant the app access to your account.
216+
217+ Here's what's happening under the hood. The window that pops up is the
218+ authentication URL, which opens a login page for the target API. The aim is to
219+ allow the user to input their username and password without the webapp frontend
220+ or the remotely hosted backend seeing it. On web browsers, this is accomplished
221+ using the browser's refusal to send credentials from one domain to another.
222+
223+ Once login here is successful, the API replies with a redirect to a URL that the
224+ remotely hosted backend controls. This is the callback URL. This redirect will
225+ contain a code which securely identifies the user to the API, embedded in the
226+ query of the request.
227+
228+ You might think that code is enough to access the API, and it would be if the
229+ API author were willing to sacrifice long-term security. The exact reasons why
230+ it doesn't work involve some deep security topics like robustness against replay
231+ attacks and session duration limitation, but we'll skip them here.
232+
233+ This code is useful only for fetching a token from the authentication endpoint.
234+ *This token * is what we want: a secure secret which the client can use to access
235+ API endpoints, and can be refreshed over time.
236+
237+ If you've gotten this far and your head isn't spinning, you haven't been paying
238+ attention. Security-sensitive protocols can be very complicated, and you should
239+ **never ** build your own implementation. Fortunately there exist very robust
240+ implementations of this flow, and ``schwab-py ``'s authentication module makes
241+ using them easy.
242+
243+
244+
207245---------------
208246Troubleshooting
209247---------------
0 commit comments