Skip to content

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 ANONYMOUS when 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 optional x-ms-client-principal-name headers.
  • Add role checks only when endpoint-level authorization decisions are required.

See Also

Sources