{"id":37229212,"url":"https://github.com/dye-tech/gatekey-android-client","last_synced_at":"2026-01-15T03:31:41.110Z","repository":{"id":331542967,"uuid":"1126968182","full_name":"dye-tech/gatekey-android-client","owner":"dye-tech","description":null,"archived":false,"fork":false,"pushed_at":"2026-01-10T02:40:30.000Z","size":1234,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-10T23:37:20.027Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dye-tech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-02T22:57:42.000Z","updated_at":"2026-01-10T02:40:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dye-tech/gatekey-android-client","commit_stats":null,"previous_names":["dye-tech/gatekey-android-client"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/dye-tech/gatekey-android-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dye-tech%2Fgatekey-android-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dye-tech%2Fgatekey-android-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dye-tech%2Fgatekey-android-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dye-tech%2Fgatekey-android-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dye-tech","download_url":"https://codeload.github.com/dye-tech/gatekey-android-client/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dye-tech%2Fgatekey-android-client/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28442285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-15T00:55:22.719Z","status":"online","status_checked_at":"2026-01-15T02:00:08.019Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-15T03:31:40.487Z","updated_at":"2026-01-15T03:31:41.104Z","avatar_url":"https://github.com/dye-tech.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gatekey Android Client\n\nAndroid client for connecting to Gatekey VPN gateways and mesh networks.\n\n## Features\n\n- **Web-based SSO Login**: Authenticate using your organization's identity provider (OIDC)\n- **API Key Authentication**: Alternative authentication using API keys\n- **Gateway Connections**: Connect to VPN gateways for secure network access\n- **Mesh Network Support**: Connect to mesh hubs for multi-site networking\n- **Multi-connection Management**: View and manage active VPN connections\n- **Material Design 3**: Modern UI built with Jetpack Compose\n- **Embedded OpenVPN3**: Built-in VPN support without requiring external apps\n\n## Requirements\n\n- Android 8.0 (API 26) or higher\n- Network connectivity to your Gatekey server\n\n## Building\n\n### Prerequisites\n\n- JDK 17 (required, JDK 25+ not supported by current Android Gradle Plugin)\n- Android SDK with API 35\n- Android NDK 29.0.14206865 (for native OpenVPN3 builds)\n- CMake (installed via Android SDK Manager)\n- SWIG 4.0+ (for OpenVPN3 Java bindings generation)\n\n### Install Build Dependencies\n\n#### On Fedora/RHEL:\n```bash\nsudo dnf install swig\n```\n\n#### On Ubuntu/Debian:\n```bash\nsudo apt install swig\n```\n\n#### On macOS:\n```bash\nbrew install swig\n```\n\n### Set up JDK 17\n\nThe build requires JDK 17. Set the JAVA_HOME environment variable:\n\n```bash\n# On Linux (Homebrew)\nexport JAVA_HOME=/home/linuxbrew/.linuxbrew/opt/openjdk@17\n\n# On macOS (Homebrew)\nexport JAVA_HOME=/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home\n\n# On Ubuntu/Debian\nexport JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64\n```\n\n### Build Steps\n\n1. Clone the repository with submodules:\n   ```bash\n   git clone --recursive https://github.com/gatekey/gatekey-android-client.git\n   cd gatekey-android-client\n   ```\n\n2. If you already cloned without submodules, initialize them:\n   ```bash\n   git submodule update --init --recursive\n   ```\n\n3. Build the debug APK:\n   ```bash\n   ./gradlew assembleDebug\n   ```\n\n4. The APK will be generated at:\n   ```\n   app/build/outputs/apk/debug/app-debug.apk\n   ```\n\n### Install on Device\n\n#### Via ADB:\n```bash\nadb install app/build/outputs/apk/debug/app-debug.apk\n```\n\n#### Via Gradle:\n```bash\n./gradlew installDebug\n```\n\n### Local Development Deployment\n\nFor rapid development and testing on a physical device:\n\n#### One-Command Build and Deploy\n```bash\n# Set JDK 17 and build+install in one step\nJAVA_HOME=/path/to/jdk17 ./gradlew installDebug\n```\n\n#### Common JDK 17 Paths\n```bash\n# Linux (Homebrew)\nexport JAVA_HOME=/home/linuxbrew/.linuxbrew/Cellar/openjdk@17/17.0.17/libexec\n\n# macOS (Homebrew)\nexport JAVA_HOME=/opt/homebrew/opt/openjdk@17/libexec\n\n# Ubuntu/Debian\nexport JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64\n\n# Fedora/RHEL\nexport JAVA_HOME=/usr/lib/jvm/java-17-openjdk\n```\n\n#### Reinstalling After Signature Change\nIf you switch between debug and release builds, or rebuild with different signing keys:\n```bash\n# Uninstall existing app first\nadb uninstall com.gatekey.client\n\n# Then install new build\nadb install app/build/outputs/apk/debug/app-debug.apk\n```\n\n#### Viewing Logs\n```bash\n# View app logs in real-time\nadb logcat --pid=$(adb shell pidof -s com.gatekey.client)\n\n# Filter for GateKey-specific logs\nadb logcat | grep -i gatekey\n```\n\n#### Wireless ADB (optional)\n```bash\n# Connect device via USB first, then enable wireless\nadb tcpip 5555\nadb connect \u003cdevice-ip\u003e:5555\n# Now you can disconnect USB\n```\n\n### Release Build\n\n1. Create a signing key (one-time):\n   ```bash\n   keytool -genkey -v -keystore release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias gatekey\n   ```\n\n2. Configure signing in `app/build.gradle.kts` or via environment variables\n\n3. Build release:\n   ```bash\n   ./gradlew assembleRelease\n   ```\n\n4. The signed APK will be at:\n   ```\n   app/build/outputs/apk/release/app-release.apk\n   ```\n\n### Creating APKs for Distribution\n\n#### Debug APK (for testing)\n```bash\nJAVA_HOME=/path/to/jdk17 ./gradlew assembleDebug\n# Output: app/build/outputs/apk/debug/app-debug.apk\n```\n\n#### Release APK (for distribution)\n```bash\nJAVA_HOME=/path/to/jdk17 ./gradlew assembleRelease\n# Output: app/build/outputs/apk/release/app-release.apk\n```\n\n#### Build Both Variants\n```bash\nJAVA_HOME=/path/to/jdk17 ./gradlew assemble\n```\n\n#### Clean Build (if encountering issues)\n```bash\nJAVA_HOME=/path/to/jdk17 ./gradlew clean assembleDebug\n```\n\n#### APK Size Optimization\nThe release APK includes native libraries for all architectures. To create smaller APKs per architecture:\n```bash\n# Build separate APKs per ABI (add to app/build.gradle.kts)\n# splits { abi { isEnable = true } }\n./gradlew assembleRelease\n# Creates: app-arm64-v8a-release.apk, app-armeabi-v7a-release.apk, etc.\n```\n\n## GitHub Actions\n\nThe project includes CI/CD workflows for automated builds and releases.\n\n### Workflows\n\n| Workflow | Trigger | Description |\n|----------|---------|-------------|\n| `ci.yml` | Push to main/develop, PRs | Build, test, and lint |\n| `release.yml` | Tag push (v*) | Build signed APKs and create GitHub Release |\n\n### Creating a Release\n\n1. Update `versionCode` and `versionName` in `app/build.gradle.kts`\n2. Commit and push changes\n3. Create and push a tag:\n   ```bash\n   git tag v1.0.4\n   git push origin v1.0.4\n   ```\n4. GitHub Actions will build and create a release with:\n   - `gatekey-android-\u003cversion\u003e-release.apk` (signed)\n   - `gatekey-android-\u003cversion\u003e-debug.apk`\n   - `checksums.txt`\n\n### Required Secrets\n\nFor signed release builds, configure these repository secrets:\n\n| Secret | Description |\n|--------|-------------|\n| `KEYSTORE_BASE64` | Base64-encoded release keystore file |\n| `KEYSTORE_PASSWORD` | Keystore password |\n| `KEY_ALIAS` | Key alias in keystore (default: `gatekey`) |\n\nTo encode your keystore:\n```bash\nbase64 -w 0 gatekey-release.keystore\n# Copy output to KEYSTORE_BASE64 secret\n```\n\n### Local Release Build\n\nTo build a signed release locally:\n```bash\nKEYSTORE_PASSWORD=\"your-password\" ./gradlew assembleRelease\n```\n\n## Testing\n\n### Run Unit Tests\n```bash\n./gradlew test\n```\n\n### Run Instrumented Tests\n```bash\n./gradlew connectedAndroidTest\n```\n\n### Manual Testing Checklist\n\n1. **Login Flow**:\n   - [ ] SSO login redirects to browser and returns with token\n   - [ ] API key authentication works\n   - [ ] Invalid credentials show error message\n\n2. **Gateway Connection**:\n   - [ ] Gateway list loads from server\n   - [ ] VPN permission prompt appears on first connect\n   - [ ] Connection establishes successfully\n   - [ ] Connection status updates in UI\n   - [ ] Disconnect works properly\n\n3. **Mesh Hub Connection**:\n   - [ ] Mesh hub list loads from server\n   - [ ] Mesh connection generates correct config\n   - [ ] Connection establishes successfully\n\n4. **Settings**:\n   - [ ] Server URL can be changed\n   - [ ] Logout clears credentials\n   - [ ] Dark/light theme works\n\n## Project Structure\n\n```\ngatekey-android-client/\n├── app/                              # Main application module\n│   └── src/main/java/com/gatekey/client/\n│       ├── GatekeyApplication.kt     # Application class\n│       ├── MainActivity.kt           # Main activity with OAuth callback\n│       ├── data/\n│       │   ├── api/\n│       │   │   ├── GatekeyApi.kt     # Retrofit API interface\n│       │   │   └── AuthInterceptor.kt # Auth header interceptor\n│       │   ├── model/\n│       │   │   ├── AuthModels.kt     # Authentication models\n│       │   │   ├── GatewayModels.kt  # Gateway/mesh models\n│       │   │   └── SettingsModels.kt # Settings models\n│       │   └── repository/\n│       │       ├── AuthRepository.kt  # Authentication logic\n│       │       ├── GatewayRepository.kt # Gateway management\n│       │       ├── SettingsRepository.kt # Settings persistence\n│       │       └── TokenRepository.kt # Token storage\n│       ├── di/\n│       │   └── NetworkModule.kt      # Hilt DI module\n│       ├── vpn/\n│       │   ├── VpnManager.kt         # VPN connection orchestration\n│       │   └── OpenVpnServiceManager.kt # OpenVPN library interface\n│       └── ui/\n│           ├── GatekeyApp.kt         # Navigation host\n│           ├── theme/\n│           │   └── Theme.kt          # Material 3 theme\n│           ├── screens/\n│           │   ├── login/LoginScreen.kt\n│           │   ├── home/HomeScreen.kt\n│           │   ├── connections/ConnectionsScreen.kt\n│           │   └── settings/SettingsScreen.kt\n│           └── viewmodel/\n│               ├── AuthViewModel.kt\n│               ├── ConnectionViewModel.kt\n│               └── SettingsViewModel.kt\n└── openvpn/                          # OpenVPN library module (ics-openvpn)\n    └── main/\n        └── src/main/\n            ├── java/de/blinkt/openvpn/  # OpenVPN Java/Kotlin code\n            └── cpp/                      # Native libraries\n                ├── openvpn3/             # OpenVPN3 core\n                ├── openssl/              # OpenSSL cryptography\n                ├── mbedtls/              # mbedTLS cryptography\n                ├── lz4/                  # LZ4 compression\n                ├── asio/                 # Asio networking\n                └── fmt/                  # fmt formatting library\n```\n\n## Configuration\n\n### Server Setup\n\n1. Launch the app\n2. Enter your Gatekey server URL (e.g., `vpn.example.com`)\n3. Tap \"Login with SSO\" to authenticate via your identity provider\n\n### API Key Authentication\n\n1. Enter your server URL\n2. Tap \"Use API Key\"\n3. Enter your API key (format: `gk_...`)\n4. Tap \"Login with API Key\"\n\n## API Endpoints Used\n\n| Endpoint | Description |\n|----------|-------------|\n| `GET /api/v1/auth/providers` | List available auth providers |\n| `GET /api/v1/auth/cli/login` | Initiate CLI/mobile login flow |\n| `GET /api/v1/auth/cli/complete` | Complete login and get token |\n| `GET /api/v1/auth/api-key/validate` | Validate API key |\n| `GET /api/v1/auth/session` | Get current session info |\n| `GET /api/v1/gateways` | List available gateways |\n| `GET /api/v1/mesh/hubs` | List available mesh hubs |\n| `POST /api/v1/configs/generate` | Generate VPN config |\n| `POST /api/v1/mesh/generate-config` | Generate mesh config |\n\n## VPN Integration\n\nThe app uses the embedded OpenVPN3 library (from ics-openvpn) for VPN connections:\n\n1. User initiates connection to a gateway or mesh hub\n2. App requests VPN permission (Android system dialog)\n3. VPN config is fetched from Gatekey server API\n4. OpenVPN3 parses config and establishes tunnel\n5. Status updates shown via VpnStatus callbacks\n\n### Architecture\n\n```\n┌────────────────────┐     ┌────────────────────┐\n│   ConnectionVM     │────▶│     VpnManager     │\n└────────────────────┘     └────────────────────┘\n                                    │\n                                    ▼\n                           ┌────────────────────┐\n                           │ OpenVpnServiceMgr  │\n                           └────────────────────┘\n                                    │\n                                    ▼\n                           ┌────────────────────┐\n                           │  OpenVPNService    │\n                           │   (VpnService)     │\n                           └────────────────────┘\n                                    │\n                                    ▼\n                           ┌────────────────────┐\n                           │ OpenVPN3 Native    │\n                           │ (C++ via JNI)      │\n                           └────────────────────┘\n```\n\n## Security\n\n- Tokens stored using Android DataStore with encryption\n- HTTPS required for all server communication\n- VPN configs include short-lived certificates (24-hour default)\n- OAuth state parameter validation prevents CSRF attacks\n- OpenVPN3 provides industry-standard encryption (AES-256-GCM)\n\n## Permissions\n\n| Permission | Purpose |\n|------------|---------|\n| `INTERNET` | Network communication |\n| `ACCESS_NETWORK_STATE` | Check network connectivity |\n| `ACCESS_WIFI_STATE` | Detect WiFi connection |\n| `CHANGE_NETWORK_STATE` | VPN tunnel configuration |\n| `FOREGROUND_SERVICE` | VPN service notification |\n| `FOREGROUND_SERVICE_SPECIAL_USE` | VPN special use case |\n| `POST_NOTIFICATIONS` | Connection status notifications |\n\n## Troubleshooting\n\n### Build Fails with JDK Version Error\nEnsure you're using JDK 17. The Android Gradle Plugin doesn't support JDK 25+.\n\nSet JAVA_HOME explicitly:\n```bash\nJAVA_HOME=/path/to/jdk17 ./gradlew assembleDebug\n```\n\n### INSTALL_FAILED_UPDATE_INCOMPATIBLE\nThe installed app was signed with a different key. Uninstall first:\n```bash\nadb uninstall com.gatekey.client\nadb install app/build/outputs/apk/debug/app-debug.apk\n```\n\n### NDK Not Found\nInstall NDK via Android Studio: SDK Manager \u003e SDK Tools \u003e NDK (Side by side) \u003e 29.0.14206865\n\n### CMake Not Found\nInstall via Android Studio: SDK Manager \u003e SDK Tools \u003e CMake\n\n### SWIG Not Found\nInstall SWIG for your platform (see Build Dependencies section above).\n\n### VPN Permission Denied\nThe user must grant VPN permission when prompted. If denied, the connection will fail.\n\n### Connection Timeout\nCheck that the Gatekey server is accessible and the server URL is correct.\n\n## License\n\nProprietary - Gatekey\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdye-tech%2Fgatekey-android-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdye-tech%2Fgatekey-android-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdye-tech%2Fgatekey-android-client/lists"}