0
# Authentication
1
2
The TD Ameritrade Python API provides OAuth 2.0 authentication through multiple approaches: command-line based authentication and Flask web-based authentication. The system handles access tokens, refresh tokens, and credential storage automatically.
3
4
## Core Imports
5
6
```python
7
from td.oauth import run, shutdown_server
8
from td.app.auth import FlaskTDAuth
9
```
10
11
## Capabilities
12
13
### Flask OAuth Server
14
15
Command-line OAuth authentication using a local Flask server for handling the OAuth callback flow.
16
17
```python { .api }
18
def run(flask_client, close_after: bool = True) -> None: ...
19
def shutdown_server() -> None: ...
20
```
21
22
**Functions:**
23
- `run()`: Starts a Flask server to handle OAuth authentication flow
24
- `shutdown_server()`: Gracefully shuts down the Flask OAuth server
25
26
**Parameters for run():**
27
- `flask_client`: Flask application instance configured for OAuth
28
- `close_after`: Whether to automatically close the server after authentication
29
30
### Flask Routes
31
32
The OAuth server exposes several routes for the authentication flow:
33
34
- `/` - Home route displaying authentication status
35
- `/login` - Initiates the OAuth login process
36
- `/login/callback` - Handles OAuth callback from TD Ameritrade
37
- `/login/refresh` - Handles token refresh requests
38
- `/shutdown` - Shuts down the OAuth server
39
40
### FlaskTDAuth Class
41
42
Advanced OAuth authentication helper using Flask and requests-oauthlib for more control over the authentication process.
43
44
```python { .api }
45
class FlaskTDAuth:
46
def __init__(self, client_id: str, redirect_uri: str) -> None: ...
47
def authorization_url(self) -> str: ...
48
def grab_access_token_and_refresh_token(self, url: str) -> Dict: ...
49
def grab_refresh_token(self) -> Dict: ...
50
def save_token(self, token_dict: Dict) -> None: ...
51
def save_state(self, token_dict: Dict) -> None: ...
52
```
53
54
**Methods:**
55
- `authorization_url()`: Generates the OAuth authorization URL for user authentication
56
- `grab_access_token_and_refresh_token()`: Exchanges callback URL for access and refresh tokens
57
- `grab_refresh_token()`: Refreshes expired access token using refresh token
58
- `save_token()`: Saves token information to secure storage
59
- `save_state()`: Saves authentication state and credentials
60
61
## Usage Examples
62
63
### Basic Authentication Flow
64
65
```python
66
from td.client import TDClient
67
68
# Initialize client with OAuth parameters
69
client = TDClient(
70
client_id='your_client_id@AMER.OAUTHAP',
71
redirect_uri='http://localhost:8080/callback',
72
account_number='your_account_number'
73
)
74
75
# Login using default command-line OAuth flow
76
client.login()
77
78
# Client is now authenticated and ready for API calls
79
quotes = client.get_quotes(['AAPL', 'MSFT'])
80
```
81
82
### Flask-based Authentication
83
84
```python
85
from td.client import TDClient
86
87
# Initialize client with Flask authentication flow
88
client = TDClient(
89
client_id='your_client_id@AMER.OAUTHAP',
90
redirect_uri='http://localhost:8080/callback',
91
auth_flow='flask'
92
)
93
94
# Login using Flask web-based OAuth flow
95
client.login()
96
97
# Authentication will open a web browser for user consent
98
# Server will handle callback automatically
99
```
100
101
### Manual OAuth with FlaskTDAuth
102
103
```python
104
from td.app.auth import FlaskTDAuth
105
106
# Initialize Flask OAuth helper
107
auth = FlaskTDAuth(
108
client_id='your_client_id@AMER.OAUTHAP',
109
redirect_uri='http://localhost:8080/callback'
110
)
111
112
# Get authorization URL
113
auth_url = auth.authorization_url()
114
print(f"Please visit: {auth_url}")
115
116
# After user authorization, handle callback
117
# (callback_url would be received from TD Ameritrade)
118
callback_url = "http://localhost:8080/callback?code=..."
119
tokens = auth.grab_access_token_and_refresh_token(callback_url)
120
121
# Save tokens
122
auth.save_token(tokens)
123
auth.save_state(tokens)
124
```
125
126
### Token Management
127
128
```python
129
from td.client import TDClient
130
131
# Initialize client
132
client = TDClient(
133
client_id='your_client_id@AMER.OAUTHAP',
134
redirect_uri='http://localhost:8080/callback',
135
credentials_path='/path/to/credentials.json'
136
)
137
138
# Login will automatically load saved credentials if available
139
client.login()
140
141
# Manual token refresh
142
new_token = client.grab_access_token()
143
print(f"New access token: {new_token}")
144
145
# Get new refresh token
146
refresh_token = client.grab_refresh_token()
147
print(f"New refresh token: {refresh_token}")
148
149
# Manual OAuth URL generation
150
oauth_url = client.grab_url()
151
print(f"OAuth URL: {oauth_url}")
152
```
153
154
### Custom OAuth Server
155
156
```python
157
from td.oauth import run, shutdown_server
158
from flask import Flask
159
160
# Create custom Flask app
161
app = Flask(__name__)
162
163
# Configure OAuth settings
164
app.config['CLIENT_ID'] = 'your_client_id@AMER.OAUTHAP'
165
app.config['REDIRECT_URI'] = 'http://localhost:8080/callback'
166
167
# Run OAuth server
168
try:
169
run(app, close_after=True)
170
except KeyboardInterrupt:
171
shutdown_server()
172
```
173
174
### Multiprocessing Safe Authentication
175
176
```python
177
from td.client import TDClient
178
179
# Initialize client with multiprocessing safety
180
client = TDClient(
181
client_id='your_client_id@AMER.OAUTHAP',
182
redirect_uri='http://localhost:8080/callback',
183
_multiprocessing_safe=True
184
)
185
186
# Login - safe for use across multiple processes
187
client.login()
188
189
# Token cache will be shared across processes
190
# Only one process will refresh tokens when they expire
191
```
192
193
### Exchange Authorization Code
194
195
```python
196
from td.client import TDClient
197
198
# Initialize client
199
client = TDClient(
200
client_id='your_client_id@AMER.OAUTHAP',
201
redirect_uri='http://localhost:8080/callback'
202
)
203
204
# Exchange authorization code for tokens
205
# (authorization_code obtained from OAuth callback)
206
authorization_code = "received_from_callback"
207
tokens = client.exchange_code_for_token(
208
code=authorization_code,
209
return_refresh_token=True
210
)
211
212
print(f"Access Token: {tokens['access_token']}")
213
print(f"Refresh Token: {tokens['refresh_token']}")
214
```
215
216
### Logout and Session Management
217
218
```python
219
from td.client import TDClient
220
221
# Initialize and authenticate
222
client = TDClient(
223
client_id='your_client_id@AMER.OAUTHAP',
224
redirect_uri='http://localhost:8080/callback'
225
)
226
client.login()
227
228
# Use API
229
accounts = client.get_accounts()
230
231
# Logout to clear session
232
client.logout()
233
234
# Client is now logged out and credentials are cleared
235
# Need to login again for further API calls
236
```
237
238
## Authentication Configuration
239
240
### Client ID Format
241
242
TD Ameritrade requires the client ID to include the OAuth application suffix:
243
- Format: `your_client_id@AMER.OAUTHAP`
244
- Example: `MYAPP12345@AMER.OAUTHAP`
245
246
### Redirect URI
247
248
The redirect URI must match exactly what was configured in your TD Ameritrade developer application:
249
- Common development URI: `http://localhost:8080/callback`
250
- Production URIs must use HTTPS
251
252
### Credentials Storage
253
254
The library automatically manages credential storage:
255
- Default location: User's home directory under `.td_python_api/`
256
- Custom path can be specified with `credentials_path` parameter
257
- Credentials include access token, refresh token, and expiration information
258
259
### Authentication Errors
260
261
Handle authentication errors using the exception classes:
262
263
```python
264
from td.exceptions import TknExpError, ForbidError
265
266
try:
267
client.login()
268
quotes = client.get_quotes(['AAPL'])
269
except TknExpError:
270
print("Token expired, need to re-authenticate")
271
client.login()
272
except ForbidError:
273
print("Access forbidden, check API permissions")
274
```