Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5718c9bae2 | ||
|
|
2c79edabea | ||
|
|
6e12a608b3 | ||
|
|
5718492e2b | ||
|
|
3bfb38ebd7 | ||
|
|
1de63af07b |
+34
-30
@@ -125,7 +125,15 @@ Created through the UniFi Network API (site `default`):
|
||||
|---|---|---|
|
||||
| Firewall policy "Allow APs RADIUS" | `62c21e63-8c15-4720-adf8-b2333c090e2f` | zone Isolated `10.2.10.0/24` → zone External `10.2.99.91`, UDP `1812-1813`, ALLOW, IPv4 |
|
||||
| RADIUS profile "Cluster 802.1X" | `3e5fcfed-63dc-4e7d-ad51-17cbc074e4bb` | auth `10.2.99.91:1812`, acct `10.2.99.91:1813`, secret `DOT1X_NAS_SECRET`, VLAN assignment on (`vlan_wlan_mode: optional`) |
|
||||
| WLAN "Renner Test" | `3eba27e7-ddc2-41fb-ad3f-82add317847a` | copy of "Renner UniFi" (WPA2/WPA3 Enterprise transition, fast roaming, BSS transition, same AP group and bands), network (90) Guest as fallback, RADIUS profile "Cluster 802.1X" |
|
||||
| WLAN "Renner UniFi" | `ef4122f2-4a83-4dca-9ef3-468d29f39a6b` | WPA3 Enterprise (no transition), PMF required, fast roaming, BSS transition, client isolation off, RADIUS profile "Cluster 802.1X"; Application Hotspot, type Passpoint (set in the UniFi UI: the API format differs from the UI's) |
|
||||
|
||||
Passpoint on "Renner UniFi" (UniFi offers Passpoint only with WPA3 Enterprise):
|
||||
venue "Renner", Residential / Private Residence, network type Private with
|
||||
Guest Access, IPv4 single NATed private, IPv6 available, NAI realm
|
||||
`renner.uno` with EAP-TTLS, sub-methods PAP and username/password, domain
|
||||
`renner.uno`, operator friendly name "Renner", connection capability ICMP
|
||||
allow. The AKMs on air are `FT/802.1X` and `802.1X/SHA-256`; plain `802.1X`
|
||||
is not offered.
|
||||
|
||||
## Live login check
|
||||
|
||||
@@ -146,20 +154,22 @@ For IPv6 set `LIVE_SOURCE` to the workstation's `fd02:50::` address and use
|
||||
## Client setup (SSID "Renner UniFi")
|
||||
|
||||
Setup page: `https://wlan.renner.uno` (behind the Authentik gate, any
|
||||
authentik user; `kubernetes/apps/authentik/wlan-setup*.yaml`). It serves the
|
||||
Apple profile (caller's username filled in), a Windows file that imports the
|
||||
WLAN profile with `netsh`, and the Linux `nmcli` command. None of these carries a password.
|
||||
authentik user; `kubernetes/apps/authentik/wlan-setup*.yaml`). Android and
|
||||
Apple get Passpoint profiles with their own app password; Windows gets a file
|
||||
that imports the WLAN profile with `netsh`, Linux an `nmcli` command
|
||||
(NetworkManager has no Passpoint support). The Windows and Linux setups carry
|
||||
no password.
|
||||
|
||||
Android gets a Passpoint profile (`application/x-wifi-config`) with its own
|
||||
app password. "Auf Android installieren" (`/android/install`) signs the user in
|
||||
through the authentik OAuth2 application `wlan-setup` (scope
|
||||
`goauthentik.io/api`). On `/android/callback`, nginx (njs) exchanges the code,
|
||||
creates an app password (`wlan-android-<user>-<timestamp>-<random>`) with the
|
||||
user's own access token, and returns the profile in the response to that GET,
|
||||
as the Android installer requires. The page stores nothing. Deleting the app
|
||||
password in authentik removes that device from the WLAN. The profile matches
|
||||
WLANs that advertise Hotspot 2.0 with domain and NAI realm `renner.uno`
|
||||
(EAP-TTLS/PAP). Creating the app password needs no admin rights.
|
||||
Passpoint (Android, Apple): `/<platform>/install` (`android` or `apple`) signs
|
||||
the user in through the authentik OAuth2 application `wlan-setup` (scope
|
||||
`goauthentik.io/api`). On `/<platform>/callback`, nginx (njs) exchanges the
|
||||
code, creates an app password (`wlan-<platform>-<user>-<timestamp>-<random>`)
|
||||
with the user's own access token, and returns the profile in the response to
|
||||
that GET: Android `application/x-wifi-config` (as its installer requires),
|
||||
Apple a `.mobileconfig`. The page stores nothing. Deleting the app password in
|
||||
authentik removes that device from the WLAN. The profiles match WLANs that
|
||||
advertise Hotspot 2.0 with domain and NAI realm `renner.uno` (EAP-TTLS/PAP),
|
||||
i.e. "Renner UniFi". Creating the app password needs no admin rights.
|
||||
|
||||
App passwords expire when unused. The page creates them with 29 days (the API
|
||||
caps new tokens at 30 days unless the group attribute
|
||||
@@ -179,14 +189,7 @@ is never sent in clear over the air.
|
||||
|
||||
### Android
|
||||
|
||||
- EAP method: TTLS
|
||||
- Phase 2 authentication: PAP
|
||||
- CA certificate: Use system certificates
|
||||
- Domain: `radius.renner.uno`
|
||||
- Identity: authentik username
|
||||
- Anonymous identity: `anonymous` (mandatory; empty sends the login to the
|
||||
UDM, where it fails)
|
||||
- Password: authentik password
|
||||
Passpoint profile from the setup page ("Auf Android installieren").
|
||||
|
||||
### Linux (NetworkManager)
|
||||
|
||||
@@ -203,7 +206,7 @@ is never sent in clear over the air.
|
||||
Settings > Network & Internet > Wi-Fi > Manage known networks > Add network:
|
||||
|
||||
- Network name: `Renner UniFi`
|
||||
- Security type: WPA2-Enterprise AES
|
||||
- Security type: WPA3-Enterprise AES
|
||||
- EAP method: EAP-TTLS
|
||||
- Authentication method: Unencrypted password (PAP)
|
||||
- Server validation: where offered ("Verify server identity" / trusted
|
||||
@@ -218,13 +221,14 @@ wireless network" instead.
|
||||
|
||||
### Apple (iOS, iPadOS, macOS)
|
||||
|
||||
Apple devices need a configuration profile; the setup page serves it with the
|
||||
username filled in. Install it via Settings (Profile Downloaded). The device
|
||||
asks for the password on the first join. The profile sets security type Any (WPA2/WPA3), outer identity
|
||||
`anonymous` and trusted server name `radius.renner.uno`; it contains no
|
||||
password and no certificate. Apple
|
||||
devices may show a one-time "trust certificate" prompt for `radius.renner.uno`
|
||||
on the first join.
|
||||
Passpoint configuration profile from the setup page ("Profil laden"),
|
||||
installed via Settings (Profile Downloaded) or, on a Mac, System Settings >
|
||||
General > Device Management. It sets `IsHotspot` with domain and NAI realm
|
||||
`renner.uno` (no SSID), security type Any, outer identity `anonymous`,
|
||||
trusted server name `radius.renner.uno`, username and app password; it
|
||||
contains no certificate. Its PayloadIdentifier is fixed, so installing it
|
||||
replaces an earlier profile. Apple devices may show a one-time "trust
|
||||
certificate" prompt for `radius.renner.uno` on the first join.
|
||||
|
||||
## Measurement: authentication latency per SSID
|
||||
|
||||
|
||||
@@ -1698,6 +1698,8 @@ data:
|
||||
redirect_uris:
|
||||
- url: https://wlan.renner.uno/android/callback
|
||||
matching_mode: strict
|
||||
- url: https://wlan.renner.uno/apple/callback
|
||||
matching_mode: strict
|
||||
|
||||
- model: authentik_core.application
|
||||
identifiers:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# wlan.renner.uno: setup files for "Renner UniFi" (802.1X, EAP-TTLS/PAP
|
||||
# against freeradius, outer identity anonymous, server name radius.renner.uno).
|
||||
# Served by wlan-setup (wlan-setup.yaml) behind the Authentik gate; the
|
||||
# username comes from X-authentik-username. Only the Android Passpoint profile
|
||||
# carries a credential (the format requires it): a per-device authentik app
|
||||
# password that the page creates with the user's own OAuth access token.
|
||||
# username comes from X-authentik-username. The Android and Apple Passpoint
|
||||
# profiles carry a credential: a per-device authentik app password that the
|
||||
# page creates with the user's own OAuth access token.
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
@@ -77,75 +77,6 @@ data:
|
||||
return 200 $wifi_user;
|
||||
}
|
||||
|
||||
# Apple: com.apple.wifi.managed, TTLS (21) with inner PAP. Fixed
|
||||
# PayloadIdentifier/UUIDs so a reinstall replaces the old profile.
|
||||
location = /renner-unifi.mobileconfig {
|
||||
default_type application/x-apple-aspen-config;
|
||||
add_header Cache-Control "no-store" always;
|
||||
add_header Content-Disposition 'attachment; filename="renner-unifi.mobileconfig"' always;
|
||||
return 200 '<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PayloadContent</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.wifi.managed</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>uno.renner.wifi.renner-unifi.network</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>824959bf-c55d-4ed2-b569-c33f3759c2b6</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Renner UniFi</string>
|
||||
<key>PayloadOrganization</key>
|
||||
<string>Renner</string>
|
||||
<key>SSID_STR</key>
|
||||
<string>Renner UniFi</string>
|
||||
<key>HIDDEN_NETWORK</key>
|
||||
<false/>
|
||||
<key>AutoJoin</key>
|
||||
<true/>
|
||||
<key>EncryptionType</key>
|
||||
<string>Any</string>
|
||||
<key>EAPClientConfiguration</key>
|
||||
<dict>
|
||||
<key>UserName</key>
|
||||
<string>$wifi_user</string>
|
||||
<key>OuterIdentity</key>
|
||||
<string>anonymous</string>
|
||||
<key>AcceptEAPTypes</key>
|
||||
<array>
|
||||
<integer>21</integer>
|
||||
</array>
|
||||
<key>TTLSInnerAuthentication</key>
|
||||
<string>PAP</string>
|
||||
<key>TLSTrustedServerNames</key>
|
||||
<array>
|
||||
<string>radius.renner.uno</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
<key>PayloadType</key>
|
||||
<string>Configuration</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>uno.renner.wifi.renner-unifi</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>7175a2a3-ddd3-42ea-b4ad-b7e5501892f3</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>WLAN Renner UniFi</string>
|
||||
<key>PayloadOrganization</key>
|
||||
<string>Renner</string>
|
||||
</dict>
|
||||
</plist>
|
||||
';
|
||||
}
|
||||
|
||||
location = /renner-unifi-wlan.cmd {
|
||||
default_type application/octet-stream;
|
||||
add_header Cache-Control "no-store" always;
|
||||
@@ -153,16 +84,17 @@ data:
|
||||
try_files /renner-unifi-wlan.cmd =404;
|
||||
}
|
||||
|
||||
# Android: a tap on /android/install starts an authorization-code
|
||||
# sign-in at authentik (the user is already signed in there); the
|
||||
# callback creates the app password as the user and answers the same
|
||||
# navigation with the Passpoint profile (application/x-wifi-config,
|
||||
# base64, no Content-Disposition), as the Android installer requires.
|
||||
location = /android/install {
|
||||
# Android and Apple: a tap on /<platform>/install starts an
|
||||
# authorization-code sign-in at authentik (the user is already signed
|
||||
# in there); the callback creates the app password as the user and
|
||||
# answers the same navigation with the Passpoint profile. Android:
|
||||
# application/x-wifi-config, base64, no Content-Disposition, as its
|
||||
# installer requires. Apple: a .mobileconfig download.
|
||||
location ~ ^/(android|apple)/install$ {
|
||||
js_content passpoint.install;
|
||||
}
|
||||
|
||||
location = /android/callback {
|
||||
location ~ ^/(android|apple)/callback$ {
|
||||
# The query carries the one-time authorization code.
|
||||
access_log off;
|
||||
js_content passpoint.callback;
|
||||
@@ -216,6 +148,11 @@ data:
|
||||
# (authorization code, scope goauthentik.io/api). It starts with 29 days
|
||||
# (below the 30-day token cap); each 802.1X login renews it to 60 days
|
||||
# (policy dot1x-app-password-renew).
|
||||
# Apple: com.apple.wifi.managed with IsHotspot, DomainName and NAIRealmNames
|
||||
# renner.uno (no SSID: Passpoint matching), TTLS (21) with inner PAP, outer
|
||||
# identity anonymous, trusted server name radius.renner.uno, username and
|
||||
# app password. Fixed PayloadIdentifier/UUIDs so a reinstall replaces the
|
||||
# previous profile.
|
||||
passpoint.js: |
|
||||
const ISRG_ROOT_X1 = "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZLubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=";
|
||||
const USER = /^[A-Za-z0-9._@+-]{1,64}$/;
|
||||
@@ -253,8 +190,60 @@ data:
|
||||
return b64(mime);
|
||||
}
|
||||
|
||||
function xml(s) {
|
||||
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
}
|
||||
|
||||
function mobileconfig(user, password) {
|
||||
return '<?xml version="1.0" encoding="UTF-8"?>\n' +
|
||||
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n' +
|
||||
'<plist version="1.0"><dict>' +
|
||||
'<key>PayloadContent</key><array><dict>' +
|
||||
'<key>PayloadType</key><string>com.apple.wifi.managed</string>' +
|
||||
'<key>PayloadVersion</key><integer>1</integer>' +
|
||||
'<key>PayloadIdentifier</key><string>uno.renner.wifi.renner-unifi.network</string>' +
|
||||
'<key>PayloadUUID</key><string>824959bf-c55d-4ed2-b569-c33f3759c2b6</string>' +
|
||||
'<key>PayloadDisplayName</key><string>Renner UniFi</string>' +
|
||||
'<key>PayloadOrganization</key><string>Renner</string>' +
|
||||
'<key>IsHotspot</key><true/>' +
|
||||
'<key>DomainName</key><string>renner.uno</string>' +
|
||||
'<key>NAIRealmNames</key><array><string>renner.uno</string></array>' +
|
||||
'<key>DisplayedOperatorName</key><string>Renner</string>' +
|
||||
'<key>ServiceProviderRoamingEnabled</key><false/>' +
|
||||
'<key>AutoJoin</key><true/>' +
|
||||
'<key>EncryptionType</key><string>Any</string>' +
|
||||
'<key>EAPClientConfiguration</key><dict>' +
|
||||
'<key>UserName</key><string>' + xml(user) + '</string>' +
|
||||
'<key>UserPassword</key><string>' + xml(password) + '</string>' +
|
||||
'<key>OuterIdentity</key><string>anonymous</string>' +
|
||||
'<key>AcceptEAPTypes</key><array><integer>21</integer></array>' +
|
||||
'<key>TTLSInnerAuthentication</key><string>PAP</string>' +
|
||||
'<key>TLSTrustedServerNames</key><array><string>radius.renner.uno</string></array>' +
|
||||
'</dict></dict></array>' +
|
||||
'<key>PayloadType</key><string>Configuration</string>' +
|
||||
'<key>PayloadVersion</key><integer>1</integer>' +
|
||||
'<key>PayloadIdentifier</key><string>uno.renner.wifi.renner-unifi</string>' +
|
||||
'<key>PayloadUUID</key><string>7175a2a3-ddd3-42ea-b4ad-b7e5501892f3</string>' +
|
||||
'<key>PayloadDisplayName</key><string>WLAN Renner UniFi</string>' +
|
||||
'<key>PayloadOrganization</key><string>Renner</string>' +
|
||||
'</dict></plist>\n';
|
||||
}
|
||||
|
||||
const PLATFORMS = {
|
||||
android: { label: "Android" },
|
||||
apple: { label: "Apple" },
|
||||
};
|
||||
|
||||
// "android" or "apple" from /<platform>/install or /<platform>/callback.
|
||||
function platform(r) {
|
||||
return r.uri.split("/")[1];
|
||||
}
|
||||
|
||||
function redirectUri(name) {
|
||||
return "https://wlan.renner.uno/" + name + "/callback";
|
||||
}
|
||||
|
||||
const CLIENT_ID = "wlan-setup";
|
||||
const REDIRECT_URI = "https://wlan.renner.uno/android/callback";
|
||||
const AUTHORIZE = "https://auth.renner.uno/application/o/authorize/";
|
||||
const STATE_COOKIE = "wlan_oauth_state";
|
||||
const LIFETIME_DAYS = 29;
|
||||
@@ -300,19 +289,21 @@ data:
|
||||
}
|
||||
|
||||
function install(r) {
|
||||
const name = platform(r);
|
||||
const state = random();
|
||||
r.headersOut["Set-Cookie"] = STATE_COOKIE + "=" + state +
|
||||
"; Path=/android/; Max-Age=300; HttpOnly; Secure; SameSite=Lax";
|
||||
"; Path=/" + name + "/; Max-Age=300; HttpOnly; Secure; SameSite=Lax";
|
||||
r.return(302, AUTHORIZE + "?" + form({
|
||||
response_type: "code",
|
||||
client_id: CLIENT_ID,
|
||||
redirect_uri: REDIRECT_URI,
|
||||
redirect_uri: redirectUri(name),
|
||||
scope: "openid profile goauthentik.io/api",
|
||||
state: state,
|
||||
}));
|
||||
}
|
||||
|
||||
async function callback(r) {
|
||||
const name = platform(r);
|
||||
try {
|
||||
const state = cookie(r, STATE_COOKIE);
|
||||
if (!state || r.args.state !== state || !r.args.code) { r.return(400, "Bitte die Einrichtung neu starten.\n"); return; }
|
||||
@@ -320,7 +311,7 @@ data:
|
||||
const grant = await ak(r, "POST", "/application/o/token/", "Basic", client, FORM, form({
|
||||
grant_type: "authorization_code",
|
||||
code: r.args.code,
|
||||
redirect_uri: REDIRECT_URI,
|
||||
redirect_uri: redirectUri(name),
|
||||
}));
|
||||
const access = grant.access_token;
|
||||
const me = await ak(r, "GET", "/api/v3/core/users/me/", "Bearer", access, "");
|
||||
@@ -329,23 +320,29 @@ data:
|
||||
|
||||
const now = new Date();
|
||||
const stamp = now.toISOString().replace(/[-:]/g, "").replace(/\..*$/, "");
|
||||
const identifier = "wlan-android-" + user.replace(/[^A-Za-z0-9-]/g, "-").toLowerCase() + "-" + stamp + "-" + random().substring(0, 6).replace(/[^A-Za-z0-9]/g, "x");
|
||||
const identifier = "wlan-" + name + "-" + user.replace(/[^A-Za-z0-9-]/g, "-").toLowerCase() + "-" + stamp + "-" + random().substring(0, 6).replace(/[^A-Za-z0-9]/g, "x");
|
||||
const expires = new Date(now.getTime() + LIFETIME_DAYS * 86400000).toISOString();
|
||||
await ak(r, "POST", "/api/v3/core/tokens/", "Bearer", access, JSON_CT, JSON.stringify({
|
||||
identifier: identifier,
|
||||
intent: "app_password",
|
||||
description: "WLAN Android, " + now.toISOString().substring(0, 10) + " (wlan.renner.uno)",
|
||||
description: "WLAN " + PLATFORMS[name].label + ", " + now.toISOString().substring(0, 10) + " (wlan.renner.uno)",
|
||||
expiring: true,
|
||||
expires: expires,
|
||||
}));
|
||||
const key = (await ak(r, "GET", "/api/v3/core/tokens/" + identifier + "/view_key/", "Bearer", access, "")).key;
|
||||
|
||||
r.headersOut["Set-Cookie"] = STATE_COOKIE + "=; Path=/android/; Max-Age=0; HttpOnly; Secure; SameSite=Lax";
|
||||
r.headersOut["Content-Type"] = "application/x-wifi-config";
|
||||
r.headersOut["Content-Transfer-Encoding"] = "base64";
|
||||
r.return(200, profile(user, key));
|
||||
r.headersOut["Set-Cookie"] = STATE_COOKIE + "=; Path=/" + name + "/; Max-Age=0; HttpOnly; Secure; SameSite=Lax";
|
||||
if (name === "apple") {
|
||||
r.headersOut["Content-Type"] = "application/x-apple-aspen-config";
|
||||
r.headersOut["Content-Disposition"] = 'attachment; filename="renner-unifi.mobileconfig"';
|
||||
r.return(200, mobileconfig(user, key));
|
||||
} else {
|
||||
r.headersOut["Content-Type"] = "application/x-wifi-config";
|
||||
r.headersOut["Content-Transfer-Encoding"] = "base64";
|
||||
r.return(200, profile(user, key));
|
||||
}
|
||||
} catch (e) {
|
||||
r.error("wlan-setup android: " + e.message);
|
||||
r.error("wlan-setup " + name + ": " + e.message);
|
||||
r.return(502, "Die Einrichtung ist fehlgeschlagen.\n");
|
||||
}
|
||||
}
|
||||
@@ -383,7 +380,7 @@ data:
|
||||
<body>
|
||||
<main>
|
||||
<h1>WLAN einrichten</h1>
|
||||
<p>WLAN <strong>Renner UniFi</strong>. Anmeldung mit deinem Konto <strong id="user">…</strong> und deinem authentik-Passwort.</p>
|
||||
<p>WLAN <strong>Renner UniFi</strong> für dein Konto <strong id="user">…</strong>. Android, iPhone, iPad und Mac bekommen ein eigenes WLAN-App-Passwort; Windows und Linux melden sich mit deinem authentik-Passwort an.</p>
|
||||
|
||||
<div id="detected"></div>
|
||||
|
||||
@@ -403,11 +400,12 @@ data:
|
||||
<template id="t-apple">
|
||||
<section data-os="apple">
|
||||
<h2>iPhone, iPad, Mac</h2>
|
||||
<p><a class="button" href="/renner-unifi.mobileconfig">Profil laden</a></p>
|
||||
<p><a class="button" href="/apple/install">Profil laden</a></p>
|
||||
<ol>
|
||||
<li>iPhone/iPad: Einstellungen → „Profil geladen“ → Installieren. Mac: Systemeinstellungen → Allgemein → Geräteverwaltung → Profil doppelklicken.</li>
|
||||
<li>Beim ersten Verbinden mit „Renner UniFi“ dein Passwort eingeben.</li>
|
||||
<li>Das Gerät verbindet sich danach selbst mit „Renner UniFi“.</li>
|
||||
</ol>
|
||||
<p class="muted">Das Gerät bekommt ein eigenes WLAN-App-Passwort in deinem authentik-Konto; dort gelöscht, ist das Gerät aus dem WLAN.</p>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user