Skip to content

Commit 5ae429e

Browse files
feat: Example for Access Token For Connection
1 parent 53e3ea0 commit 5ae429e

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed

examples/AccessTokenForConnection.md

+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# Auth0 Access Token For Connection Integration Guide
2+
This guide demonstrates how to integrate Auth0's federated access token functionality in a Flask application. This approach allows your application to authenticate users once with Auth0 and then access multiple third-party services using tokens that Auth0 manages on your behalf.
3+
4+
## Prerequisites
5+
- Python 3.7+
6+
- Auth0 account with a configured application
7+
- Environment variables for Auth0 credentials
8+
9+
## Step 1: Clone the Sample Application
10+
```bash
11+
git clone https://github.com/auth0-samples/auth0-python-web-app.git
12+
cd auth0-python-web-app
13+
```
14+
15+
## Step 2: Install Dependencies
16+
```bash
17+
pip install -r requirements.txt
18+
```
19+
## Step 4: Using Auth0 SDK for Authentication
20+
Before implementing the OAuth flow, understand how to use the Auth0 SDK for direct authentication:
21+
```python
22+
from auth0.authentication import GetToken
23+
# Initialize the GetToken object with your Auth0 domain and client credentials
24+
auth_client = GetToken('your-domain.us.auth0.com', 'your-client-id', client_secret='your-client-secret')
25+
```
26+
## Step 5: Modify the Login Route
27+
Replace the standard OAuth login route with a custom implementation that supports federated access:
28+
```python
29+
@app.route("/login")
30+
def login():
31+
"""Manually build the Auth0 authorization URL for redirection."""
32+
# Clear any existing session
33+
session.clear()
34+
# Generate a secure state parameter for OAuth flow
35+
session['oauth_state'] = secrets.token_urlsafe(16)
36+
# Get configuration values
37+
auth0_domain = env.get("AUTH0_DOMAIN")
38+
client_id = env.get("AUTH0_CLIENT_ID")
39+
client_secret = env.get("AUTH0_CLIENT_SECRET")
40+
# Generate the callback URL
41+
redirect_uri = url_for("callback", _external=True)
42+
# Construct the Auth0 authorization URL
43+
auth_url = (
44+
f"https://{auth0_domain}/authorize?"
45+
+ urlencode({
46+
"client_id": client_id,
47+
"client_secret": client_secret,
48+
"response_type": "code",
49+
"redirect_uri": redirect_uri,
50+
"access_type": "offline",
51+
"prompt": "consent",
52+
"scope": "offline_access openid profile email",
53+
"grant_type": "authorization_code",
54+
"state": session['oauth_state'],
55+
})
56+
)
57+
return redirect(auth_url)
58+
```
59+
## Step 6: Update Callback Handler
60+
Update the callback handler to work with the custom login route:
61+
```python
62+
@app.route("/callback")
63+
def callback():
64+
# Verify state parameter
65+
if session.get('oauth_state') != request.args.get('state'):
66+
return "State verification failed", 400
67+
# Get the authorization code
68+
code = request.args.get("code")
69+
# Exchange code for tokens
70+
token_url = f"https://{env.get('AUTH0_DOMAIN')}/oauth/token"
71+
token_payload = {
72+
"grant_type": "authorization_code",
73+
"client_id": env.get("AUTH0_CLIENT_ID"),
74+
"client_secret": env.get("AUTH0_CLIENT_SECRET"),
75+
"code": code,
76+
"redirect_uri": url_for("callback", _external=True)
77+
}
78+
# Get tokens from Auth0
79+
token_response = requests.post(token_url, json=token_payload).json()
80+
# Store tokens in session (including refresh_token)
81+
session["tokens"] = {
82+
"access_token": token_response.get("access_token"),
83+
"refresh_token": token_response.get("refresh_token"),
84+
"id_token": token_response.get("id_token")
85+
}
86+
# Get user info
87+
user_info_url = f"https://{env.get('AUTH0_DOMAIN')}/userinfo"
88+
user_info_headers = {"Authorization": f"Bearer {token_response.get('access_token')}"}
89+
user_info = requests.get(user_info_url, headers=user_info_headers).json()
90+
# Store user info in session
91+
session["user"] = user_info
92+
return redirect("/")
93+
```
94+
## Step 7: Implement Federated Token Route
95+
Add a new route for handling federated connections:
96+
```python
97+
@app.route("/federated/<connection>")
98+
def federated_login(connection):
99+
"""Handles federated login flow."""
100+
try:
101+
# Store connection name
102+
connection_name = connection
103+
# Attempt to get refresh token from session
104+
refresh_token = session.get("tokens", {}).get("refresh_token")
105+
# Call SDK federated connection function
106+
federated_token_response = auth_client.access_token_for_connection(
107+
subject_token=refresh_token,
108+
subject_token_type="urn:ietf:params:oauth:token-type:refresh_token",
109+
requested_token_type="http://auth0.com/oauth/token-type/federated-connection-access-token",
110+
connection=connection_name,
111+
grant_type="urn:auth0:params:oauth:grant-type:token-exchange:federated-connection-access-token"
112+
)
113+
# Check for successful token retrieval
114+
if not federated_token_response:
115+
return "Failed to retrieve federated access token", 500
116+
# Extract the access token
117+
access_token = federated_token_response["access_token"]
118+
# Call the third-party API using the federated token
119+
api_response = call_third_party_api(access_token)
120+
# Handle API response
121+
if not api_response:
122+
return "API returned an empty response. Check authentication and scopes.", 500
123+
# Prepare and return the response to the user
124+
return render_template(
125+
"federated_result.html",
126+
connection=connection_name,
127+
data=api_response
128+
)
129+
except Exception as e:
130+
return f"An error occurred: {str(e)}", 500
131+
```
132+
133+
## Step 8: Implement Third-Party API Call Function
134+
Create a helper function to call the third-party API:
135+
```python
136+
def call_third_party_api(access_token):
137+
"""Generic function to call a third-party API with the federated access token."""
138+
# Set up headers with the access token
139+
headers = {
140+
"Authorization": f"Bearer {access_token}",
141+
"Content-Type": "application/json"
142+
}
143+
# Make the API request
144+
response = requests.get(
145+
"https://api.third-party-service.com/endpoint",
146+
headers=headers
147+
)
148+
# Check for successful response
149+
if response.status_code == 200:
150+
return response.json()
151+
else:
152+
print(f"API request failed with status code: {response.status_code}")
153+
return None
154+
```
155+
156+
## Step 9: Run the Application
157+
```bash
158+
python server.py
159+
```
160+
## Key Concepts
161+
1. **Federated Connection**: An Auth0 feature that allows your application to obtain access tokens for third-party services through Auth0.
162+
2. **Token Exchange**: The process of exchanging a refresh token for a service-specific access token.
163+
3. **Offline Access**: Requesting permission to refresh tokens even when the user is not present.
164+
4. **Connections**: Auth0's term for different identity providers or authentication methods (google-oauth2, github, etc.).
165+
## Security Considerations
166+
- Always store tokens securely
167+
- Use HTTPS for all communications
168+
- Validate state parameters to prevent CSRF attacks
169+
- Implement proper token refresh mechanisms
170+
- Don't expose sensitive credentials in client-side code
171+
## Troubleshooting
172+
- Check scopes if APIs return unauthorized errors
173+
- Ensure refresh tokens are being properly stored and used
174+
- Verify connection names match exactly with Auth0 configurations
175+
- Monitor token expiration and implement proper refresh logic
176+

0 commit comments

Comments
 (0)