How to get Application ID URI formats working - azure-web-app-service

I'm having trouble getting any of the Application ID URIs working. I have a Blazor WebAssembly Hosted application, written in ASP.NET Core 5.0. Using the api://<appId> format is fine, but this doesn't play well with Terraform. I can get my client talking to the server using api://<appId>, so I know the code is working fine. When I swap the Application ID URI to use any of the other formats, such as https://<verifiedCustomDomain>/<string> or api://<tenantId>/<string>, I get a 401 error. I'm using a verified Azure AD domain.
I can see that <string> means, "The string value for the host or the api path segment.", but I'm not sure what that means. I've been testing with <string> set to the name of my App Service and also the name of the App Registration. I've also tried changing the App Registration from Single Tenant to Multitenant (just in case that makes a difference).
Any advice would be much appreciated.

For anyone stumbling upon this, the solution is to make sure to include the Audience within the AzureAD block in appsettings.json.
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "7867-7866-7687-8678-8678678676",
"ClientId": "5456-6567-5676-5675-5675757565",
"Audience": "https://myapp.example.com"
}
The Application ID URI (within the App Registration - Expose an API section) should be exactly the same as the Audience value.

Related

Microsoft.IdentityModel does not support a B2C issuer with 'tfp' in the URI

I am trying to run the WebApp B2C sample:
https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/1-WebApp-OIDC/1-5-B2C
When I try to login, I get the following error:
IDX40002: Microsoft.IdentityModel does not support a B2C issuer with 'tfp' in the URI. See https://aka.ms/ms-id-web/b2c-issuer for details.
If I edit the Instance to https://myHost.b2clogin.com I get:
AADSTS50011: The redirect URI 'https://myHost.b2clogin.com/1c2009bb-7e35-4a0e-9f22-xxxxxxxxx/oauth2/authresp' specified in the request does not match the redirect URIs configured for the application 'c24b0337-0bd9-45ee-8376-xxxxxxxxx'. Make sure the redirect URI sent in the request matches one added to your application in the Azure portal. Navigate to https://aka.ms/redirectUriMismatchError to learn more about how to fix this.
Edit:
These are my redirects:
I tried to reproduce the same in my environment and got the below results:
I deployed custom policy starter pack via IEF Setup App by entering my Azure B2C tenant name like below:
When I checked that in Portal, custom policies are created successfully like below:
Now I registered one Azure AD B2C app named webapp1 as below:
I added redirect Uri to the above application like below: https://localhost:44316/signin-oidc
Now, I followed the same link that you mentioned and deployed one sample B2C web application by modifying appsettings.json file like below:
"AzureAdB2C": {
"Instance": "https://sridevib2c.b2clogin.com",
"ClientId": "9986e76d-bxx7-4x6x-bxx7-3d8xxxxx9a45",
"Domain": "sridevib2c.onmicrosoft.com",
"SignedOutCallbackPath": "/signout/B2C_1A_SIGNUP_SIGNIN",
"SignUpSignInPolicyId": "B2C_1A_SIGNUP_SIGNIN",
"ResetPasswordPolicyId": "B2C_1A_PASSWORDRESET",
"EditProfilePolicyId": "B2C_1A_PROFILEEDIT" // Optional profile editing policy
//"CallbackPath": "/signin/B2C_1A_SIGNUP_SIGNIN" // defaults to /signin-oidc
},
JSON file:
When I ran the above web application, it took me to below web page:
After selecting Sign Up/In, I got the login screen like below:
When I entered my credentials, I logged in to the application successfully like below:
When I clicked on Sign Out, it showed me below screen by signing me out:
After a long research I found this article/sample, where the Microsoft.Identity.UI framework is replaced with the Microsoft.AspNetCore.Authentication.AzureADB2C.UI.
However, with the https://myDomain.b2clogin.com url I still get the same error, using the custom domain it works, that's enough for me.

Does the resource URL in webApplicationInfo need to contain the Microsoft Teams App ID?

My teams app uses a bot and is configured for SSO, the webApplicationInfo property in my manifest looks something like this following this documentation:
"webApplicationInfo": {
"id": "{Azure AD AppId}",
"resource": "api://{Subdomain}.example.com/botid-{Azure AD AppId}"
}
The resource URL is ultimately used as the Application ID URI and Redirect URI in my bot's app registration and then is also used as the Token Exchange URL in my bot's connection.
The current set up works well, but I want to automate the creation of the bot in Azure using Terraform or Pulumi. However, because the resource URL in webApplicationInfo is structured to include the App ID, the creation process for the app registration has a self-referential problem: the Application ID URI and Redirect URI can't be configured during creation because the App ID isn't available until after the app registration is created.
What purpose does including the App ID in the resource URL serve? Is it essential for me to include? Will I run into issues down the road? Excluding it from the URL would solve these self-referential problems.
First off, you have an error in your code sample: it's not botid-{Azure AD AppId}, but rather just {Azure AD AppId}. That means it's the same AppId as the line above. A complete example would look something like this (with a sample app id):
"webApplicationInfo": {
"id": "3bbd1472-40d9-4852-bee6-33e16739a7b7",
"resource": "api://myApi.example.com/3bbd1472-40d9-4852-bee6-33e16739a7b7"
}
That aside, you definitely need to have this id, but the sequence for Terraform /Pullumi should be ok. It should be:
Create Azure App, get it's Id
Create Bot (you can specify the Azure App Id you created above, as being the App Id to use)
Create the Teams manifest using the Azure App Id

Problem calling Microsoft Graph from ASP.NET Grpc service

I have two applications -
public client application (.NET Core console app), in which user gets Microsoft identity access token
web API, which tries to call Microsoft Graph on-behalf-of user, using that access token
When I call Microsoft Graph from web API, I get a MicrosoftIdentityWebChallengeUserException, which inner exception states:
"The user or administrator has not consented to use the application with ID <...> named <...>. Send an interactive authorization request for this user and resource."
I've tried:
to pre-authorize client application in service application using Expose an API tab in Azure Portal
to add client application ID in knownClientApplications array in Manifest tab
to include the scopes, needed for Microsoft Graph (e.g. "User.Read"), in the access token, obtained by the user
but it seems that this does not work and I still get the same exception.
The question is - can I somehow avoid this exceptional situation by getting all needed permissions in a user access token, before calling the GRPC service, or if not, that how do I need to handle this exception to propagate it back to the user.
Full details here. Keep following the Next Steps.
Basically, you'll need to:
Include the Microsoft.Identity.Web and Microsoft.Identity.Web.MicrosoftGraph NuGet packages in your API project.
Set up a Client Secret or a Certificate in the Azure App Registration. Include that in your appsettings.json file:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "{YOUR-DOMAIN-NAME-FROM-APP-REGISTRATION}",
"TenantId": "{YOUR-TENANT-ID-FROM-APP-REGISTRATION}",
"ClientId": "{YOUR-CLIENT-ID-FROM-APP-REGISTRATION}",
"Scopes": "{YOUR-API-ACCESS-SCOPE-FROM-APP-REGISTRATION}",
"CallbackPath": "/signin-oidc",
"ClientSecret": "{YOUR-CLIENT-SECRET-FROM-APP-REGISTRATION}"
}
Include the following section in your appsettings.json file:
"Graph": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "User.Read"
}
Include the following code in your Project.cs file or Startup.cs file (depending on what version of .Net you're using):
Startup.cs:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration, Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(Configuration.GetSection("Graph"))
.AddInMemoryTokenCaches();
Project.cs:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(builder.Configuration.GetSection("Graph"))
.AddInMemoryTokenCaches();
From there, you just need to inject the GraphServiceClient into your controller or page constructor. The link above provides code for implementation in an ASP.NET API. I'm using this method in a Blazor Webassembly hosted app, so my implementation needs varied slightly from the instructions, but it's running/working as it should.

Azure AD Audience is Invalid due to "api://" being appended

I have two Azure Daemon apps. App A and App B.
App B works as expected. I call the /oauth2/v2.0/token to the the access token. Then I decode the token and extract the roles.
App A does not.. when i decode and validate the token it says "Invalid Audience".
When i use jwt.ms to look at the token, the difference is App A is putting api:// in the aud portion.. and App B is not.
For example..
App A: { "aud":"api://3srlk3j..."}
App B: { "aud":"323f4lk2..."}
What is causing one to add api:// for one and not the other?
The value of audience is also controlled by the accesstokenacceptedversion in the manifest file.
When you decode the token you can check if issuer has v1 or v2 endpoint
"iss": "https://login.microsoftonline.com/xxxxx/v2.0",
For example here I have v2 endpoint ,so accesstokenacceptedversion in manifest must be set to 2 which might be probably null or 1 by default.
"accessTokenAcceptedVersion": 2,
So please check the same for your web app A and set it accordingly .(Also check the same for web app B) and then try to generate token.
Also if above alone doesn’t solve the error,the problem might be the configuration data for the Web API. When we say the ClientId ,it is the value under the "expose an API" option where it says "Application ID URI
Depending on how you request the access token, the audience of the token might be either the client id or Application ID URI of the API.
Here under expose an API , it has App ID Uri as api://xxxxx, same must be set as client id in the application app settings.
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "myportal.onmicrosoft.com",
"TenantId": "mytenant-guid",
"ClientId": "api://xxxxx"
},
So please check this match in both the applications(A and B) with their respective app ID URIs in their app registrations.

Unable to get App Service CDN to work with authentication

I have an asp.net core web application hosted in azure as an app service. I've configured the application to use OpenId Connect with Azure AD as the authority. The authentication happens within my application (I am not configuring the app service itself to handle the authentication).
Everything works fine when I hit the app service directly (or even if I use a custom domain name).
I've enabled the CDN service within the app service. Once the initial propagation finished, I open a browser and navigate to the CDN address ([name].azureedge.net).
I get a redirect to Azure AD, but once I finish the authentication process, I get an error.
It looks like when the redirect to Azure AD came back from the CDN, the app service's URL was set as the return_url. So when Azure AD redirected me, I was no longer hitting the CDN. When the redirect to Azure AD happens, there's a cookie placed in my browser; I suspect my site is looking for that cookie, but the browser didn't send it because it was set by a different domain.
I've tried configuring the CallbackPath in the OpenIdConnectOptions to the full URL (schema, host, domain, etc), but when my application initializes, and error is thrown saying that the path must start with a '/' (presumably it's expecting a path from the root of the domain in the request).
Hopefully someone else has come across this problem and can tell me what I'm doing wrong.
Per request, here's my OIDC configuration:
var openIdOptions = new OpenIdConnectOptions
{
ClientId = adSettings.ClientId,
ClientSecret = adSettings.ClientSecret,
Authority = adSettings.Authority,
CallbackPath = adSettings.CallbackPath,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
Events = new OpenIdConnectEvents { OnTicketReceived = AddApplicationRolesToUserClaimsAsync, OnAuthorizationCodeReceived = RedeemCodeAsync }
};
foreach (var scope in adSettings.Scopes.Concat(settings.MicrosoftGraph.Scopes))
openIdOptions.Scope.Add(scope);
application.UseOpenIdConnectAuthentication(openIdOptions);
adSettings is a POCO that is hydrated from the following appsettings.json:
"AzureAd": {
"AADInstance": "https://login.microsoftonline.com/",
"ClientSecret": "REDACTED",
"CallbackPath": "/signin-oidc",
"ClientId": "REDACTED",
"TenantId": "REDACTED",
"Scopes": [
"openid",
"profile",
"offline_access"
]
}
adSettings.Authority is defined in the POCO as:
public string Authority => $"{AADInstance}{TenantId}/v2.0";
After digging around a bit, I found the answer.
The OpenIdConnectOptions.Events property allows you to hook into various events that happen throughout the lifecycle of authentication. One callback is called OnRedirectToIdentityProvider. It provides a RedirectContext. On that object you can read/write to a property called ProtocolMessage.RedirectUri. That property allows you to specify a full URL which is used as the return_url when the user is forwarded to AAD.
It's worth noting that I'm using the Microsoft.AspNetCore.Authorization.OpenIdConnect packge from Nuget. There are other packages available that provide similar functionality that do allow you to set a full URL in the options object.

Resources