HTTP Authentication¶
This recipe uses App Service Authentication (Easy Auth) with Java HTTP triggers, where authentication is enforced at the platform layer and identity claims are passed in request headers.
Architecture¶
flowchart TD
CLIENT[Client with Microsoft Entra sign-in] --> EASYAUTH[Easy Auth on Function App]
EASYAUTH --> FUNC[HTTP Trigger authLevel=ANONYMOUS]
FUNC --> CLAIMS[Read Easy Auth identity headers]
CLAIMS --> API[Authorization logic] Prerequisites¶
Use AuthorizationLevel.ANONYMOUS in code and enable authentication in the platform:
az webapp auth update \
--resource-group $RG \
--name $APP_NAME \
--enabled true \
--action LoginWithAzureActiveDirectory
| CLI element | Explanation |
|---|---|
| Command(s) | az webapp auth update |
| Key flags | --resource-group, --name, --enabled, --action |
| Variables | $RG, $APP_NAME |
| Expected result | Azure CLI applies the configuration change; confirm the returned JSON or follow-up query shows the expected value. |
Set unauthenticated behavior to require sign-in:
az resource update \
--resource-group $RG \
--name $APP_NAME/authsettingsV2 \
--resource-type "Microsoft.Web/sites/config" \
--set properties.globalValidation.unauthenticatedClientAction=RedirectToLoginPage
| CLI element | Explanation |
|---|---|
| Command(s) | az resource update |
| Key flags | --resource-group, --name, --resource-type, --set |
| Variables | $RG, $APP_NAME |
| Expected result | Azure CLI applies the configuration change; confirm the returned JSON or follow-up query shows the expected value. |
Java implementation¶
package com.contoso.functions;
import com.microsoft.azure.functions.*;
import com.microsoft.azure.functions.annotation.*;
import java.util.Map;
import java.util.Optional;
public class EasyAuthFunction {
@FunctionName("profile")
public HttpResponseMessage run(
@HttpTrigger(
name = "request",
methods = {HttpMethod.GET},
authLevel = AuthorizationLevel.ANONYMOUS,
route = "profile"
) HttpRequestMessage<Optional<String>> request
) {
String userId = request.getHeaders().get("x-ms-client-principal-id");
String identityProvider = request.getHeaders().get("x-ms-client-principal-idp");
String displayName = request.getHeaders().getOrDefault("x-ms-client-principal-name", "unknown");
if (userId == null || userId.isBlank() || identityProvider == null || identityProvider.isBlank()) {
return request.createResponseBuilder(HttpStatus.UNAUTHORIZED)
.body(Map.of("error", "Missing Easy Auth identity headers"))
.build();
}
return request.createResponseBuilder(HttpStatus.OK)
.header("Content-Type", "application/json")
.body(Map.of(
"userId", userId,
"identityProvider", identityProvider,
"displayName", displayName,
"message", "Authenticated by Easy Auth"
))
.build();
}
}
Implementation notes¶
- Keep trigger auth at
ANONYMOUSwhen Easy Auth is the enforcement point. - Trust identity only when the request came through App Service Authentication.
- Read identity from
x-ms-client-principal-id,x-ms-client-principal-idp, and optionalx-ms-client-principal-nameheaders. - Add role checks only when endpoint-level authorization decisions are required.