Peek Field App — OAuth2 Settings

The Peek field app reads the Application Proxy host and OAuth2 parameters from a built-in defaults asset. For enterprise MDM deployments the same keys can be overridden per device at runtime.

Defaults Asset

File: peek_field_app/src/assets/peek_core_device/server-info-tuple-defaults.json

Shape (matches ServerInfoTuple in peek_core_device/plugin-module/_private/tuples/server-info-tuple.ts):

{
    "host": "peekfieldapp-synerty.msappproxy.net",
    "useSsl": true,
    "httpPort": 443,
    "websocketPort": 443,
    "hasConnected": true,
    "oauth2AppId": "<application-client-id>",
    "oauth2TenantId": "<tenant-id>",
    "oauth2WebRedirectUrl": "https://peekfieldapp-synerty.msappproxy.net/.auth/login/aad/callback",
    "oauth2BundleId": "com.synerty.peek"
}

The oauth2WebRedirectUrl field controls which OAuth2 scope format the field app requests:

  • Omit / leave blank → scope is api://<appId>/user_impersonation (matches an api:// identifier URI on the Entra app registration).

  • Set to the proxy callback URL → scope is https://<host>/user_impersonation (matches an https:// identifier URI, which is the recommended format for Application Proxy deployments).

The recommended setup uses the Application Proxy external URL as the identifier URI (https://peekfieldapp-synerty.msappproxy.net). In that case set oauth2WebRedirectUrl to the proxy’s OIDC callback path:

"oauth2WebRedirectUrl": "https://peekfieldapp-synerty.msappproxy.net/.auth/login/aad/callback"

If you registered api://<appId> as the identifier URI instead, omit oauth2WebRedirectUrl from the JSON.

Field reference:

Key

Meaning

host

External Application Proxy hostname

useSsl

Must be true for Application Proxy

httpPort

443 (TLS)

websocketPort

443 (shares the HTTPS port through proxy)

hasConnected

Set true for baked-in proxy deployments so the app skips the Connect screen and goes straight to OAuth2 on launch

oauth2AppId

appId of the Entra app registration

oauth2TenantId

Entra directory (tenant) ID

oauth2WebRedirectUrl

Omit for Capacitor builds. When present and non-empty, shifts the OAuth2 scope from api://<appId>/… to https://<host>/…. Only needed if the PWA path uses an Application Proxy URL-based identifier URI. See “Browser / PWA Build” below.

oauth2BundleId

iOS bundle ID — used to build msauth.<bundleId>://auth

The asset is loaded once, on first launch, by ServerInfoTuple.loadDefaultValues(). Once hasConnected flips to true the values persist in the device’s offline tuple storage; changes to this JSON will not be picked up until the app is reinstalled (or offline storage is cleared).

MDM Overrides (iOS)

For MDM-managed fleets, push the same values as AppConfig keys. The keys are defined in MdmAppConfigKeyEnum (peek_core_device/plugin-module/_private/hardware-info/hardware-info.ts):

AppConfig key

Maps to

peek.serverConnection.host

host

peek.serverConnection.useSsl

useSsl

peek.serverConnection.httpPort

httpPort

peek.serverConnection. websocketPort

websocketPort

peek.serverConnection. hasConnected

hasConnected

peek.oauth2.appId

oauth2AppId

peek.oauth2.tenantId

oauth2TenantId

peek.oauth2.webRedirectUrl

oauth2WebRedirectUrl

peek.oauth2.bundleId

oauth2BundleId

MDM values are read via @capacitor-community/mdm-appconfig and take precedence over the JSON defaults on FIELD_IOS builds only.

iOS Bundle ID and URL Scheme

The iOS bundle identifier in ios/App/App.xcodeproj/project.pbxproj (PRODUCT_BUNDLE_IDENTIFIER) must match oauth2BundleId. The Capacitor OAuth2 plugin builds the redirect URI as msauth.<bundle-id>://auth at runtime and that exact value must be registered as the iOS redirect URI on the Entra app registration (see Azure Proxy — App Setup).

If you change the bundle ID:

  1. Update PRODUCT_BUNDLE_IDENTIFIER in Xcode.

  2. Update oauth2BundleId in the JSON above.

  3. Update the iOS platform redirect URI on the Entra app.

  4. Re-register the MSAL redirect handler in Info.plist (CFBundleURLSchemes) if it is hardcoded.

Angular Build Configuration

The Peek field app uses a dedicated Angular build configuration, capacitor, which sets serviceWorkerEnabled: false via environment.capacitor.ts. The Angular service worker must be disabled at build time for Capacitor (iOS/Android) builds — leaving it enabled causes the service worker to detect build-hash changes and trigger continuous WebView reloads via clients.navigate(), which bypasses any JavaScript-level interception.

The capacitor configuration is the default for npm run build. For web/PWA builds use ng build --configuration=production.

Browser / PWA Build

When the PWA is served behind Application Proxy, authentication is handled by the proxy’s own pre-auth flow (the user signs in once at the proxy, the proxy sets a session cookie, and the backend receives the X-MS-CLIENT-PRINCIPAL header). The PWA does not run its own MSAL flow, so oauth2WebRedirectUrl is not needed on the native side.

The proxy’s pre-auth does, however, use the PeekFieldApp app registration and sends the external URL as its redirect_uri. That external URL must be registered under the Web platform of the app registration (see Azure Proxy — App Setup). Registering it under Single-page application instead forces PKCE on the proxy’s server-side token exchange and the proxy login fails with AADSTS9002325.

Xcode Cloud Build

For Xcode Cloud deployments the defaults asset is not edited by hand. Fill in app_spec.json at the repo root (including the oauth2 section) and run patch_and_tag_for_xcode_build.py — the script writes server-info-tuple-defaults.json automatically before tagging the build.

See app_spec.json Reference for the full field reference, the serverConnection / oauth2 mapping table, and a worked example.

Troubleshooting

App shows “Connect To Server” instead of redirecting to Entra. The defaults JSON is blank or host is null. Confirm the asset is present in the built App.app bundle at public/assets/peek_core_device/server-info-tuple-defaults.json.

Proxy login returns ``AADSTS9002325`` (PKCE required). The Application Proxy external URL has been registered under the Single-page application platform on the Entra app registration. Move it to Web — Application Proxy pre-auth uses a server-side (confidential-client) token exchange without PKCE, and SPA registration forces PKCE. The iOS flow uses msauth.<bundle-id>://auth under iOS / macOS only.

Proxy login returns ``AADSTS50011`` (redirect URI mismatch). The Application Proxy external URL is not registered on the app registration at all. Add it under the Web platform — see Azure Proxy — App Setup.

OAuth2 browser opens but returns a different redirect-URI error. The iOS platform redirect URI is missing or mismatched. Confirm Entra has msauth.<bundle-id>://auth under iOS / macOS with <bundle-id> equal to oauth2BundleId.

OAuth2 succeeds but the WebSocket drops after ~85 seconds. Application Proxy applicationServerTimeout is still Default. Set it to Long on the Application Proxy app settings.

App reloads continuously (~450 ms cycle) immediately after launch. The Angular service worker was enabled in the Capacitor build. Ensure the build was produced with npm run build (which uses the capacitor configuration) rather than a web/production configuration. The service worker detects build-hash changes on every reinstall and triggers clients.navigate() from the worker context, which cannot be suppressed from JavaScript. See “Angular Build Configuration” above.

App crashes or reloads once ~400 ms after launch, then stabilises. VortexService.setVortexUrl(null) was not called for the native platform. The VortexService static default URL is "/vortex"; on Capacitor it must be explicitly set to null so the service does not attempt an HTTP connection to the Capacitor asset server at startup. This is handled automatically by main.ts as of the current version.