Commercial SupportGuaranteed response times on Shiny bug fixes, straight from the maintainers. Plans from US$1,500 a year.Guaranteed response times on Shiny bug fixes, straight from the maintainers. Plans from US$1,500 a year.See the plans
BLE Hubs 1.0Think SignalR for BLE!Think SignalR for BLE!Hub it up!
UniHub 1.0Universal Hubs - SignalR Styled Hub BLE or HTTP - Why not both!?Universal Hubs - SignalR Styled Hub BLE or HTTP - Why not both!?YES PLEASE!
VPN
The VPN bridge lets the page install the app’s profile in the operating system’s built-in IKEv2 VPN client, then
connect, disconnect and watch the tunnel. It’s built on Shiny.Net.Vpn. The OS owns the tunnel: it keeps
running after the app closes, shows in the system VPN settings, and the user can switch it off or delete it there.
This is IKEv2 only, through the OS’s own client. WireGuard, OpenVPN and custom protocols need a packet tunnel extension
or a VpnService, which this bridge does not provide.
Apple: enable the Personal VPN capability on the App ID and add the
com.apple.developer.networking.vpn.api entitlement with the value allow-vpn.
Android: no manifest entries are needed.
Linux: install network-manager-strongswan (Debian, Ubuntu) or NetworkManager-strongswan (Fedora). Saving and
connecting go through polkit: interactive on a desktop, and a polkit rule on a headless device.
An app that already calls services.AddVpn() keeps its registration. See Shiny.Net.Vpn.
Platforms expose different parts of their VPN client, so check capabilities from GET vpn before offering an option.
An option the platform lacks answers 501 not_supported.
Capability
Missing on
status
Android 11 and 12: the state is Unknown, connect returns once the OS accepts the request, and vpn.status never fires
certificate
Linux, which reads certificates from files rather than taking them inline
serverRootCertificate
Apple, which only trusts a private CA the user installed through a configuration profile
remoteIdentifier
Android, which always uses the server address as the server’s identity
PUT vpn/profile installs the app’s one profile, or replaces it. It takes a name, a serverAddress and one of three
kinds of authentication:
authentication
Needs
SharedSecret
secret, the pre-shared key. Servers usually look it up by localIdentifier, which Android requires
UsernamePassword
username and password, for EAP-MSCHAPv2
Certificate
pkcs12, the client certificate and its private key as a base64 .p12 bundle, with its password. Android requires localIdentifier
remoteIdentifier is the server’s IKE ID (the server address when left out), and serverRootCertificate is the CA
certificate, DER or PEM, that issued the server’s, for a server with a private CA.
The first save shows the OS consent prompt. A user who declines gets { access: "Denied" } and nothing is saved. Saving
does not connect, and a tunnel that is up keeps its old settings until the next connect. Secrets go to the keychain or
keystore and are never read back. DELETE vpn/profile disconnects and deletes the profile and its secrets.
POST vpn/connect brings the tunnel up and waits for it, timeoutSeconds (1 to 300, 30 by default), then answers the
new state. POST vpn/disconnect takes it down and keeps the profile. vpn.status fires on every change, including ones
the user makes in system settings and the OS reconnecting on its own, and starts with the current state when the page
subscribes.
The profile is incomplete, or timeoutSeconds is out of range
403
vpn_permission
No profile is saved, the user withdrew consent, or an entitlement is missing
501
not_supported
The platform has no VPN client to drive, or lacks the option asked for
502
vpn_connection_failed
The tunnel did not come up: rejected credentials, a server that does not answer, a rejected certificate, or the timeout. The message carries the OS’s reason
Installs or replaces the app's VPN profile. The first save shows the OS consent prompt, and a user who declines answers Denied with nothing saved. Saving does not connect. Fails with 400 when the profile is incomplete, and 501 when the platform cannot save this kind of profile.
Brings the tunnel up and waits until it is connected. Fails with 403 vpn_permission when no profile is saved or the user withdrew consent, and 502 vpn_connection_failed with the OS's reason when the tunnel does not come up in time.
The IKEv2 profile to install. The app owns exactly one, so saving again replaces it. Secrets go to the OS's keychain or keystore and are never read back.
name
string
The name shown in the system VPN settings (Android lists the profile under the app's name).
The VPN decides where the device’s traffic goes, so a page that can save a profile can send it to a server of its
choosing. The bridge sits behind the bridge policy like every other (callers on this device only, plus the launch
session), but register it only for a web app you ship. Don’t put credentials in the web app’s bundle: fetch them from
your server after the user signs in. The C# VpnProfileRequest leaves its secrets out of ToString(), so a logged
request doesn’t leak them. See Security.