Azure App Service Authentication / Authorization returns HTTP 401 IDX10205: Issuer validation failed

Viewed 3815

I am having an issue calling my a Azure Web App Service application (REST API) secured with the built-in Authentication / Authorization at App Service level.

Context:

  • rest API deployed in Azure Web App Service;
  • app is secured with the Azure Web App Service built-in Authentication / Authorization feature;
  • on-premise script authenticates against it

Target application is a simple Spring Boot application with endpoint /test that returns Test OK. Does not handle security on the application itself, the goal was to test if it can be handled on "infrastructure" side, meaning without development on the services.

It is configured like so:

Azure Web App Service configuration

The App Registrations were done following this guide.

As a client, I am using the sample Microsoft provides here except the request is done to the target application instead of Microsoft Graph.

To achieve that, the following configuration file is used:

{
    "authority": "https://login.microsoftonline.com/<my_tenant_id>",
    "client_id": "<my_client_id>",
    "scope": ["<API URI ( in form of api://GUID)>/.default"],
    "secret": "<my_client_secret>",
    "endpoint": "target_application_endpoint"
}

When I run it, I get the HTTP 401 and the following json respose body:

{
  "code": 401,
  "message": "IDX10205: Issuer validation failed. Issuer: '[PII is hidden]'. Did not match: validationParameters.ValidIssuer: '[PII is hidden]' or validationParameters.ValidIssuers: '[PII is hidden]'."
}

I also used the equivalent sample with the previous library (adal) and I can replicated the flow in Postman with the same result, therefore I do not believe there is any issue with the code sample.

This suggests the issuer of the token is not the same but when I access my application settings in Kudu I have the following:

{
  "deployment_branch": "master",
  "SCM_TRACE_LEVEL": "Verbose",
  "SCM_COMMAND_IDLE_TIMEOUT": "60",
  "SCM_LOGSTREAM_TIMEOUT": "7200",
  "SCM_BUILD_ARGS": "",
  "WEBSITE_AUTH_MSA_SCOPE": "",
  "ScmType": "VSTSRM",
  "WEBSITE_AUTH_UNAUTHENTICATED_ACTION": "RedirectToLoginPage",
  "WEBSITE_AUTH_AUTO_AAD": "False",
  "WEBSITE_AUTH_OPENID_ISSUER": "https://login.microsoftonline.com/<my_tenant_id>/",
  "WEBSITE_AUTH_LOGOUT_PATH": "/.auth/logout",
  "WEBSITE_AUTH_RUNTIME_VERSION": "~1",
  "WEBSITE_SITE_NAME": "<my_app_service_name>",
  "WEBSITE_AUTH_FB_SCOPE": "",
  "WEBSITE_AUTH_TOKEN_STORE": "False",
  "WEBSITE_AZMON_ENABLED": "True",
  "WEBSITE_AUTH_ENABLED": "True",
  "FUNCTIONS_RUNTIME_SCALE_MONITORING_ENABLED": "0",
  "WEBSITE_AUTH_ALLOWED_AUDIENCES": "<my_client_app_id_in_app_registrations>",
  "WEBSITE_HTTPLOGGING_RETENTION_DAYS": "15",
  "REMOTEDEBUGGINGVERSION": "16.0.28729.10",
  "SCM_USE_LIBGIT2SHARP_REPOSITORY": "0",
  "WEBSITE_AUTH_CLIENT_ID": "<my_target_app_id_in_app_registrations>",
  "WEBSITE_AUTH_DEFAULT_PROVIDER": "AzureActiveDirectory"
}

Any hints on this issue or tips on what is misconfigured?


EDIT: Adding App registration manifests

Target App Manifest

{
    "id": "<target_app_registration_id>",
    "acceptMappedClaims": null,
    "accessTokenAcceptedVersion": "2",
    "addIns": [],
    "allowPublicClient": false,
    "appId": "<target_app_id>",
    "appRoles": [
        {
            "allowedMemberTypes": [
                "Application"
            ],
            "description": "Accesses the TodoListService-Cert as an application.",
            "displayName": "access_as_application",
            "id": "<app_role_unique_ID>",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "value": "access_as_application"
        }
    ],
    "oauth2AllowUrlPathMatching": false,
    "createdDateTime": "2020-06-02T13:23:22Z",
    "groupMembershipClaims": null,
    "identifierUris": [
        "api://<target_app_id>"
    ],
    "informationalUrls": {
        "termsOfService": null,
        "support": null,
        "privacy": null,
        "marketing": null
    },
    "keyCredentials": [],
    "knownClientApplications": [],
    "logoUrl": null,
    "logoutUrl": null,
    "name": "Rule Engine",
    "oauth2AllowIdTokenImplicitFlow": true,
    "oauth2AllowImplicitFlow": true,
    "oauth2Permissions": [
        {
            "adminConsentDescription": "Test service",
            "adminConsentDisplayName": "Test service",
            "id": "<exposed_api_id_1>",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "type": "User",
            "userConsentDescription": null,
            "userConsentDisplayName": null,
            "value": "service"
        },
        {
            "adminConsentDescription": "Test",
            "adminConsentDisplayName": "Test",
            "id": "<exposed_api_id_2>",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "type": "User",
            "userConsentDescription": null,
            "userConsentDisplayName": null,
            "value": "Test.Test"
        }
    ],
    "oauth2RequirePostResponse": false,
    "optionalClaims": null,
    "orgRestrictions": [],
    "parentalControlSettings": {
        "countriesBlockedForMinors": [],
        "legalAgeGroupRule": "Allow"
    },
    "passwordCredentials": [],
    "preAuthorizedApplications": [
        {
            "appId": "<client_app_id>",
            "permissionIds": [
                "<exposed_api_id_2>",
                "<exposed_api_id_1>"
            ]
        }
    ],
    "publisherDomain": "<tenant_name>",
    "replyUrlsWithType": [
        {
            "url": "<app_url>",
            "type": "Web"
        }
    ],
    "requiredResourceAccess": [
        {
            // Default accesses and also the User.AccessAll mentioned for the Graph API as in the docs
            "resourceAppId": "00000003-0000-0000-c000-000000000000",
            "resourceAccess": [
                {
                    "id": "0e263e50-5827-48a4-b97c-d940288653c7",
                    "type": "Scope"
                },
                {
                    "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
                    "type": "Scope"
                }
            ]
        }
    ],
    "samlMetadataUrl": null,
    "signInUrl": null,
    "signInAudience": "AzureADMyOrg",
    "tags": [
        "webApi",
        "notApiConsumer"
    ],
    "tokenEncryptionKeyId": null,
    "verifiedPublisher": {
        "displayName": null,
        "verifiedPublisherId": null,
        "addedDateTime": null
    }
}

Client App Manifest:

{
    "id": "<client_app_registration_id>",
    "acceptMappedClaims": null,
    "accessTokenAcceptedVersion": "2",
    "addIns": [],
    "allowPublicClient": null,
    "appId": "<client_app_id>",
    "appRoles": [],
    "oauth2AllowUrlPathMatching": false,
    "createdDateTime": "2020-06-02T12:02:17Z",
    "groupMembershipClaims": null,
    "identifierUris": [],
    "informationalUrls": {
        "termsOfService": null,
        "support": null,
        "privacy": null,
        "marketing": null
    },
    "keyCredentials": [],
    "knownClientApplications": [],
    "logoUrl": null,
    "logoutUrl": null,
    "name": "daemon_rest_client",
    "oauth2AllowIdTokenImplicitFlow": false,
    "oauth2AllowImplicitFlow": false,
    "oauth2Permissions": [],
    "oauth2RequirePostResponse": false,
    "optionalClaims": {
        "idToken": [],
        "accessToken": [],
        "saml2Token": []
    },
    "orgRestrictions": [],
    "parentalControlSettings": {
        "countriesBlockedForMinors": [],
        "legalAgeGroupRule": "Allow"
    },
    "passwordCredentials": [
        {
            "customKeyIdentifier": null,
            "endDate": "2299-12-30T23:00:00Z",
            "keyId": "<client_secret_id>",
            "startDate": "2020-06-02T12:06:51.305Z",
            "value": null,
            "createdOn": "2020-06-02T12:06:54.1593511Z",
            "hint": "0CA",
            "displayName": "test_rest_call"
        }
    ],
    "preAuthorizedApplications": [],
    "publisherDomain": "<tenant_name>",
    "replyUrlsWithType": [],
    "requiredResourceAccess": [
        {
            "resourceAppId": "<target_app_id>",
            "resourceAccess": [
                {
                    "id": "<exposed_api_id_2>",
                    "type": "Scope"
                },
                {
                    "id": "<exposed_api_id_2>",
                    "type": "Scope"
                },
                {
                    "id": "<app_role_unique_ID>",
                    "type": "Role"
                }
            ]
        },
        {
            // Default accesses and also the User.AccessAll mentioned for the Graph API as in the docs
            "resourceAppId": "00000003-0000-0000-c000-000000000000",
            "resourceAccess": [
                {
                    "id": "0e263e50-5827-48a4-b97c-d940288653c7",
                    "type": "Scope"
                },
                {
                    "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
                    "type": "Scope"
                }
            ]
        }
    ],
    "samlMetadataUrl": null,
    "signInUrl": null,
    "signInAudience": "AzureADMyOrg",
    "tags": [
        "apiConsumer",
        "backgroundProcess"
    ],
    "tokenEncryptionKeyId": null,
    "verifiedPublisher": {
        "displayName": null,
        "verifiedPublisherId": null,
        "addedDateTime": null
    }
}

GUIDs of the resources omitted for compliance.

1 Answers

I was trying different scenarios to try to reproduce your issue, I was having alot of trouble, as I used the authentication in the web app to automatically create the app registration. then I was randomly changing variables to try to get it to fail. the only way I got it to fail was as rohit was on the right track i think, Accesstokenacceptedversion, when i set it to 2 it kept failing. try to set it to null,

Related