Exception Error while reading from Azure Key Vault - azure

We faced the below exception while trying to read a secret from Azure Key Vault from Service fabric application.
The application uses Client Certificate to authenticate with AAD and access the KeyVault to fetch the secret.
This issue is occurring intermittently.
Is there a way we could identify the root cause so that the same error can be prevented from further occurrences.
Message: AADSTS70002: Error validating credentials. AADSTS50012: Client assertion is not within its valid time range.
Trace ID: 333ee9c1-c74f-432d-824a-000f38a0e400
Correlation ID: 35b5cadf-c538-4f75-b1fb-56c4743088f4
Timestamp: 2018-10-24 06:23:30Z
......

Client assertion is not within its valid time range.
According to your error message and your issue occurs intermittently, I think it may be your token's region time cause the problem. Region time may have some time interval with your token valid time.
So, I suggest that you could use DateTime.UtcNow as standard to set your token start time and end time. Here is a code sample you could refer to.
private static async Task<string> GetClientAssertiotokenAsync(string tenantId,string clientId)
{
X509Certificate2 cert = new X509Certificate2(#"D:\Joey\Documents\joey.pfx", "password", X509KeyStorageFlags.MachineKeySet);
var now = DateTime.UtcNow;
var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Audience = $"https://login.microsoftonline.com/{tenantId}/oauth2/token",
Issuer = clientId,
NotBefore = now.AddHours(1),
Expires = now.AddHours(3),
Subject = new ClaimsIdentity(new[] {
new Claim("sub",clientId)}),
SigningCredentials = new X509SigningCredentials(cert)
};
SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);
string tokenString = tokenHandler.WriteToken(token);
}
For more details, you could refer to this article.

Related

Microsoft.IdentityModel.LoggingExtensions.IdentityLoggerAdapter Error Logs in AzureAD Auth Implementation

We have integrated AzureAD for our API Authorization and API Auth is working fine but seeing error logs for Microsoft.IdentityModel.LoggingExtensions.IdentityLoggerAdapter with below messages,
IDX40003: Neither tid nor tenantId claim is present in the token obtained from Microsoft identity platform.
IDX10516: Signature validation failed. Unable to match key: kid: '*'. Number of keys in TokenValidationParameters: '16'. Number of keys in Configuration: '0'. Exceptions caught: '[PII of type 'System.Text.StringBuilder' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'. token: '[PII of type 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'. Valid Lifetime: 'False'. Valid Issuer: 'False'**
Our APIs are being consumed by UI APP as well as via Swagger/Postman.
What should be root cause to it?
The error IDX10516: Signature validation failed. Unable to match key: kid occurs when the Kid in your decoded token which validates token signature is not valid.
So one needs to load keys from the openid provider.
code:
var openidConfiguration = new ConfigurationManager<OpenIdConnectConfiguration>(
$"https://login.microsoftonline.com/{tenantid}/v2.0/.well-known/openid-configuration",
new OpenIdConnectConfigurationRetriever(),
new HttpDocumentRetriever());
var config = await openidConfiguration.GetConfigurationAsync();
var parameteres = new TokenValidationParameters()
{
RequireAudience = true,
RequireExpirationTime = true,
ValidateAudience = true,
ValidateIssuer = true,
ValidateLifetime = true,
ValidAudiences = new[] { "<my client id or appId uri or resource identitifer>" },
ValidIssuers = new[] { $"https://sts.windows.net/{tenantid}/" },
IssuerSigningKeys = config.SigningKeys
};
AppId Uri , you can check from the portal : api://
Add the following to check for more clear descriptive exception in ConfigureServices method in Startup.cs :IdentityModelEventSource.ShowPII = true
Example:
public void ConfigureServices(IServiceCollection services)
{
...
IdentityModelEventSource.ShowPII = true;
...
}
Reference : Azure AD - Why can't I validate JWT token issued by Azure AD for my Web API? Getting "IDX10516: Signature validation failed" error - Stack Overflow

How can I create an Azure Auth Token in a blobTrigger Azure Function?

I am trying to create a new Storage Account resource from an Azure Function. I am trying to use a StorageManagementClient, and need to pass in a ServiceClientCredential.
My code feels too simple... it compiles, but I feel like I must be missing some params. I am passing in a subscriptionId and a tenantId of an account in my subscription.
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/", tenantId);
ServiceClientCredentials credentials = new TokenCredentials(accessToken);
StorageManagementClient StorageManagement = new StorageManagementClient(credentials) { SubscriptionId = subscriptionId };
When it runs, I get the following error:
2021-02-12T03:32:26.407 [Error] Executed 'BlobTrigger1' (Failed, Id=9c293b8d-591e-420e-b376-dc9ac45097cc, Duration=343ms)Parameters: Connection String: [No connection string specified], Resource: https://management.azure.com/, Authority: https://login.microsoftonline.com/cd256644-73f5-4da4-af5d-4a977f7a6a5d. Exception Message: Tried the following 3 methods to get an access token, but none of them worked.Parameters: Connection String: [No connection string specified], Resource: https://management.azure.com/, Authority: https://login.microsoftonline.com/cd256644-73f5-4da4-af5d-4a977f7a6a5d. Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. An attempt was made to access a socket in a way forbidden by its access permissions.Parameters: Connection String: [No connection string specified], Resource: https://management.azure.com/, Authority: https://login.microsoftonline.com/cd256644-73f5-4da4-af5d-4a977f7a6a5d. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Visual Studio token provider file not found at "D:\local\LocalAppData\.IdentityService\AzureServiceAuth\tokenprovider.json"Parameters: Connection String: [No connection string specified], Resource: https://management.azure.com/, Authority: https://login.microsoftonline.com/cd256644-73f5-4da4-af5d-4a977f7a6a5d. Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. 'az' is not recognized as an internal or external command,operable program or batch file.
Your code is correct. I have found this issues is similar to yours. You can try this:
Hi friends, I have little ability to write fancy workaround code (my
head is not there), but by what you said above, I harkened back to
some old advice of: In the tool bar at the top of your VS 2017 program
go to: Tools, Options, Azure Service Authentication, Account
Selection, click the drop arrow on the right of the Microsoft banner
with your account name on it, click your account pop-up
again...hard(really insist on it), and that worked. I really feel like
a "just fix it" here might be just fine for a lot of folks. Don't get
me wrong, you girls(guys) know it better. Boy did I just want it to
work (phew!) Thanks :)
If that can't solve your problem, you can try this code:
public static async Task Main(string[] args)
{
string accessToken = await GetAuthorizationHeader();
ServiceClientCredentials credentials = new TokenCredentials(accessToken);
StorageManagementClient StorageManagement = new StorageManagementClient(credentials) { SubscriptionId = subscriptionId };
}
public static async Task<string> GetAuthorizationHeader()
{
ClientCredential cc = new ClientCredential(applicationId, password);
var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
var result = await context.AcquireTokenAsync("https://management.azure.com/", cc);
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
After following instructions on creating an Application Resgistration in Azure AD, this is the code I ended up getting to work:
var azureAuthConnectionString = $"RunAs=App;AppId={appId};TenantId={tenantId};AppKey={appKey}";
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(azureAuthConnectionString);
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/");
ServiceClientCredentials credentials = new TokenCredentials(accessToken);
StorageManagementClient StorageManagement = new StorageManagementClient(credentials) { SubscriptionId = subscriptionId };

Authenticate to multiple Azure services using Service Principle (.net Core)

I need to get access to Key Vault and Service Bus from code, using a Service Principle for authentication.
I can use the following code to access Service Bus, which works as expected - when I enable to Service Principle in the Access Policies I can pull the list of topics:
var credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(APPID, APPSECRET, TENANTID, AzureEnvironment.AzureGlobalCloud);
var serviceBusManager = ServiceBusManager.Authenticate(credentials, SUBSCRIPTIONID);
var serviceBusNamespace = serviceBusManager.Namespaces.List().SingleOrDefault(n => n.Name == "SERVICEBUSNAMESPACE");
var topics = serviceBusNamespace.Topics.ListAsync().GetAwaiter().GetResult();
However, I also need to get some information from Key Vault and I was trying to establish a common way to authenticate.
METHOD 1
Similar to the above, I tried this code to access KeyVault:
var credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(APPID, APPSECRET, TENANTID, AzureEnvironment.AzureGlobalCloud);
var kvManager = new KeyVaultClient(credentials);
var secret = kvManager.GetSecretAsync("https://VAULTNAMESPACE.vault.azure.net", "SECRETNAME").GetAwaiter().GetResult().Value;
I get the the following error:
Microsoft.Azure.KeyVault.Models.KeyVaultErrorException: 'Operation
returned an invalid status code 'Unauthorized''
METHOD 2
This code does work for Key Vault however (showing I have correct permissions):
string GetSecret()
{
var client = new KeyVaultClient(GetAccessToken);
var secret = client.GetSecretAsync("https://VAULTNAMESPACE.vault.azure.net", "SECRETNAME").GetAwaiter().GetResult();
return secret;
}
private static async Task<string> GetAccessToken(string authority, string resource, string scope)
{
var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
var credential = new ClientCredential(appId, appSecret);
var tokenResult = await context.AcquireTokenAsync("https://vault.azure.net", credential);
return tokenResult.AccessToken;
}
But, again, it's a very KeyVault specific way to Authenticate and I was hoping to establish a common mechanism using SdkContext.AzureCredentialsFactory. Any reason why I'd be getting an Unauthorized exception with the code above connecting to Key Vault? (all is set up correctly in Azure).
Thanks for any tips!
When you use SdkContext.AzureCredentialsFactory.FromServicePrincipal to authenticate, it will use https://management.azure.com/ as its Resource Uri.
While Azure Key Vault has its own authorization system and its Resource Uri is https://vault.azure.net, so you may get the Unauthorized error message.
So, you could use Method2 to get access to Azure Key Vault with right Resource Uri.
For more details, you could refer to this article.

Application access to SharePoint Online using Azure AD Token

How can I get an application token to query SharePoint with application credentials (= without user impersonation) using Azure AD?
The following code works perfectly for querying data as a user but we need to fetch information without impersonation like listing all sites in the collection regardless of user permissions etc.
Exception thrown:
An exception of type
'Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException'
occurred in mscorlib.dll but was not handled in user code
Additional information: AADSTS70001: Application with identifier 'xxx'
was not found in the directory sharepoint.com
Code to get token:
internal static async Task<string> GetSharePointAccessToken(string url, string userAccessTokenForImpersonation)
{
string clientID = #"<not posted on stack overflow>";
string clientSecret = #"<not posted on stack overflow>";
var appCred = new ClientCredential(clientID, clientSecret);
var authContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext("https://login.windows.net/common");
// Use user assetion if provided, otherwise use principal account
AuthenticationResult authResult = null;
if (string.IsNullOrEmpty(userAccessTokenForImpersonation))
{
authResult = await authContext.AcquireTokenAsync(new Uri(url).GetLeftPart(UriPartial.Authority), appCred);
}
else
{
authResult = await authContext.AcquireTokenAsync(new Uri(url).GetLeftPart(UriPartial.Authority), appCred, new UserAssertion(userAccessTokenForImpersonation));
}
return authResult.AccessToken;
}
Test code:
// Auth token from Bearer https://xxx.azurewebsites.net/.auth/me
string authHeader = #"<valid jwt bearer token from azure auth>";
var sharePointUrl = #"https://xxx.sharepoint.com/sites/testsite/";
string sharePrincipalToken = await GetSharePointAccessToken(sharePointUrl, null); // <-- doesn't work
string sharePointUserToken = await GetSharePointAccessToken(sharePointUrl, authHeader); // <-- works
Permissions in Azure AD:
The error message you are getting implies that you are signing in with a user that is pointing our token service to get a token in the context of "sharepoint.com"
This is because you are using the "common" endpoint. Read more about that here.
Instead try using a fixed endpoint, where the tenant is the same as where the application is registered and see if that solves your issue.
If your plan is to make this application accessible by multiple tenants, make sure that you have explicitly set your application to be multi-tenant, and then make sure you have a user from the external tenant try and sign into the application before you try doing service to service calls.
Let me know if this helps.

WIF SAML RequestSecurityToken STS Internal server error

I try to reach my STS to request a token. The code is based on a blog post by #leastprivilege : WCF and Identity in .NET 4.5: External Authentication with WS-Trust. I use the explicit approach (by code).
private static SecurityToken RequestSecurityToken()
{
// set up the ws-trust channel factory
var factory = new WSTrustChannelFactory(
new UserNameWSTrustBinding(
SecurityMode.TransportWithMessageCredential),
"https://federation.mydomain/adfs/services/trust/mex") { TrustVersion = TrustVersion.WSTrust13 };
//factory.Credentials.SupportInteractive = false;
factory.Credentials.UserName.UserName = "user-pcote";
factory.Credentials.UserName.Password = "123456";
// create token request
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Symmetric,
AppliesTo = new EndpointReference("https://myRP/")
};
var channel = factory.CreateChannel();
return channel.Issue(rst);
}
I can see the XML when copying the STS endpoint adress in my browser, therefore the federation server is reachable. But I always get an internal server error (500) as soon as I issue the token request. Does anybody have an idea what could be my problem here.
Finally managed to get it working by changing the KeyType to KeyTypes.Bearer (since there's no certificate applied to the RP in AD FS). I based myseflf on this website that gives a good explanations on how it all relates :
http://blog.skadefro.dk/2011/09/claimsbased-authentication-and-wcf.html
if we look in Microsoft.IdentityModel.SecurityTokenService.KeyTypes we
see we can use Asymmetric, Symmetric or Bearer. Tons of post out there
about this.
If you use Asymmetric you as requestor need to supply a key to encrypt
the claims with. ( set "UseKey” )
If you use Symmetric the identity provider have all ready been told
what certificate to use, to encrypt the claims with.
If you choose Bearer. The token get signed, but claims will not be
encrypted. If a token signing certificate have been assigned on the
Relying Party, claims will simply not be included at all.
When you request a token, the token gets signed (not encrypted) with a
certificate installed on the Identity Provider ( ADFS ). If you add a
certificate on a Relying Party Trust (RP) on the ADFS server, the
claims inside the token gets encrypted with with that certificate.
Only host/applications that have access to the private key of that
certificate can now decrypt the token and read the claims. You don’t
need to read the claims in order to authenticate your self. For
instance if you have a WCF Service you want to call from within an
application. You can from within that application still request a
token from the ADFS server and then access the WCF service with that
Token. As long as the WCF service have access to the private key and
can read the claims, your application don’t need it.
private static SecurityToken RequestSecurityToken()
{
var binding = new UserNameWSTrustBinding(
SecurityMode.TransportWithMessageCredential);
var factory = new WSTrustChannelFactory(
binding,
new EndpointAddress(new Uri("<your_adfs_uri>/adfs/services/trust/13/usernamemixed"), EndpointIdentity.CreateSpnIdentity("host/your.spn.com"))) { TrustVersion = TrustVersion.WSTrust13 };
factory.Credentials.UserName.UserName = "username";
factory.Credentials.UserName.Password = "password";
// create token request
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer,
AppliesTo = new EndpointReference(<uri_of_your_relying_party>)
};
var channel = factory.CreateChannel();
try
{
var response = channel.Issue(rst);
return response ;
}
catch (Exception e)
{
var message = e.Message;
return null;
}
}
I managed to find the right endpoint (which was /adfs/services/trust/13/usernamemixed) but now I get the following error :
ID4007: The symmetric key inside the requested security token must be encrypted

Resources