UnpadAccess on Android (EAP-TLS)
UnpadAccess is Universitas Padjadjaran's campus Wi-Fi, authenticated with WPA2-Enterprise + EAP-TLS: a per-device client certificate issued after the device's MAC address is registered. There is no password.
Three Android-specific behaviours cause nearly every failure here, and none of them announce themselves:
- Android randomizes its MAC per network by default (Android 10+), while Unpad binds authorization to the MAC captured at registration. Left alone, the certificate is valid and the device is still rejected.
- A certificate imported for "VPN and apps" never appears in Wi-Fi settings. The import dialog defaults to the wrong category.
- Private DNS in strict mode fails closed. If the configured DoT hostname is unreachable — which it will be on a captive registration network — Android returns no DNS at all rather than falling back.
Workflow
1. Register the device
Registration must happen from the device itself; it captures that device's MAC.
- Connect to the open SSID
UnpadAccessRegistration. - Open
https://goah.unpad.ac.idand log in with the PAuS ID. - Tap Daftarkan Perangkat, enter a device name (letters, digits, spaces; max 16 characters), confirm the OS is Android, then Simpan Data Perangkat.
- Tap the .p12 button to download. The portal shows the import password and the certificate name on the same page.
- Quota is 5 devices per PAuS ID.
The user must type their own PAuS password and CAPTCHA. Do not enter credentials for them.
If the portal will not load at this step, jump to Private DNS before assuming the network is down — this is by far the most common blocker, and it looks like the portal is offline.
2. Install the certificate as a Wi-Fi certificate
Settings → Biometrics and security → Other security settings → Install from
device storage, pick the .p12, enter the portal password.
At the naming dialog, change Used for from VPN and apps to Wi-Fi.
This is the step people miss: leave it on the default and the certificate
installs successfully but is invisible to the Wi-Fi configuration screen, which
looks identical to the certificate having failed to install.
A correct bundle reports one user key, one user certificate, and the CA chain.
3. Configure the network
Tap UnpadAccess and set:
| Field | Value |
|---|---|
| EAP method | TLS (default is PEAP) |
| Identity | the certificate's CN — <PAuS-ID>@unpad.net |
| CA certificate | the certificate just installed |
| User certificate | the same certificate |
Selecting TLS removes the password field, which is a useful confirmation that the method actually changed.
If association later fails against the CA, Don't validate is the documented
fallback — it disables server validation only, and the client certificate still
authenticates the device.
4. Set MAC address type before connecting
Under Advanced → MAC address type, switch Randomized MAC to Phone MAC. Do this before the first connection attempt: the registration bound
authorization to the hardware MAC, and a randomized one is simply a different,
unauthorized device from the network's point of view.
Then Save and Connect. Note that Save returns to the configuration screen without connecting — the separate Connect tap is required.
5. Verify, then clean up
Confirm the device actually reached the internet rather than merely associating:
adb shell "ip addr show wlan0 | grep 'inet '" # campus lease, not the registration subnet
adb shell "ping -c 2 8.8.8.8" # routing
adb shell "ping -c 2 support.unpad.ac.id" # resolution
The registration network and UnpadAccess hand out different subnets, so the lease alone tells you which network you are really on.
Finally, long-press UnpadAccessRegistration → Forget network, so the
device stops drifting back to the registration SSID.
Private DNS fails closed
Worth checking first whenever anything "loads nothing" — including the registration portal.
adb shell settings get global private_dns_mode # hostname | opportunistic | off
adb shell settings get global private_dns_specifier
hostname means strict mode. Android will not fall back to plaintext DNS when
the configured DoT provider is unreachable, and campus networks routinely block
port 853, so every lookup fails with ERR_NAME_NOT_RESOLVED while ICMP still
works fine.
adb shell settings put global private_dns_mode opportunistic
opportunistic keeps encrypted DNS where it is available and degrades
gracefully where it is not. Tell the user if this disables a DNS-based ad
blocker they were relying on, and that restoring hostname will break
resolution again on campus.
Driving setup over adb / scrcpy
Useful when helping someone else, or when the on-screen flow is fiddly.
adb devices -l # confirm authorized
scrcpy --stay-awake
adb shell svc wifi enable
adb shell am start -a android.settings.WIFI_SETTINGS
adb shell am start -a android.settings.SECURITY_SETTINGS
adb shell am start -a android.intent.action.VIEW -d "https://goah.unpad.ac.id"
adb exec-out screencap -p > screen.png # read state before tapping
Screenshot before each tap. Coordinates from screencap map 1:1 onto
input tap, but menu positions shift between OEM skins and Android versions,
so tapping from a remembered layout goes wrong quietly.
Two practical notes. adb shell input text needs %s for spaces, and some
keyevent codes are remapped by OEM keyboards — keyevent 111 (Escape) can
emit a stray character instead of dismissing the keyboard, so verify the field
contents afterwards rather than trusting the keystroke. adb shell cmd wifi
subcommands require root and will refuse with a SecurityException on stock
devices; drive the UI instead.
Enabling Wi-Fi stops any active hotspot, since most phones share one radio. If a laptop is tethered to this phone, it loses connectivity at that moment — arrange another path for it first.
Reference
references/troubleshooting.md — symptom table, adb diagnostics, official links.