We have a .net core application which uses Azure AD for authentication (MSAL/ v2.0). We want a linux application to access an API from the first application. The second application has no user context and will interact exactly as curl script would.
From reading the documentation I believe that I should register a second application with azure ad. I can get so far as a JWT token that has the target application as audience but I cannot get access to the api. We've been able to access the (real) api from scripts with an access token captured from a logged in user.
I created a Test environment to find the solution.
Created a .net core project authenticated by azure ad. It is running locally from my workstation not deployed to azure. Azure Authentication is working for interactive users.
Registered a second application and created a secret for it.
The first application is configured with both id and access tokens for implicit grant, it is not set as a public client.
I defined an approle 'access_as_application' in the manifest.
Under Expose an API I Created a scope 'api' and added the other application as an authorized client application.
Under API permissions I added a permisison, chose application permission and checked the approle I created earlier.
I can run a curl script and retrieve a bearer token that when decoded shows an audience matching my application. When I use that token in a curl script it is redirected to sign in.
Manifest:
{
"id": "33b*******************************",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": null,
"appId": "3d8*******************************",
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"description": "Access webapp as an application.",
"displayName": "access_as_application",
"id": "ff5ea9b2*******************************",",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "access_as_application"
}
],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2019-10-29T16:49:37Z",
"groupMembershipClaims": null,
"identifierUris": [
"api://3d8*******************************"
],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": "https://localhost:44321/signout-callback-oidc",
"name": "WebApp",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [
{
"adminConsentDescription": "consent for api",
"adminConsentDisplayName": "consent for api",
"id": "a4b2*******************************",",
"isEnabled": true,
"lang": null,
"origin": "Application",
"type": "Admin",
"userConsentDescription": null,
"userConsentDisplayName": null,
"value": "api"
}
],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2299-12-31T05:00:00Z",
"keyId": "e03c4*******************************",",
"startDate": "2019-10-31T20:05:42.56Z",
"value": null,
"createdOn": "2019-10-31T20:05:42.7555795Z",
"hint": "00_",
"displayName": "webappsecret"
}
],
"preAuthorizedApplications": [
{
"appId": "a4b*******************************",
"permissionIds": [
"23b*******************************"
]
},
{
"appId": "3d8*******************************",
"permissionIds": [
"23b*******************************"
]
}
],
"publisherDomain": "brainbuzgmail.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "https://localhost:44321/signin-oidc",
"type": "Web"
},
{
"url": "https://localhost:44321/",
"type": "Web"
}
],
"requiredResourceAccess": [
{
"resourceAppId": "3d8*******************************",
"resourceAccess": [
{
"id": "23b*******************************",
"type": "Scope"
},
{
"id": "ff5ea*******************************",",
"type": "Role"
}
]
},
{
"resourceAppId": "a4b*******************************",
"resourceAccess": [
{
"id": "a37a*******************************",",
"type": "Scope"
},
{
"id": "ccf78*******************************",",
"type": "Role"
}
]
},
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "e1fe*******************************",",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADMyOrg",
"tags": [],
"tokenEncryptionKeyId": null
}
Variables $ are set in environment. Token is captured from successful request and set as $TOKEN. -k insecure flag is used in curl due to local app using self signed certificate.
curl -X POST -d "grant_type=client_credentials&client_id=$CLIENTID&client_secret=$SECRET&resource=$SCOPE" https://login.microsoftonline.com/$TENANT/oauth2/token
curl -k 'https://localhost:44321/api/' \
-H 'Accept: application/json' \
-H "Authorization: Bearer $TOKEN" \
-H 'Sec-Fetch-Mode: cors' -H 'Content-Type: application/json' --compressed
Partial response redirecting to login page, it looks like the client is being asked to get an id token, even though it has a valid access token:
< HTTP/2 302
< location: https://login.microsoftonline.com/****/oauth2/v2.0/authorize?client_id=***&redirect_uri=https%3A%2F%2Flocalhost%3A44321%2Fsignin-oidc&response_type=id_token