Unauthorize Error to Azure App Configuration with Azure Functions - azure

I'm using App Configuration and Key Vault for store my config. Firstly, I used access key where was Endpoint, Id and Secret. That is working fine, but it isn't secure, because Id and Secret are sensitive data.
I tried to use value after 'Endpoint=' and in Startup.cs set DefaultAzureCredential(), but always when I launch my Azure Function, I get 401 (Unauthorize error). Why do I get this and how could I fix that?
ConfigureAppConfiguration in Startup
public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
{
base.ConfigureAppConfiguration(builder);
var configurationBuilder = builder.UseAppSettings().ConfigurationBuilder.AddEnvironmentVariables().Build();
var connectionString = configurationBuilder["appConfiguration"];
builder.ConfigurationBuilder.AddAzureAppConfiguration(options =>
{
var credentials = new DefaultAzureCredential();
options.Connect(new Uri(connectionString), credentials)
.Select(KeyFilter.Any, LabelFilter.Null)
.Select(KeyFilter.Any, builder.GetContext().EnvironmentName)
.ConfigureKeyVault(kv =>
{
kv.SetCredential(new DefaultAzureCredential());
});
});
}
appConfiguration from appsettings
"appConfiguration": "https://rta-dev-edu-app-config.azconfig.io"
Error
A host error has occurred during startup operation '9467e813-9979-44b9-8ecf-3d956fbaf72e'.
Azure.Data.AppConfiguration: Service request failed.
Status: 401 (Unauthorized)
WWW-Authenticate: HMAC-SHA256,Bearer error="invalid_token", error_description="The access token is from the wrong issuer. It must match the AD tenant associated with the subscription, to which the configuration store belongs. If you just transferred your subscription and see this error message, please try back later.
P.S. I already added my account to IAM for my App Configuration.

The access token is from the wrong issuer. It must match the AD tenant associated with the subscription, to which the configuration store belongs. If you just transferred your subscription and see this error message, please try back later.
As Mentioned in this MS Doc of Accessing the Key Vault from the Dot Net Core Application,
you have to check that your account should have the multiple tenants access and then Set the Credential types such as SharedTokenCacheTenantId, VisualStudioTenantId to the DefaultAzureCredentialOptionswhile using the DefaultAzureCrendential in the required tenant.
Your Azure Account should be logged in the Same tenant level as you're trying to access the app configuration resource from the same tenant.
Refer to the GitHub Issue #14867.

Related

Trying to use Managed Identity with Azure Service Bus

I've tried following this tutorial in order to authenticate my service bus against DefaultAzureCredentials, however, I get a 401.
I'm using the following code in the set-up:
services.AddAzureClients(x =>
{
x.AddServiceBusClientWithNamespace("myns.servicebus.windows.net")
.WithCredential(new Azure.Identity.DefaultAzureCredential());
});
I then call the SB client like this:
var sender = client.CreateSender("myqueue");
var message = new ServiceBusMessage(Encoding.UTF8.GetBytes("test"));
await sender.SendMessageAsync(message);
When I call SendMessageAsync I get a 401 error:
fail: Azure-Messaging-ServiceBus[82]
An exception occurred while creating send link for Identifier: myqueue-578624f3-f732-4a9b-2ab0-9adc01949a5a. Error Message:
'System.UnauthorizedAccessException: Put token failed. status-code:
401, status-description: InvalidIssuer: Token issuer is invalid.
TrackingId:cde3a89c-8108-48d1-8b8f-dacde18e176f,
SystemTracker:NoSystemTracker, Timestamp:2021-05-19T07:18:44.
Before I run this, I call az login. I have access to the the namespace to both send and receive. My guess is that I need to allocate some kind of permission between the service bus and ... something - but since I'm running this as a console app, I'm running with my own credentials. Clearly there's something about managed identity that I don't understand.
EDIT:
Following advice from #juunas, I tried the following:
services.AddHostedService<ConsoleHostedService>();
services.AddAzureClients(x =>
{
//var creds = new Azure.Identity.EnvironmentCredential(); // 1st - EnvironmentCredential authentication unavailable. Environment variables are not fully configured.'
//var creds = new Azure.Identity.ManagedIdentityCredential(); // 2nd - No Managed Identity endpoint found
//var creds = new Azure.Identity.SharedTokenCacheCredential(); // 3rd - 'SharedTokenCacheCredential authentication unavailable. No accounts were found in the cache.'
//var creds = new Azure.Identity.VisualStudioCodeCredential(); // 4th - 'Stored credentials not found. Need to authenticate user in VSCode Azure Account.'
//var creds = new Azure.Identity.AzureCliCredential(); // 5th
var creds = new Azure.Identity.DefaultAzureCredential();
x.AddServiceBusClientWithNamespace("myns.servicebus.windows.net")
.WithCredential(creds);
It says the "token issuer is invalid".
That means it got an access token, but it was issued by the wrong Azure AD tenant.
The Az CLI allows you to specify the Azure AD tenant id with the -t tenant-id-here argument on az login.
DefaultAzureCredential could also be using some other credential (it attempts multiple credentials like VisualStudioCredential before the AzureCliCredential).
You could instead try to use AzureCliCredential directly and see if it works.
That of course won't use Managed Identity so you'd need to use ChainedTokenCredential with the AZ CLI credential + ManagedIdentityCredential to support both.

Unable to get access token. 'AADSTS500011: The resource principal named 'xxx' was not found in the tenant -tenantid

I am trying to get the access token for the Azure function app. I have enabled managed identity for the function app(system assigned). but while fetching the token using the nuget Azure.Identity.
var tokenCredential = new DefaultAzureCredential();
var accessToken = await tokenCredential.GetTokenAsync(
new TokenRequestContext(scopes: new string[] { "https://xxx.azure-api.net/" + "/.default" }) { }
);
I am getting the error.
The resource principal named 'xxx.azure-api.net' was not found in
the tenant 123
but when run az cli to check the subscription details, the subscription indeed part of the tenant 123 only.
Here is what I have finally done.
I have registered an App in AD. and Exposed the API of that App.
I have assigned System Assigned Managed Identity to the Function.
In the local I am not able to request token because Azure CLI is not given consent.
After deploying the application in Function my Function app can request a token using its identity.
You need to register the application in azure ad and enable the access token. Once that is done the you need to provide RBAC access to your xxx.azurewebsites.net
Follow this article for the step by step documentation Microsoft Document Reference
Unfortunately, the error message is not really helpful. But adding a scope to the app registration solved the problem for me:
In Azure Portal navigate to App Registrations
Find your app, in the left side menu select Manage => Expose an API
Add a scope. I named mine api_access as this was where this error occurred.
In my case I then got an API URI (like api://client-id/scope_name) which I used in my Angular app. Error message was gone.
Also, make sure that in the Enterprise Application you have created, under Manage => Properties, "Assignment required" and "Visible to users" is turned on.

Retrieve Azure KeyVault secret using client secret

I'm experimenting with various Azure features and currently want to retrieve a secret from KeyVault.
Straight to the case:
I'm using this nuget package to interact with my azure resources.
I've developed a simple .NET Core console app and run it locally.
I have a KeyVault resource with one secret defined which is active and not expired.
I've registered an App in AAD so my locally shipped .NET Core console app has an identity within AAD.
Than I've created a "client secret" within this registered app in AAD to use it to authenticate myself as an app.
After that I've added access policy in my KeyVault resource to allow GET operation for secrets for this registered app:
Then I've developed a small piece of code which should retrieve the desired secret:
public class AzureAuthentication
{
public async Task<string> GetAdminPasswordFromKeyVault()
{
const string clientId = "--my-client-id--";
const string tenantId = "--my-tenant-id--";
const string clientSecret = "--my-client-secret--";
var credentials = new ClientSecretCredential(tenantId, clientId, clientSecret);
var client = new SecretClient(new Uri("https://mykeyvaultresource.vault.azure.net"), credentials);
var secret = await client.GetSecretAsync("admincreds");
return secret.Value.Value;
}
}
However when I'm trying to do this I'm getting an AccessDenied error:
Am I missing something painfully obvious here? Or there is some latency (>30 min for this moment) for which changes from Access policies screen in KeyVault resource are applied?
I test your code and Get permission, it works fine.
From your screenshot, it looks you didn't add the correct service principal related to the AD App to the Access policies.
If you add the service principal related to the AD App, it will appear as APPLICATION, not COMPOUND IDENTITY.
So when you add it, you could search for the client Id(i.e. application Id) or the name of your App Registration directly, make sure you add the correct one.
Make sure your AD App(service principal) has the correct permission in your keyvault -> Access policies

ASP.NET Core Web App using Work (Azure AD) Authentication works debugging locally, but not after publish to Azure

My ASP.NET Core web app works great when running and debugging locally, but fails to run once published to Azure.
I enabled Organizational Authentication and selected the appropriate domain upon publishing.
The appropriate reply URL was registered
After I publish to Azure I get this error:
An unhandled exception occurred while processing the request.
OpenIdConnectProtocolException: Message contains error: 'invalid_client', error_description: 'AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.
Trace ID: 640186d6-9a50-4fce-ae39-bbfc1caf2400
Correlation ID: 622758b2-ca52-4bb0-9a98-e14d5a45cf80
Timestamp: 2017-04-19 16:36:32Z', error_uri: 'error_uri is null'.
I'm assuming that it's because the Client Secret needs to be stored in Azure somewhere; however, the value in secrets.json did not work when I added it as an App Setting (invalid client secret error) as I saw someone was able to do on another post. Also not sure if putting the value of "Authentication:AzureAd:ClientSecret" in Azure AppSettings is a good idea anyway.
Not sure if this is useful to anyone or not. But i receive a similar error message.
OpenIdConnectProtocolException: Message contains error: 'invalid_client', error_description: 'error_description is null', error_uri: 'error_uri is null'.
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler+<RedeemAuthorizationCodeAsync>d__22.MoveNext()
The solution for me was to provide a secret in the token service
,new Client
{
ClientId = "Testclient",
ClientName = "client",
ClientSecrets =
{
new Secret("secret".Sha256())
},
//Hybrid is a mix between implicit and authorization flow
AllowedGrantTypes = GrantTypes.Hybrid,
And provide the secret in the client
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
//The name of the authentication configuration.. just incase we have multiple
AuthenticationScheme = "oidc",
//Represents where to store the identity information -> which points to the cookie middleware declared above
SignInScheme = "Cookies",
//where the token service reside -> system will configure itself by invoking the discovery endpoint for the token service
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ClientId = "Testclient",
ClientSecret = "secret",
//hybrid flow -grant type
ResponseType = "code id_token",
Hopefully this helps someone
Somehow I the Azure AD IDs needed for the proper Azure Active Directory App Registration were mixed up. There were 2 App Registration entries and the ClientID and TenentID's didn't match up with the local. So I synchronized the Client and Tenent IDs with one of the App Registration entries, and made sure the Client Secret was in App Settings, and it worked properly.
I verified these steps with this fine example Win's GitHub repository and they match now.

How to configure permissions for the Azure AD authentication v2.0

I have set up a new web app to be able to use the Oauth2 V2 authorization endpoint. I defined the app in https://apps.dev.microsoft.com/
If I want to obtain a new authorization token, following instructions in
https://blogs.msdn.microsoft.com/richard_dizeregas_blog/2015/09/04/working-with-the-converged-azure-ad-v2-app-model/
I get the following error on the login page:
Sorry, but we’re having trouble signing you in.
We received a bad request.
Additional technical information:
Correlation ID: eb9c2331-32bd-45a9-90d1-e9105f0bfa87
Timestamp: 2016-05-22 18:10:48Z
AADSTS70011: The provided value for the input parameter 'scope' is not valid. The scope https://graph.microsoft.com/Calendar.Read is not valid.
The scope is taken from an example in :
https://github.com/Azure/azure-content/blob/master/articles/active-directory/active-directory-v2-scopes.md
So I imagine it is a valid scope.
In v1 of the OAuth2 protocol, it was necessary to configure access to APIs in the Azure AD of my tenant, prior to using them. So I attempted to do so for the new application.
Attempting to do so, the Azure application management reports an error:
{
"message":"This request has a value that is not valid.",
"ErrorMessage":"This request has a value that is not valid.",
"httpStatusCode":"InternalServerError","operationTrackingId":null,"stackTrace":null,"Padding":null
}
What is missing to be able to use the new authorization endpoint ?
The documentation contains a typo if states calendar.read. It must be calendars.read:
private static string[] scopes = {
"https://graph.microsoft.com/calendars.readwrite"};
Uri authUri = await authContext.GetAuthorizationRequestUrlAsync(scopes, additionalScopes, clientId, redirectUri, UserIdentifier.AnyUser, null);

Resources