mirror of
https://github.com/sstent/go-garth.git
synced 2026-01-25 16:42:28 +00:00
11 KiB
Executable File
11 KiB
Executable File
Garth - Garmin SSO Authentication Flows Documentation
Overview
Garth is a Python library that provides authenticated access to Garmin Connect APIs using the same authentication flow as the official Garmin Connect mobile application. It implements a sophisticated OAuth1/OAuth2 hybrid authentication system that maintains long-term session persistence.
Architecture Summary
- Primary Domain:
connect.garmin.com(orconnect.garmin.cnfor China) - Authentication Method: Hybrid OAuth1 + OAuth2 with SSO
- Session Persistence: OAuth1 tokens valid for ~1 year
- MFA Support: Built-in multi-factor authentication handling
- Storage: Local credential caching in
~/.garthby default
Authentication Flow Components
1. Initial Login Flow
1.1 Credential Validation
Endpoint: https://sso.garmin.com/sso/signin
Method: POST
Headers:
- Content-Type: application/x-www-form-urlencoded
- User-Agent: GCMv3 (Garmin Connect Mobile v3)
Parameters:
- username: <email_address>
- password: <password>
- embed: true
- lt: <login_ticket> (obtained from initial GET request)
- _eventId: submit
- displayNameRequired: false
1.2 Login Ticket Acquisition
Endpoint: https://sso.garmin.com/sso/signin
Method: GET
Headers:
- User-Agent: GCMv3
Purpose: Extract login ticket (lt) from hidden form field
Response: HTML form with embedded lt parameter
2. Multi-Factor Authentication (MFA)
2.1 MFA Detection
After initial credential validation, if MFA is required:
Response Pattern:
- HTTP 200 with MFA challenge form
- Contains: mfaCode input field
- Action endpoint: https://sso.garmin.com/sso/verifyMFA
2.2 MFA Code Submission
Endpoint: https://sso.garmin.com/sso/verifyMFA
Method: POST
Headers:
- Content-Type: application/x-www-form-urlencoded
Parameters:
- mfaCode: <6_digit_code>
- lt: <login_ticket>
- _eventId: submit
3. OAuth Token Exchange Flow
3.1 OAuth1 Consumer Credentials
OAUTH_CONSUMER = {
'key': 'fc020df2-e33d-4ec5-987a-7fb6de2e3850',
'secret': 'secret_key_from_mobile_app' # Embedded in mobile app
}
3.2 OAuth1 Request Token
Endpoint: https://connectapi.garmin.com/oauth-service/oauth/request_token
Method: GET
Headers:
- Authorization: OAuth oauth_consumer_key="...", oauth_nonce="...",
oauth_signature_method="HMAC-SHA1", oauth_timestamp="...",
oauth_version="1.0", oauth_signature="..."
Response:
oauth_token=<request_token>&oauth_token_secret=<request_secret>
3.3 OAuth1 Authorization
Endpoint: https://connect.garmin.com/oauthConfirm
Method: GET
Parameters:
- oauth_token: <request_token>
- oauth_callback: https://connect.garmin.com/modern/
Headers:
- Cookie: <session_cookies_from_login>
3.4 OAuth1 Access Token Exchange
Endpoint: https://connectapi.garmin.com/oauth-service/oauth/access_token
Method: POST
Headers:
- Authorization: OAuth oauth_consumer_key="...", oauth_nonce="...",
oauth_signature_method="HMAC-SHA1", oauth_timestamp="...",
oauth_token="<request_token>", oauth_verifier="<oauth_verifier>",
oauth_version="1.0", oauth_signature="..."
Response:
oauth_token=<access_token>&oauth_token_secret=<access_secret>
4. OAuth2 Token Exchange
4.1 OAuth2 Authorization Request
Endpoint: https://connectapi.garmin.com/oauth-service/oauth/exchange_token
Method: POST
Headers:
- Authorization: OAuth oauth_consumer_key="...", oauth_nonce="...",
oauth_signature_method="HMAC-SHA1", oauth_timestamp="...",
oauth_token="<oauth1_access_token>", oauth_version="1.0",
oauth_signature="..."
Response Format (JSON):
{
"access_token": "<oauth2_access_token>",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "<oauth2_refresh_token>",
"scope": "GHS_ADMIN_READ GHS_ADMIN_WRITE"
}
5. Token Refresh Flow
5.1 OAuth2 Token Refresh
Endpoint: https://connectapi.garmin.com/oauth-service/oauth/token
Method: POST
Headers:
- Content-Type: application/x-www-form-urlencoded
Parameters:
- grant_type: refresh_token
- refresh_token: <oauth2_refresh_token>
Response:
{
"access_token": "<new_oauth2_access_token>",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "<new_oauth2_refresh_token>",
"scope": "GHS_ADMIN_READ GHS_ADMIN_WRITE"
}
Session Management
6. Credential Storage Structure
6.1 Storage File Location
Default Path: ~/.garth
Format: JSON
Permissions: 600 (user read/write only)
6.2 Stored Credential Format
{
"domain": "garmin.com",
"oauth1_token": {
"oauth_token": "<oauth1_access_token>",
"oauth_token_secret": "<oauth1_access_secret>"
},
"oauth2_token": {
"access_token": "<oauth2_access_token>",
"token_type": "Bearer",
"expires_in": 3600,
"expires_at": 1698765432,
"refresh_token": "<oauth2_refresh_token>",
"scope": "GHS_ADMIN_READ GHS_ADMIN_WRITE"
},
"user_profile": {
"username": "<username>",
"profile_id": "<profile_id>",
"display_name": "<display_name>"
}
}
7. API Request Authentication
7.1 Connect API Requests
Base URL: https://connectapi.garmin.com
Headers:
- Authorization: Bearer <oauth2_access_token>
- NK: NT (Garmin-specific header)
- User-Agent: GCMv3
Auto-refresh: OAuth2 token refreshed automatically when expired
7.2 Upload API Requests
Endpoint: https://connectapi.garmin.com/upload-service/upload
Method: POST
Headers:
- Authorization: OAuth oauth_consumer_key="...", oauth_nonce="...",
oauth_signature_method="HMAC-SHA1", oauth_timestamp="...",
oauth_token="<oauth1_access_token>", oauth_version="1.0",
oauth_signature="..."
- Content-Type: multipart/form-data
Body: Multipart form with FIT file data
Key Endpoints Reference
8. Authentication Endpoints
| Purpose | Method | Endpoint |
|---|---|---|
| Get Login Form | GET | https://sso.garmin.com/sso/signin |
| Submit Credentials | POST | https://sso.garmin.com/sso/signin |
| Verify MFA | POST | https://sso.garmin.com/sso/verifyMFA |
| OAuth Request Token | GET | https://connectapi.garmin.com/oauth-service/oauth/request_token |
| OAuth Authorize | GET | https://connect.garmin.com/oauthConfirm |
| OAuth Access Token | POST | https://connectapi.garmin.com/oauth-service/oauth/access_token |
| OAuth2 Exchange | POST | https://connectapi.garmin.com/oauth-service/oauth/exchange_token |
| OAuth2 Refresh | POST | https://connectapi.garmin.com/oauth-service/oauth/token |
9. Data API Endpoints
| Data Type | Method | Endpoint Pattern |
|---|---|---|
| Sleep Data | GET | /wellness-service/wellness/dailySleepData/{username} |
| Stress Data | GET | /usersummary-service/stats/stress/weekly/{date}/{weeks} |
| User Profile | GET | /userprofile-service/userprofile |
| Activities | GET | /activitylist-service/activities/search/activities |
| Upload FIT | POST | /upload-service/upload |
| Weight Data | GET | /weight-service/weight/daterangesnapshot |
Configuration Options
10. Domain Configuration
10.1 Global Domains
- Standard:
garmin.com(default) - China:
garmin.cn(usegarth.configure(domain="garmin.cn"))
10.2 Proxy Configuration
garth.configure(
proxies={"https": "http://localhost:8888"},
ssl_verify=False
)
Error Handling
11. Common Error Scenarios
11.1 Session Expiration
from garth.exc import GarthException
try:
garth.client.username
except GarthException:
# Session expired - need to re-authenticate
garth.login(email, password)
11.2 MFA Required
# Synchronous MFA handling
result1, result2 = garth.login(email, password, return_on_mfa=True)
if result1 == "needs_mfa":
mfa_code = input("Enter MFA code: ")
oauth1, oauth2 = garth.resume_login(result2, mfa_code)
11.3 Token Refresh Failures
- Automatic retry mechanism built-in
- Falls back to OAuth1 if OAuth2 refresh fails
- Full re-authentication required if OAuth1 tokens expire
Security Considerations
12. Security Features
12.1 Token Security
- OAuth1 tokens have 1-year lifetime
- OAuth2 tokens expire every hour (auto-refreshed)
- Stored credentials encrypted at filesystem level
- No plaintext password storage
12.2 Session Security
- CSRF protection via login tickets
- MFA support for enhanced security
- Secure random nonce generation for OAuth signatures
- HMAC-SHA1 signature validation
12.3 Network Security
- All communications over HTTPS
- Certificate validation enabled by default
- User-Agent matching official mobile app
- Request rate limiting handled automatically
Flow Diagrams
13. End-to-End Authentication Flow
graph TB
A[Client Application] --> B[garth.login call]
B --> C[Get Login Ticket]
C --> D{Credentials Valid?}
D -->|No| E[Authentication Error]
D -->|Yes| F{MFA Required?}
F -->|Yes| G[Prompt for MFA Code]
G --> H[Submit MFA Code]
H --> I{MFA Valid?}
I -->|No| E
I -->|Yes| J[Get OAuth1 Request Token]
F -->|No| J
J --> K[Authorize OAuth1 Token]
K --> L[Exchange for OAuth1 Access Token]
L --> M[Exchange OAuth1 for OAuth2 Token]
M --> N[Store Credentials to ~/.garth]
N --> O[Authentication Complete]
O --> P[Make API Request]
P --> Q{OAuth2 Token Valid?}
Q -->|Yes| R[Execute API Request]
Q -->|No| S[Refresh OAuth2 Token]
S --> T{Refresh Successful?}
T -->|Yes| R
T -->|No| U{OAuth1 Token Valid?}
U -->|Yes| M
U -->|No| B
R --> V[Return API Response]
style E fill:#ffcccc
style O fill:#ccffcc
style V fill:#ccffcc
14. Token Lifecycle Management
graph LR
A[Fresh Login] --> B[OAuth1 Access Token<br/>~1 year lifetime]
B --> C[OAuth2 Access Token<br/>~1 hour lifetime]
C --> D{API Request}
D --> E{OAuth2 Expired?}
E -->|No| F[Use OAuth2 Token]
E -->|Yes| G[Refresh OAuth2 Token]
G --> H{Refresh Success?}
H -->|Yes| C
H -->|No| I{OAuth1 Expired?}
I -->|No| J[Re-exchange OAuth1 for OAuth2]
J --> C
I -->|Yes| K[Full Re-authentication Required]
K --> A
F --> L[API Response]
style K fill:#ffcccc
style L fill:#ccffcc
Implementation Notes
15. Key Implementation Details
15.1 User Agent String
- Uses
GCMv3to mimic Garmin Connect Mobile v3 - Critical for endpoint compatibility
- Some endpoints reject requests without proper User-Agent
15.2 OAuth Signature Generation
- HMAC-SHA1 signatures for OAuth1 requests
- Includes all OAuth parameters in signature base string
- Consumer secret and token secret used as signing key
15.3 Session Cookie Handling
- Automatic cookie jar management
- Session cookies preserved across authentication flow
- Required for OAuth authorization step
15.4 Rate Limiting
- Built-in request throttling
- Exponential backoff for failed requests
- Respects Garmin's API rate limits
This comprehensive documentation covers all aspects of the Garth authentication system, from initial login through ongoing API access, providing developers with the technical details needed to understand and work with the authentication flows.