Fix InsecureConnectionBuilder (Android) and add allowInsecureConnections support (iOS/macOS)#650
Conversation
…ecureConnections support for iOS/macOS Android: Replace no-op InsecureConnectionBuilder.openConnection() with real SSL bypass using TrustManager + HostnameVerifier when allowInsecureConnections=true. iOS/macOS: Add InsecureURLProtocol (NSURLProtocol subclass) that intercepts HTTPS connections and trusts all certificates. Register/unregister conditionally based on allowInsecureConnections flag. Previously, the flag was completely ignored on Apple platforms. Fixes MaikuB#386
|
Thanks for the PR. Before I go take a look into in more depth, do you have instructions I could follow to test this PR and ensure the functionality continues to work in the future? |
|
Hi @MaikuB, here's how to test this PR: PrerequisitesYou need an OIDC provider with a self-signed HTTPS certificate. The easiest way is a local Keycloak: # Generate a self-signed cert
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=localhost"
# Run Keycloak with the self-signed cert
docker run -d --name keycloak-test -p 8443:8443 \
-v $(pwd)/cert.pem:/etc/keycloak/cert.pem \
-v $(pwd)/key.pem:/etc/keycloak/key.pem \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:26.6 \
start \
--hostname=localhost \
--hostname-strict=false \
--https-certificate-file=/etc/keycloak/cert.pem \
--https-certificate-key-file=/etc/keycloak/key.pemWait for it to start (~15s), then create a client and a test user via the admin console at
Alternatively, via the API: # Get admin token
ADMIN_TOKEN=$(curl -sk -X POST "https://localhost:8443/realms/master/protocol/openid-connect/token" \
-d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
# Create client
curl -sk -X POST "https://localhost:8443/admin/realms/master/clients" \
-H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \
-d '{"clientId":"test-app","enabled":true,"publicClient":true,"redirectUris":["com.example.app://callback","com.example.app://logout"],"standardFlowEnabled":true,"directAccessGrantsEnabled":true}'
# Create user
curl -sk -X POST "https://localhost:8443/admin/realms/master/users" \
-H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \
-d '{"username":"testuser","email":"testuser@example.com","emailVerified":true,"firstName":"Test","lastName":"User","enabled":true,"credentials":[{"type":"password","value":"testpass123","temporary":false}]}'Test with the example app
What to verify
The key thing to confirm is that the flag is opt-in only: when I've tested this exact setup — Keycloak 26.6 starts correctly with the self-signed cert, the OIDC discovery endpoint responds, and token grants work against it. |
Summary
Fixes #386
The
allowInsecureConnectionsparameter does not work on any platform:InsecureConnectionBuilder.openConnection()is a no-op — it callsURL.openConnection()without any SSL/TLS configuration, so HTTPS connections still validate the certificate chain normally.allowInsecureConnectionsparameter is completely ignored. There is no equivalent ofInsecureConnectionBuilder, and no SSL bypass mechanism exists.This makes it impossible to use the plugin against OIDC providers with self-signed certificates during development (e.g., local Keycloak instances).
Changes
Android
Replaced the no-op
InsecureConnectionBuilder.openConnection()with a real implementation that:SSLContextwith a trust-allX509TrustManagerHostnameVerifieronHttpsURLConnectionallowInsecureConnections=true(the existing routing inFlutterAppauthPluginviagetConnectionBuilder()is unchanged)iOS & macOS
Added
InsecureURLProtocol(anNSURLProtocolsubclass) that:NSURLSessionwith emptyprotocolClassesto avoid recursionNSURLSessionAuthChallengeUseCredentialallowInsecureConnections=trueAlso added
allowInsecureConnectionsproperty toTokenRequestParametersandEndSessionRequestParameterson iOS/macOS (was previously only defined on Android).Testing
Verified on Android emulator against a local Keycloak instance with a self-signed certificate:
All operations succeed without "Network error" when
allowInsecureConnections=true.Security Note
The SSL bypass is only active when
allowInsecureConnections=trueis explicitly passed by the caller. Production configurations use CA-signed certificates andallowInsecureConnections=false(the default), so this change has no production impact.