|
| 1 | +# OAuth Authentication Limitations |
| 2 | + |
| 3 | +This document outlines the current limitations and implementation details of OAuth authentication in API Dash. |
| 4 | + |
| 5 | +## Table of Contents |
| 6 | + |
| 7 | +1. [OAuth2 Limitations](#oauth2-limitations) |
| 8 | +2. [OAuth1 Limitations](#oauth1-limitations) |
| 9 | +3. [Platform-Specific Behavior](#platform-specific-behavior) |
| 10 | +4. [Technical Implementation Details](#technical-implementation-details) |
| 11 | +5. [Workarounds](#workarounds) |
| 12 | +6. [Future Improvements](#future-improvements) |
| 13 | + |
| 14 | +## OAuth2 Limitations |
| 15 | + |
| 16 | +### Response Format Restriction |
| 17 | + |
| 18 | +**Limitation**: OAuth2 implementation only supports `application/json` response format as specified in [RFC 6749, Section 5.1](https://tools.ietf.org/html/rfc6749#section-5.1). |
| 19 | + |
| 20 | +**Details**: |
| 21 | +- The OAuth2 client automatically sets the `Accept: application/json` header for token requests |
| 22 | +- Servers that return token responses in other formats (e.g., `application/x-www-form-urlencoded`, `text/plain`) are not supported |
| 23 | +- This is enforced by the `_JsonAcceptClient` wrapper in the HTTP client manager |
| 24 | + |
| 25 | +**Impact**: |
| 26 | +- Some legacy OAuth2 providers that don't return JSON responses will fail |
| 27 | +- Non-standard OAuth2 implementations may not work correctly |
| 28 | + |
| 29 | +**Code Reference**: |
| 30 | +```dart |
| 31 | +// In HttpClientManager.createClientWithJsonAccept() |
| 32 | +class _JsonAcceptClient extends http.BaseClient { |
| 33 | + @override |
| 34 | + Future<http.StreamedResponse> send(http.BaseRequest request) { |
| 35 | + request.headers['Accept'] = 'application/json'; |
| 36 | + return _inner.send(request); |
| 37 | + } |
| 38 | +} |
| 39 | +``` |
| 40 | + |
| 41 | +### Port Range Limitation (Desktop Only) |
| 42 | + |
| 43 | +**Limitation**: For desktop platforms, the OAuth2 callback server requires at least one free port in the range 8080-8090. |
| 44 | + |
| 45 | +**Details**: |
| 46 | +- The callback server attempts to bind to ports starting from 8080 |
| 47 | +- If all ports in the range (8080-8090) are occupied, the OAuth flow will fail |
| 48 | +- This only affects desktop platforms (macOS, Windows, Linux) |
| 49 | + |
| 50 | +**Impact**: |
| 51 | +- Users running other services on these ports may experience OAuth failures |
| 52 | +- Development environments with multiple applications may conflict |
| 53 | + |
| 54 | +**Code Reference**: |
| 55 | +```dart |
| 56 | +// In OAuthCallbackServer.start() |
| 57 | +for (int port = 8080; port <= 8090; port++) { |
| 58 | + try { |
| 59 | + _server = await HttpServer.bind(InternetAddress.loopbackIPv4, port); |
| 60 | + _port = port; |
| 61 | + break; |
| 62 | + } catch (e) { |
| 63 | + if (port == 8090) { |
| 64 | + throw Exception('Unable to find available port for OAuth callback server'); |
| 65 | + } |
| 66 | + } |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +## OAuth1 Limitations |
| 71 | + |
| 72 | +### Incomplete Flow Implementation |
| 73 | + |
| 74 | +**Limitation**: OAuth1 implementation does not handle the complete OAuth1 authorization flow. |
| 75 | + |
| 76 | +**Details**: |
| 77 | +- The implementation assumes that the necessary steps to obtain the access token have already been performed manually or through a backend service |
| 78 | +- Users must provide pre-obtained access tokens and token secrets |
| 79 | +- The three-legged OAuth1 flow (request token → user authorization → access token) is not implemented |
| 80 | +- This aligns with the behavior in other API clients such as Postman and Insomnia |
| 81 | + |
| 82 | +**Impact**: |
| 83 | +- Users cannot complete OAuth1 authentication entirely within API Dash |
| 84 | +- External tools or manual processes are required to obtain tokens |
| 85 | +- Limited to scenarios where tokens are already available |
| 86 | + |
| 87 | +**Workaround**: |
| 88 | +Users need to: |
| 89 | +1. Obtain request tokens from the OAuth1 provider |
| 90 | +2. Complete user authorization outside of API Dash |
| 91 | +3. Exchange the authorized request token for an access token |
| 92 | +4. Manually enter the access token and token secret in API Dash |
| 93 | + |
| 94 | +## Platform-Specific Behavior |
| 95 | + |
| 96 | +### Redirect URI Handling |
| 97 | + |
| 98 | +**Mobile Platforms (iOS, Android)**: |
| 99 | +- **Default Redirect URI**: `apidash://oauth2` |
| 100 | +- **Mechanism**: Uses `flutter_web_auth_2` with custom URL scheme |
| 101 | +- **User Experience**: Opens authorization in a WebView within the app |
| 102 | + |
| 103 | +**Desktop Platforms (macOS, Windows, Linux)**: |
| 104 | +- **Default Redirect URI**: `http://localhost:{port}/callback` |
| 105 | +- **Port Range**: 8080-8090 (automatically selects first available port) |
| 106 | +- **Mechanism**: Opens authorization in the system's default browser |
| 107 | +- **User Experience**: External browser window with automatic callback handling |
| 108 | + |
| 109 | +**Code Reference**: |
| 110 | +```dart |
| 111 | +// Platform detection logic |
| 112 | +static bool get shouldUseLocalhostCallback => isDesktop; |
| 113 | +
|
| 114 | +// Redirect URL determination |
| 115 | +if (PlatformUtils.shouldUseLocalhostCallback) { |
| 116 | + callbackServer = OAuthCallbackServer(); |
| 117 | + final localhostUrl = await callbackServer.start(); |
| 118 | + actualRedirectUrl = Uri.parse(localhostUrl); |
| 119 | +} else { |
| 120 | + // Use custom scheme for mobile |
| 121 | + actualRedirectUrl = redirectUrl; // apidash://oauth2 |
| 122 | +} |
| 123 | +``` |
| 124 | + |
| 125 | +## Technical Implementation Details |
| 126 | + |
| 127 | +### Grant Types Supported |
| 128 | + |
| 129 | +**OAuth2**: |
| 130 | +- ✅ Authorization Code Grant |
| 131 | +- ✅ Client Credentials Grant |
| 132 | +- ✅ Resource Owner Password Grant |
| 133 | +- ❌ Implicit Grant (deprecated by OAuth2.1) |
| 134 | +- ❌ Device Authorization Grant |
| 135 | + |
| 136 | +**OAuth1**: |
| 137 | +- ✅ Manual token entry (post-authorization) |
| 138 | +- ❌ Automated three-legged flow |
| 139 | + |
| 140 | +### PKCE Support |
| 141 | + |
| 142 | +**Status**: ✅ Supported for Authorization Code Grant |
| 143 | +- Code Challenge Method: SHA-256 or Plaintext |
| 144 | +- Automatically generates code verifier and challenge |
| 145 | +- Configurable through the UI |
| 146 | + |
| 147 | +### Token Storage |
| 148 | + |
| 149 | +**Mechanism**: File-based credential storage |
| 150 | +- **Location**: `{workspaceFolderPath}/oauth2_credentials.json` |
| 151 | +- **Format**: JSON with access token, refresh token, expiration time |
| 152 | +- **Security**: Stored as plain text (limitation for local development tool) |
| 153 | + |
| 154 | +**Auto-refresh**: ✅ Supported |
| 155 | +- Automatically refreshes expired tokens using refresh tokens |
| 156 | +- Updates stored credentials file |
| 157 | + |
| 158 | +## Workarounds |
| 159 | + |
| 160 | +### For Non-JSON OAuth2 Responses |
| 161 | + |
| 162 | +If you encounter an OAuth2 provider that doesn't return JSON responses: |
| 163 | + |
| 164 | +1. **Contact the provider** to request JSON support (recommended) |
| 165 | +2. **Use a proxy server** to convert the response format |
| 166 | +3. **Consider alternative authentication methods** if available |
| 167 | + |
| 168 | +### For Port Conflicts on Desktop |
| 169 | + |
| 170 | +If ports 8080-8090 are occupied: |
| 171 | + |
| 172 | +1. **Stop conflicting services** temporarily during OAuth flow |
| 173 | +2. **Use mobile platform** for OAuth authentication if possible |
| 174 | +3. **Configure OAuth provider** to use a different callback URL (if supported) |
| 175 | + |
| 176 | +## Related Documentation |
| 177 | + |
| 178 | +- [Setup and Run Guide](setup_run.md) |
| 179 | +- [Platform-Specific Instructions](platform_specific_instructions.md) |
| 180 | +- [Testing Guide](testing.md) |
| 181 | +- [OAuth2 RFC 6749](https://tools.ietf.org/html/rfc6749) |
| 182 | +- [OAuth1 RFC 5849](https://tools.ietf.org/html/rfc5849) |
0 commit comments