Azure Proxy — App Setup¶
Create the Entra ID app registration and Application Proxy configuration used to publish the Peek backend. Both methods below produce the same result; use whichever is more convenient.
Prerequisites¶
Entra tenant with a Global Administrator account.
A licence that includes Application Proxy (Entra ID P1 or P2).
A connector group already created and at least one connector registered — see Azure Proxy — Connector VM.
Internal URL resolvable from the connector VM. Application Proxy rejects raw IPs for the internal URL, so use a hostname (a hosts file entry on the connector is acceptable).
Naming conventions used below:
Placeholder |
Example / meaning |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Option A — PowerShell (Microsoft Graph)¶
Run from any machine with PowerShell 7+ and network access to Graph.
Install the Graph module (once):
Install-Module Microsoft.Graph -Scope CurrentUser
Authenticate:
Connect-MgGraph -Scopes `
"Application.ReadWrite.All", `
"Directory.ReadWrite.All", `
"DelegatedPermissionGrant.ReadWrite.All"
Create the app registration:
$app = New-MgApplication -DisplayName "PeekFieldApp" `
-SignInAudience "AzureADMyOrg"
$appId = $app.AppId
$objectId = $app.Id
$externalUrl = "https://peekfieldapp-synerty.msappproxy.net/"
Add the iOS platform redirect URI:
Update-MgApplication -ApplicationId $objectId -PublicClient @{
RedirectUris = @("msauth.com.synerty.peek://auth")
}
Register the Application Proxy external URL as a Web redirect URI.
Application Proxy’s pre-authentication flow uses this same app registration
and sends redirect_uri=<external-url> to Entra — without it Entra
rejects the login with
AADSTS50011: The redirect URI ... does not match the redirect URIs
configured for the application:
Update-MgApplication -ApplicationId $objectId -Web @{
RedirectUris = @($externalUrl)
}
Warning
Register the external URL under Web, not Single-page application
(SPA). Application Proxy pre-auth is a confidential-client server-side
token exchange with no PKCE; SPA registration forces Entra to
require PKCE and login fails with
AADSTS9002325: Proof Key for Code Exchange is required for
cross-origin authorization code redemption.
Expose the user_impersonation API scope and set token version to v2.
Use the Application Proxy external URL as the identifier URI — this keeps the
scope human-readable (https://<external-url>/user_impersonation) and is
consistent across all Peek proxy deployments:
$scopeId = [guid]::NewGuid().ToString()
Update-MgApplication -ApplicationId $objectId `
-IdentifierUris @($externalUrl.TrimEnd('/')) `
-Api @{
RequestedAccessTokenVersion = 2
Oauth2PermissionScopes = @(@{
Id = $scopeId
AdminConsentDescription = "Access Peek as the signed in user"
AdminConsentDisplayName = "Access Peek"
IsEnabled = $true
Type = "User"
Value = "user_impersonation"
})
}
Note
RequestedAccessTokenVersion = 2 is required. The Peek field app uses
the Entra v2.0 token endpoint (/oauth2/v2.0/token); leaving this at
the default (null = v1) causes token acquisition to fail silently
after the redirect returns from login.microsoftonline.com.
Create the service principal and grant admin consent:
$sp = New-MgServicePrincipal -AppId $appId
# Allow any member of the tenant to use the app
Update-MgServicePrincipal -ServicePrincipalId $sp.Id `
-AppRoleAssignmentRequired:$false
Enable Application Proxy (Graph beta endpoint — not in v1.0):
$patch = @{
onPremisesPublishing = @{
internalUrl = "https://peek-internal.example.com"
externalUrl = "https://peekfieldapp-synerty.msappproxy.net/"
externalAuthenticationType = "aadPreAuthentication"
applicationServerTimeout = "Long"
isTranslateHostHeaderEnabled = $true
isHttpOnlyCookieEnabled = $true
isSecureCookieEnabled = $true
}
}
Invoke-MgGraphRequest -Method PATCH `
-Uri "https://graph.microsoft.com/beta/applications/$objectId" `
-Body ($patch | ConvertTo-Json -Depth 5)
Assign the connector group to the app:
$groupId = (Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/onPremisesPublishingProfiles/applicationproxy/connectorGroups" `
).value `
| Where-Object { $_.name -eq "PeekConnectorGroup" } `
| Select-Object -ExpandProperty id
Invoke-MgGraphRequest -Method PUT `
-Uri "https://graph.microsoft.com/beta/applications/$objectId/connectorGroup/`$ref" `
-Body (@{ "@odata.id" = `
"https://graph.microsoft.com/beta/onPremisesPublishingProfiles/applicationproxy/connectorGroups/$groupId" `
} | ConvertTo-Json)
Note
applicationServerTimeout = Long is required for WebSocket support.
The default (Default, 85s) will cut long-lived connections.
Option B — Entra Admin Portal (UI)¶
Sign in to https://entra.microsoft.com as a Global Administrator.
Register the application
Go to Applications -> App registrations -> + New registration.
Name:
PeekFieldApp.Supported account types: Accounts in this organizational directory only.
Redirect URI: leave blank (added per platform below).
Click Register, then note the Application (client) ID.
Add platforms
Go to Authentication -> + Add a platform.
iOS / macOS: Bundle ID
com.synerty.peek. Entra auto-generates the redirect URImsauth.com.synerty.peek://auth.Web: add the Application Proxy external URL, e.g.
https://peekfieldapp-synerty.msappproxy.net/. Application Proxy pre-authentication uses this same app registration and sends the external URL as its redirect URI, so it must be registered here or the proxy login fails withAADSTS50011(redirect URI mismatch).
Do not add the external URL under Single-page application — that forces PKCE on the proxy’s server-side token exchange and login fails with
AADSTS9002325.Expose an API
Go to Expose an API and click Set next to Application ID URI.
Replace the default
api://<client-id>with the Application Proxy external URL (without the trailing slash), e.g.https://peekfieldapp-synerty.msappproxy.net. Using the proxy URL keeps the OAuth2 scope human-readable and consistent across deployments.Click + Add a scope.
Set the scope name to
user_impersonation.Set Who can consent to Admins and users.
Click Add scope.
Go to Manifest.
Set
"requestedAccessTokenVersion": 2and save. The Peek field app uses the v2.0 token endpoint; without this the token exchange fails silently after the OAuth2 redirect.
Application Proxy
Go to Applications -> Enterprise applications -> + New application -> On-premises application.
Name:
PeekFieldApp.Internal URL:
https://peek-internal.example.com(must be a hostname — raw IPs are rejected; see Azure Proxy — Connector VM for the hosts file workaround).External URL: Let Azure generate one — produces
https://peekfieldapp-synerty.msappproxy.net/.Pre-Authentication: Microsoft Entra ID.
Connector Group:
PeekConnectorGroup.Additional settings: set Backend Application Timeout to Long (required for WebSocket).
Click Add.
User assignment
Open the new enterprise application -> Properties.
Assignment required? -> No (so anyone in the tenant can use it).
Save.
Verification¶
The external URL should now return a 302 to
https://login.microsoftonline.com with client_id matching your app:
curl -sI https://peekfieldapp-synerty.msappproxy.net/ | head
Open the external URL in a browser to confirm that sign-in succeeds and the Peek “Enroll This Device” page loads.
Troubleshooting¶
AADSTS50011: The redirect URI … does not match the redirect URIs configured for the application. The Application Proxy external URL has not been registered. Add it under the Web platform of the app registration (see Step 3 above).
AADSTS9002325: Proof Key for Code Exchange is required for cross-origin authorization code redemption. The Application Proxy external URL has been registered under the Single-page application (SPA) platform. Move it to Web — the proxy’s pre-auth token exchange does not use PKCE. Verify with:
# Graph, expects spa.redirectUris == []
# and web.redirectUris contains the external URL
curl -H "Authorization: Bearer <token>" \
"https://graph.microsoft.com/v1.0/applications/<objectId>?\$select=spa,web"
OAuth2 login completes (redirect returns) but the app stays on the loading
screen / no token is stored.
requestedAccessTokenVersion on the app registration is null or 1.
The Peek field app uses the v2.0 token endpoint; requesting a v1 token via
that endpoint fails silently. Set it to 2 in Manifest or via Graph:
PATCH https://graph.microsoft.com/v1.0/applications/<objectId>
{ "api": { "requestedAccessTokenVersion": 2 } }
Forbidden / “You are not authorized to access this application”.
Either (a) the user is not a member of the tenant / not assigned, and the
Enterprise Application has Assignment required = Yes, or (b) the
AADSTS9002325 failure above caused the proxy to fall back to the
Forbidden page. Clear SPA redirect URIs first, then if the error remains,
set Assignment required to No or add the user.
Reference Configurations¶
The non-default fields for a Peek Application Proxy app registration are shown
below. Fields set to null, [], or boilerplate defaults are omitted.
Replace <external-url> and <bundle-id> with your values.
To download the full JSON for any registration:
# Microsoft Graph (requires Directory.Read.All or equivalent)
GET https://graph.microsoft.com/v1.0/applications/<objectId>
Authorization: Bearer <token>
# Azure CLI
az ad app show --id <appId>
# PowerShell
Get-MgApplication -ApplicationId <objectId> | ConvertTo-Json -Depth 10
{
"displayName": "<app-name>",
"appId": "<application-client-id>",
"id": "<object-id>",
"signInAudience": "AzureADMyOrg",
"identifierUris": ["https://<external-url>"],
"publicClient": {
"redirectUris": ["msauth.<bundle-id>://auth"]
},
"web": {
"homePageUrl": "https://<external-url>/",
"logoutUrl": "https://<external-url>/?appproxy=logout",
"redirectUris": ["https://<external-url>/"],
"implicitGrantSettings": {
"enableAccessTokenIssuance": false,
"enableIdTokenIssuance": true
}
},
"spa": { "redirectUris": [] },
"api": {
"requestedAccessTokenVersion": 2,
"oauth2PermissionScopes": [
{ "value": "user_impersonation", "type": "User", "isEnabled": true }
]
},
...
}