I'm setting up a KeyVault to remove secrets from my .NET Azure WebApp and pass CredScan and everything is hooked up correctly as far as I can tell.
The KeyVault exists in the same resource group as the app and has the required secrets. The App Service has explicit read-permissions set in the KeyVault's Access Policies. And all the correct parameters are used to create the API client in the code, following the documentation.
However when I use the standard API call to actually access a secret using the client, i.e.
SecretClient client = new SecretClient(keyVaultURI, new DefaultAzureCredential());
string secret = client.GetSecret(secretName).Value.Value;
I get the following error:
DefaultAzureCredential failed to retrieve a token from the included
credentials.\r\nEnvironmentCredential authentication unavailable.
Environment variables are not fully
configured.\r\nManagedIdentityCredential authentication unavailable,
no managed identity endpoint found.\r\nSharedTokenCacheCredential
authentication unavailable. Token acquisition failed for user . Ensure
that you have authenticated with a developer tool that supports Azure
single sign on.
I'm guessing there must be some required config step or setting that I am unaware of.
I summary the whole solution as below.
If you want to DefaultAzureCredential to access Azure key vault in Azure app service, you need to enable MSI and configure the right access policy for you MSI in Azure key vault. For more details, please refer to the document
The detailed steps are as below.
a. Enable system-assigned MSI
Scroll down to the Settings group in the left navigation.
Select Identity.
Within the System assigned tab, switch Status to On. Click Save.
b. Configure access policy
Search for your Key Vault in “Search Resources dialog box” in Azure
Portal.
Select "Overview", and click on Access policies
Click on "Add New", select "Secret Management" from the dropdown for
"Configure from template"
Click on "Select Principal", and in the search field enter the Object ID of you web app MSI you created earlier. Select the web app in the result list and click "Select".
Click on "OK" to add the new Access Policy, then click "Save" to save
the Access Policies
Related
When I am trying to run user flow manually from portal.azure.com by clicking 'Run user flow' at the bottom I can select the application and reply URL.
I have defined two reply URLs:
https://localhost:5001/signin-oidc
https://jwt.ms
I select the first reply URL and below that information the 'Run user flow endpoint' is generated automatically. When I copy this endpoint and try to call from my blazor app it is working correctly. I can log in and change my profile info. Then, I can click continue to reply to my blazor app.
After clicking I want to get back to my app but I have an error:
Error.
An error occurred while processing your request.
Request ID:
00-f13479803a4cdeb7d3e203f0910e3688-a0619e9d48caf391-00
Details OpenIdConnectAuthenticationHandler: message.State is null or
empty.
When I set the reply URL to jwt.ms everything works fine.
How to call Edit Profile User Flow from the blazor app properly?
There are below few workaround may help to achieve the above requirement
Kindly check the signuporsignin.xml b2c userflow policy for correct tenant id and public policy uri in that policy file specifically check the technical profile id and inherent output claims regarding post successful authentication with Azure ad b2c .
Since after successful authentication to the blazor app you are able to login and able to change the profile info in the signinsignup user flow page successfully ,But when returning to the blazor client application you are encountering an error that displays the State parameter is null or empty, which inherently implies that the token access authentication is not passed on or the token has is broken/missing or misinterpreted during the changes of pages.
Thus i would suggest you to please check the program.cs file in the blazor client application code whether it includes the below code snippets or not.
builder.Services.AddMsalAuthentication(options => { builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication); options.ProviderOptions.DefaultAccessTokenScopes.Add("api://https://domain.onmicrosoft.com/cxxxx-1xx-4xxxe-aad0-4xxxxx/API.Access"); });
The above code snippet states that the blazor client application has exposed his api to the blazor server application as a provider.
Further also please check the authentication.razor file for the parameter to be passed on public string
Once the above has been checked and found correct then please ensure that the appsettings.json file on both the client & server applications has the correct respective client Id and the policy name mentioned. Also check the Azure ADb2c app registration for the details in blazor web assembly application.
For more information please refer the below links:-
Secure an ASP.NET Core Blazor WebAssembly hosted app with Azure Active Directory | MICROSOFT DOCUMENTATION
With my outlook.com account I logged in to portal.azure.com and I created a new application. Microsoft has provided a sample app (daemon_console) for quick experiments (in QuickStart guide) and I followed steps provided for the sample app, the app automatically takes the application id and client secret you generated and updates the configuration JSON file (appsettings.json) with this info. I downloaded the code after these steps but when I run the sample app it throws the error "Authorization_IdentityNotFound".
Looks like it is able to fetch the token but following code is throwing the error:
var httpClient = new HttpClient();
var apiCaller = new ProtectedApiCallHelper(httpClient);
await apiCaller.CallWebApiAndProcessResultASync($"{config.ApiUrl}v1.0/users", result.AccessToken, Display);
Microsofts page has step to get Admin consent in two ways:
If you are a global administrator, go to API Permissions page select Grant admin consent for Enter_the_Tenant_Name_Here
Standard user
If you're a standard user of your tenant, then you need to ask a global administrator to grant admin consent for your application. To do this, give the following URL to your administrator:
https://login.microsoftonline.com/common/adminconsent?client_id=my apps client id
I have tried both these options. With the first option, I am able to grant the required permissions. But the issue still exists.
With the second option when I go to the suggested URL it fails with error:
"AADSTS500113: No reply address is registered for the application."
I think this should have been a straightforward process but somehow the app is not able to execute and fails with errors:
"code": "Authorization_IdentityNotFound",
"message": "The identity of the calling application could not be established.",
Please let me know if anyone has tried these steps and has managed to resolve this issue.
Note that I can run "https://graph.microsoft.com/v1.0/users" from graph explorer with my outlook.com account and it works perfectly fine.
I tested it, and at first I was running into the same issue,
its because of the common in the appsettings.json
replace the "Tenant": "common"
with "Tenant": "your Tenant ID",
You can get the tenant ID from the overview page of your app registration Directory (tenant) ID. After you do that, make sure you right click the project and click rebuild. because if I just do a normal run it had it cached and did not update it from common.
I have a custom UWP application which I have registered in portal.azure.com. The app has been configured to support all account types ("Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)").
In my application I create a IPublicClientApplication like so:
PublicClientApp = PublicClientApplicationBuilder.Create(appId)
.WithAuthority(AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount)
.WithLogging((level, message, containsPii) =>
{
ConfigurationHandler.Log.Info($"MSAL: {level} {message} ");
}, LogLevel.Warning, enablePiiLogging: false, enableDefaultPlatformLogging: true)
.WithUseCorporateNetwork(true)
.Build();
And later on I'm trying to acquire an authentication token like so:
authResult = await PublicClientApp.AcquireTokenInteractive(Scopes)
.ExecuteAsync()
.ConfigureAwait(false);
This will open the sign in popup window where user enters their email address and password. The authentication works without issues when I'm using a personal (xyz#outlook.com) account but it doesn't work with work accounts. The window is trying to redirect to the organization sign in page after entering the work email and clicking next. The redirect process begins but always ends up to following error:
"We can't connect to the service you need right now. Check your network connection or try this again later"
I have tried to add WithRedirectUri with value "urn:ietf:wg:oauth:2.0:oob" to the PublicClientApplication creation but it didn't help. That's the only redirect URI I have configured in Azure Portal.
Is there some other setting which I'm not aware of? How can I get rid of this error and get the work accounts working as well?
EDIT: I forgot to mention it's a desktop application.
I can not reproduce your issue on my side. My steps seem the same as yours, anyway, here is the screenshot for your reference. Also, here is an complete guide.
By the way, if you want to integrate authentication on federated domains, you need to enale additional capabilities.
1.Open Package.appxmanifest.
2.Select Capabilities and enable the following settings:
Enterprise Authentication
Private Networks (Client & Server)
Shared User Certificates
This issue was resolved by adding a missing certificate to Trusted Root Certification Authorities in Windows certificate manager.
I am running Google Translate API in C#.
Running locally on my computer the next code works, but online on a server it throws the following error:
using Google.Cloud.Translation.V2;
TranslationClient client = TranslationClient.Create();
var response = client.TranslateText(sentence, targetLanguage, sourceLanguage: sourceLanguage);
"The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information."
Locally this runs just by installing Cloud SDK Installer which does all the settings, there is no need for authentication in code.
On the server, should I use instead OAuth 2.0 or Service account keys ?
Can someone assist me on how to solve this?
EDIT: Can someone confirm to me if it is necessary to have access to the local server to run commands in command line like here https://cloud.google.com/storage/docs/authentication ? This would be pretty ridiculous, instead of just writing code. For example Youtube API does not require local access.
Follow directions to get json file:
https://cloud.google.com/translate/docs/reference/libraries
Then run this code first:
System.Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "c:\mypath\myfile.json");
To generate a private key in JSON or PKCS12 format:
Open the list of credentials in the Google Cloud Platform Console.
OPEN THE LIST OF CREDENTIALS
Click Create credentials.
Select Service account key. A Create service account key window
opens.
Click the drop-down box below Service account, then click New service account.
Enter a name for the service account in Name.
Use the default Service account ID or generate a different one.
Select the Key type: JSON or P12.
Click Create. A Service account created
window is displayed and the private key for the Key type you
selected is downloaded automatically. If you selected a P12 key, the
private key's password ("notasecret") is displayed.
Click Close.
You can find more details here
https://cloud.google.com/storage/docs/authentication
Its all in the errormessage. You have two options
Run the Google Compute Engine on the machine you have your program running on and input your credentials there.
Use a service account and set the "GOOGLE_APPLICATION_CREDENTIALS" environment variable to reference your credentials file (which is a .json file that you can download from the google developer console.)
PS: Do not store your credentials file anywhere on the server where it may be accessed by someone else!
You must download API key from
https://console.developers.google.com/iam-admin/serviceaccounts
After that download .P12 file file to use it in your code
var certificate = new X509Certificate2(#"key3.p12", "notasecret", X509KeyStorageFlags.Exportable);
notasecret is default password
The easiest answer to my question , to avoid local settings on the server, is the third option of using the Translation API described below: using API keys.
This means just a simple POST to an endpoint that has the API key in the link.
https://cloud.google.com/docs/authentication/#getting_credentials_for_server-centric_flow
https://cloud.google.com/docs/authentication/api-keys
I am just starting out with the c# Google.Apis.Gmail.V1 classes and using a service account to read a mailbox.
My code works fine when I use the following snippet
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(ServiceAccountEmailAddress)
{
User = "abc#test.domain.com",
Scopes = new[] { "https://www.googleapis.com/auth/gmail.readonly" }
}.FromCertificate(certificate));
With that code I can call the following successfully
if (credential.RequestAccessTokenAsync(CancellationToken.None).Result)
{
}
But I need to modify the email messages so I changed the scope from
https://www.googleapis.com/auth/gmail.readonly
to
https://www.googleapis.com/auth/gmail.modify
I now get an exception when requesting the access token
{"Error:\"unauthorized_client\", Description:\"Unauthorized client or scope in request.\", Uri:\"\""}
I have checked the service account (*.iam.gserviceaccount.com) in the Google Developers Console and I have tried all options for permissions including OWNER which should give me Full access to all resources but no joy.
I think I am just missing a simple step but I am unsure of where to look next.
TL;DR
I would read through this, but here is the short version. I know this is an older post, but hopefully it finds you!
If you have not updated/white-listed the service account's privileges/scopes in the Google Admin Console you will need to do that, make sure the domain has API access enabled, make sure the service account is setup properly, when creating the "certificate" object be aware its parameters so that it is being instantiated correctly, check the permissions on the account being impersonated and finally make sure you've made an appropriate Google Apps service account key (could have easily made an inappropriate key type.)
White-listing Google APIs in the Admin Console
This gives the Google Apps service account the abilityto use whatever scopes you provide in your Google Apps domain.
Login to the Google Apps Admin Console by using the following link.
https://admin.google.com/
The Google Apps user account must have sufficient privileges to modify domain related settings. It does not have to be the account used to create the Google Apps project in the developer console. If the account does not have privilege you will be directed to a completely different screen with no options to click on varying domain controlling web apps like "Security", "Roles", "Support", "Groups" and etc. Instead you'll dumped onto a page that shows things like "Gmail", "Drive", "Docs" and etc. that is typical user apps. The current link it drops you at is https://apps.google.com/user/hub
Click “Security.”
Click “Show more” option at the bottom of the security options list.
Click “Advanced Settings” to get the more options.
Select the “Manage API client access” link.
Now certain API scopes must be white-listed for the desired service account. In the “Client Name” text box provide the service account’s client ID. The client ID is obtained in the developer console. In the “One or more API scopes” add the desired scopes; comma delimited.
Note, if there are existing scopes they will be removed so be sure to re-add any that will be needed.
Enable Domain Wide API Access
Login to the Google Apps Admin Console by using the following link.
https://admin.google.com/
Go to the “Security” page.
Under “API reference” section
Make sure that “Enable API access” is enabled.
Creating an Appropriate Google Apps Service Account Key (Probably this)
Go to the Google Developer Console. Login as the Google Apps user that created the Google Apps project/service account. https://console.developers.google.com/
Navigate to the particular project with which you created the service account.
Click the "Service Account" button on the left of the project's page to bring up a page with all of the project's service accounts.
Click the vertical ellipse widget all the way to the right of the desired service account's row. Select “Create Key.”
Select .p12 key as it looks like this is what you're trying to use. Click "Create." Be sure to protect this key.
I have found that if the key is not created this way then it leaves open the possiblity for making either an API key or an OAuth 2.0 client/user key. These are the wrong types of keys to use in this case you would need to have created a service account key. The way outlined above forces you to create a service account key.
Modifying the Existing Google Apps Service Account's Settings
I'm not going over how to setup the actual service account, one thing you may need in your case is to make sure that the service account has domain wide delegation enabled. This is toggled in the Google Developer Console. Should be pretty easy to find.
Code
You do not provide your entire code base for creating the token, so just want to add a few things you might be doing improperly.
Make sure when you create the certificate that the secret you provide is the default "notasecret" string. This secret is currently the default value provided by all keys distributed by Google and is immutable during key creation. I had a link to prove this, but have since lost it.
X509Certificate2 certificate = new X509Certificate2(certificateFilePath, "notasecret", X509KeyStorageFlags.Exportable);
Just trying to advocate proper coding. While I have found some bugs in the past with Google's constant values that required additional string manipulation (adding additional slashes.) You should really be using the string constants that they provide in place of literals. I only say to use these because it provides a layer of abstraction, who is to say Google will never change the literal; unlikely.
In your case the new scope is:
GmailService.Scope.GmailModify
While the old scope was:
GmailService.Scope.GmailReadonly
Otherwise, everything code wise looks good to me.
Another thing to try would be to make sure that the actual Google Apps user account being impersonated by the service account has sufficient privileges. I would suspect a different error if this were the case, would be getting a 403 in the response instead. Anyway, in your case this is the "abc#test.domain.com" account. Once again you would go to the Google Admin Console, check its roles make sure it has sufficient roles checked for whatever it is you're trying to do. I don't know what specifically you'll need in this case, best bet would be to give it the same permissions as the "Super Admin" role then remove permissions as you go to see what it might actually need. Otherwise, if possible just give it "Super Admin."
If I was a gambler I would put my money on an inappropriately created service account key. I just recently ran into this and it was the only thing that produced the same exact error you're receiving. Other things would get me the same "Description" value in the response token, but not the same "Error" value. I'm not really even sure how the culprit key was made, because I didn't make it. I just know the fix was to recreate a new key with the steps above and that fixed the issue.