Conversation
95ea224 to
a627e09
Compare
| // - appCallbackUrl: Change if using custom scheme or intermediary server | ||
| // - authTimeoutSeconds: Change if users need more/less time to authenticate | ||
| final Map<String, String> parameters = const { | ||
| 'appCallbackUrl': 'auth0flutter://callback', |
There was a problem hiding this comment.
Do we need the appCallbackUrl parameter at all. User can pass their intermediary url as part of the redirect_uri if required
There was a problem hiding this comment.
I have a strong opinion about adding too many options to a public SDK. Once we add something like appCallbackUrl, customers will start using it. After that, we can’t remove it without a breaking change. And that also means we’re committing to maintaining it long-term.
I’m more aligned with what @pmathew92 suggested (using only redirect_uri). From my understanding, the developer can configure it like this:
redirect_uri: 'https://customers-domain.com/handle-redirect?target=flutterapp://callback'Auth0 will then append ?code=34r43r.... and redirect the user to:
https://customers-domain.com/handle-redirect?target=flutterapp://callback?code=34r43r....
The intermediate page can extract both target and code, show a meaningful message to the user, and then redirect to:
flutterapp://callback?code=34r43r....
We can document a simple reference implementation of this intermediate page so it’s easy for customers to set up.
In this example we use target as the parameter name, but customers can choose any name they prefer. Because of this, I don’t see a strong need to introduce another public option like appCallbackUrl.
@frederikprijck, do you have any strong thoughts on this ?
There was a problem hiding this comment.
removed appCallbackUrl altogether. redirect url will solve the purpose we need for waking up the app on redirection from browser
| 'email', | ||
| 'offline_access', | ||
| }, | ||
| required final String redirectUrl, |
There was a problem hiding this comment.
redirectUrl can have the default value auth0flutter://callback
There was a problem hiding this comment.
done. added auth0flutter://callback as default redirectUrl
| return {parts[0], parts[1], parts[2]}; | ||
| } | ||
|
|
||
| web::json::value DecodeJwtPayload(const std::string &token) |
There was a problem hiding this comment.
This is just decoding the payload. It's still not verifying the JWS signature.
There was a problem hiding this comment.
added both claim and signature validation as well
| * @brief Implementation of ID Token validation | ||
| */ | ||
|
|
||
| #include "id_token_validator.h" |
There was a problem hiding this comment.
This class is only validating the claims . We are not validating signature which could also be tempered. Please check with security guidelines or else we should get the public key from JWKS and validate the signature too
There was a problem hiding this comment.
done added validation of signature as well id_token_signature_validator.cpp file
| } | ||
|
|
||
| // Run authentication flow in background thread to avoid blocking UI | ||
| std::thread([ |
There was a problem hiding this comment.
The entire login flow runs on a std::thread that is immediately .detach()ed. If the Flutter engine shuts down while the thread is running (e.g., app closes during authentication), accessing result is undefined behavior and will crash. There is also no way to cancel the authentication from the Dart side.
Current Code:
std::thread(result = std::move(result), ... mutable {
// ...
}).detach();
I would recommend to design a safe, non fire and forget solution using cpprestsdk’s pplx::task instead of detaching a thread. Check this : https://microsoft.github.io/cpprestsdk/classpplx_1_1cancellation__token__registration.html
This will:
- Avoid undefined behavior if the Flutter engine shuts down. (no crashes)
- Give structured async task management (no fire-and-forget)
|
|
||
| late Auth0 auth0; | ||
| late WebAuthentication webAuth; | ||
| late WindowsWebAuthentication windowsWebAuth; |
There was a problem hiding this comment.
WindowsWebAuthentication is a parallel class rather than a platform extension. WindowsWebAuthentication class exposed via auth0.windowsWebAuthentication(). This is existing platofrm where auth0.webAuthentication() works cross-platform.
from dx point of view custoemrs will now need platform conditional code like below from now on
if (Platform.isWindows) {
await auth0.windowsWebAuthentication().login(redirectUrl: '...');
} else {
await auth0.webAuthentication().login();
}
The separate class is fine as an internal implementation detail, but it should not be the public API That must be consistent
| { | ||
|
|
||
| // Local URL encoding helper (kept here per design requirement) | ||
| static std::string UrlEncode(const std::string &str) |
There was a problem hiding this comment.
This code is duplicate at two places . would recommend to unify it. check here : https://github.com/auth0/auth0-flutter/pull/656/changes#diff-361778dbfaf243c1651b49403a356c63e7c2f41c62770b44b7a93511db1124ecR15
There was a problem hiding this comment.
logout has same code
| */ | ||
| bool IsNetworkError() const | ||
| { | ||
| return statusCode_ == 0 || statusCode_ >= 500; |
There was a problem hiding this comment.
5xx eg 503 these are server errors canot be treated as network error. we can refer android / ios SDK for this
| std::string state = generateCodeVerifier(); // Reuse code verifier generation for random state | ||
|
|
||
| DebugPrint("codeVerifier = " + codeVerifier); | ||
| DebugPrint("codeChallenge = " + codeChallenge); |
There was a problem hiding this comment.
we should remove it before check in
| { | ||
| authUrl << "&audience=" << UrlEncode(audience); | ||
| } | ||
|
|
There was a problem hiding this comment.
IdTokenValidationConfig has a nonce but we are not adding capability to add nonce here to authUrl. it is important to mitigate replay attacks . please add taht along witjh organisationid and other params
| /// this class uses the Windows native implementation to perform interactions | ||
| /// with Universal Login. | ||
| /// | ||
| /// It is not intended for you to instantiate this class yourself, as an |
There was a problem hiding this comment.
We are saying here it is not intended for you to instantiate this class yourself. but this is not enforce we still have a public constructor
(cherry picked from commit 6ad8d90)
…entage url encoding to login and logout urls - id token validation - presence of openid scope - code refactoring (cherry picked from commit 5f1b308)
…e as app callback_url - params optional handling (cherry picked from commit fd4b341ba06017c2c6a1ae1d1da36cf3bc20cc49)
a627e09 to
408b69a
Compare
* main: (79 commits) build(deps): bump aws-actions/configure-aws-credentials from 5.1.1 to 6.0.0 in /.github/actions/rl-scanner (#744) chore: updated the RL wrapper installation path (#746) Release af-v2.0.0-beta.3 (#743) Release afpi-v2.0.0-beta.3 (#742) Release afpi-v2.0.0-beta.3 (#741) build(deps): bump ruby/setup-ruby from 1.286.0 to 1.288.0 in /.github/actions/setup-darwin (#740) CredentialsManager user info/ID token contents accessible via flutter SDK (#607) CI cleanup Avoid running always failing smoke tests for iOS make PR runs with release workflow that triggers flutter analyze udpate pubspec udpate podspecs Release af-v2.0.0-beta.2 pubspec update for beta release Release afpi-v2.0.0-beta.2 fix flutter analyse errors build(deps): bump ruby/setup-ruby from 1.285.0 to 1.286.0 in /.github/actions/setup-darwin (#728) build(deps-dev): bump lodash from 4.17.21 to 4.17.23 in /appium-test (#729) chore:Fixed errors from flutter analyze (#727) feat: Add allowedBrowsers parameter to logout API [SDK-724] (#726) ...
📋 Changes
This PR adds native Windows desktop support to the
auth0_flutterSDK, enabling Auth0 Universal Login on Flutter Windows apps using the OAuth 2.0 Authorization Code Flow with PKCE. The implementation is a C++ Flutter plugin that integrates with the existing platform-interface layer without modifying the mobile (iOS/Android) code paths.New:
WindowsWebAuthenticationclassA dedicated Windows authentication class exposed via
Auth0.windowsWebAuthentication(). Unlike the mobileWebAuthenticationclass, this:redirectUrlexplicitly (no platform default exists on Windows)CredentialsManager(no Keychain/Keystore on Windows)parametersmap for Windows-specific configurationauthTimeoutSeconds(default'180'): How long the plugin polls for the OAuth callback before returningUSER_CANCELLED. Increase for slow MFA flows; decrease for fast failure in tests.New: Windows C++ plugin (
auth0_flutter/windows/)login_web_auth_request_handler.cpplogout_web_auth_request_handler.cppoauth_helpers.cppauth0flutter://callback pollingauth0_client.cppid_token_validator.cppid_token_signature_validator.cppjwt_util.cpptoken_decoder.cppCredentialsstructuser_profile.cpp/user_identity.cppUserProfilestructtime_util.cppurl_utils.cppwindows_utils.cppWideToUtf8,BringFlutterWindowToFrontAuthentication flow:
code_verifier(32 cryptographically random bytes viaRAND_bytes) andcode_challenge(SHA-256 via OpenSSL, base64-URL encoded)statevalue for CSRF protection/authorizeURL with all parameters RFC 3986-encodedShellExecuteAPLUGIN_STARTUP_URLenvironment variable (set by Windows when the app is launched via theauth0flutter://custom scheme) every 200 ms until the callback arrives or the timeout expiresstateto prevent CSRF; extractcodecode+code_verifierfor tokens via POST to/oauth/tokenauth_time, nonce, RS256 signature)Key design decisions:
auth0flutter://callback(kDefaultRedirectUri). TheredirectUrlsent to Auth0 may differ (e.g. an HTTPS intermediary server URL); that server is responsible for forwarding toauth0flutter://callback?code=…&state=….authTimeoutSeconds) are consumed before building the authorize URL and are not appended to it.std::threadto avoid blocking the Flutter UI thread.openidscope is always enforced even when not explicitly passed, as required by OpenID Connect.New:
vcpkg.jsondependency manifestManages C++ dependencies via vcpkg, integrating automatically with CMake through the vcpkg toolchain file set by Flutter during
flutter build windows:cpprestsdkopensslRAND_bytes(PKCE entropy), SHA-256 (code challenge), RS256 signature verification, TLSboost-system/boost-date-time/boost-regexNew: Unit tests (Google Test,
auth0_flutter/windows/test/)oauth_helpers_test.cppid_token_validator_test.cppauth_time, nonce, leeway validationjwt_util_test.cpptime_util_test.cpptoken_decoder_test.cppurl_utils_test.cppuser_identity_test.cppuser_profile_test.cppwindows_utils_test.cppWideToUtf8wide-to-UTF-8 conversionTests are compiled as a separate
auth0_flutter_testsexecutable and registered with CTest, enabled via-DAUTH0_FLUTTER_ENABLE_TESTS=ON.New: CI pipeline (
.github/workflows/main.yml)Added a
windows-testsjob that installs vcpkg dependencies, builds the test executable with CMake, and runs all C++ unit tests via CTest onwindows-latest.Changed:
Auth0class (lib/auth0_flutter.dart)windowsWebAuthentication({String? scheme})factory methodWindowsWebAuthenticationfrom the libraryChanged:
web_authentication_test.dartappCallbackUrl,authTimeoutSeconds) to appear in mobileWebAuthenticationcalls — the mobile class passesparametersthrough unchanged'passes custom authTimeoutSeconds to parameters'→'passes custom parameters to platform': the original test called.login()with no parameters but asserted a'300'timeout value; the body now actually passes and verifies explicit custom parametersChanged: README
auth0flutter://custom URL scheme registration, Allowed Callback URL configuration, and both redirect patterns (direct vs. intermediary server)📎 References
🎯 Testing
Automated — C++ unit tests (Windows)
All 9 test suites pass.
Automated — Flutter unit tests (any platform)
Manual — end-to-end on Windows
Prerequisites:
auth0flutteras a custom URL scheme pointing to your app executable (via installer or registry)auth0flutter://callbackto Allowed Callback URLs in the Auth0 dashboardcd auth0_flutter/example flutter run -d windowsauth0flutter://callback?code=…&state=…To test the intermediary server pattern, point
redirectUrlat an HTTPS endpoint that reads thecodeandstatequery parameters and responds with a redirect toauth0flutter://callback?code=…&state=….