Support for user certificate authentification in Azure AD - azure

I'am searching for public/private key-based authentication for users with Azure-ActiveDirectory but can't find any hints in Azure AD Authentification Scenarios. Every user should bring his own key pair. Any suggestions how to achieve it?

Azure AD supports OAuth 2.0 to authorize the third-party apps and the OAuth 2.0 support to acquire the token using the app’s client credential.
There are two ways to acquire the token for the client credential flow.
First is that using the keys which generated by the Azure portal like figure below:
And here is a figure about token request using the key(client_secret):
Another way is using the cert. Technical speaking, the cert is a pair of public/private key. We will store the information of public key with the app. When we require to prove we are the owner of the third-party apps, we need to sign the message with the private key and Azure AD with verify the messages with public key.
To store the cert information with apps, we need to change the manifest of app. Here is the detail steps to use a self-signed certificate from here:
1.Generate a self-signed certificate:
makecert -r -pe -n "CN=MyCompanyName MyAppName Cert" -b 03/15/2015 -e 03/15/2017 -ss my -len 2048
2.Open the Certificates MMC snap-in and connect to your user account.
3.Find the new certificate in the Personal folder and export the public key to a base64-encoded file (for example, mycompanyname.cer). Your application will use this certificate to communicate with AAD, so make sure you retain access to the private key as well.
Note You can use Windows PowerShell to extract the thumbprint and base64-encoded public key. Other platforms provide similar tools to retrieve properties of certificates.
4.From the Windows PowerShell prompt, type and run the following:
$cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cer.Import("mycer.cer")
$bin = $cer.GetRawCertData()
$base64Value = [System.Convert]::ToBase64String($bin)
$bin = $cer.GetCertHash()
$base64Thumbprint = [System.Convert]::ToBase64String($bin)
$keyid = [System.Guid]::NewGuid().ToString()
5.Store the values for $base64Thumbprint, $base64Value and $keyid, to be used when you update your application manifest in the next set of steps.
Using the values extracted from the certificate and the generated key ID, you must now update your application manifest in Azure AD.
6.In the Azure Management Portal, select your application and choose Configure in the top menu.
7.In the command bar, click Manage manifest and select Download Manifest.
8.Open the downloaded manifest for editing and replace the empty KeyCredentials property with the following JSON:
"keyCredentials": [
{
"customKeyIdentifier": "$base64Thumbprint_from_above",
"keyId": "$keyid_from_above",
"type": "AsymmetricX509Cert",
"usage": "Verify",
"value": "$base64Value_from_above"
}
],
9.Save your changes and upload the updated manifest by clicking Manage manifest in the command bar, selectingUpload manifest, browsing to your updated manifest file, and then selecting it.
And below is the figure about token request using the cert:
In the article above, it generate the client_assertion from scratch. We can also use the ADAL library to help us and authenticate for a daemon apps:
string authority = $"https://login.microsoftonline.com/{tenant}";
var thumbprint="";
X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByThumbprint, thumbprint, false);
X509Certificate2 cert = fcollection[0];
var certCred = new ClientAssertionCertificate(clientId, cert);
var authContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(authority);
AuthenticationResult result = null;
try
{
result = await authContext.AcquireTokenAsync(resource, certCred);
}
catch (Exception ex)
{
}
return result.AccessToken;
And if you want to use the cert to authorize for the OAuth2.0 code grant flow, you also can refer the code sample here.

If you're looking for a programmatic method to authenticate users (not apps) in Azure AD using certificates, this is not currently possible.
It is possible to do certificate-based authentication in AD FS (e.g.), and it is possible to federate authentication for users from Azure AD to AD FS. However, this requires the overhead of Windows Server AD, Azure AD Connect and AD FS, and I don't think the federated authentication can be achieved in a programmatic way (i.e. without prompting the user to choose a certificate).

Related

Replacing secret with certificate in Azure app registration

I am currently using a client secret with an Azure app registration to access an Azure Media service from an App Service. I want to replace the client secret with a certificate as the certificate will last longer. I have successfully generated a certificate and uploaded it to the app registration.
Using the client secret seems straight forward. I create environment variables (in the app service configuration or local.settings.json) for the app registration client ID, app registration client secret and tenant ID and then use the following code:
private async Task<ServiceClientCredentials> GetCredentialsAsync(string aadClientId, string aadSecret, string aadTenantId)
{
ClientCredential clientCredential = new ClientCredential(aadClientId, aadSecret);
return await ApplicationTokenProvider.LoginSilentAsync(aadTenantId, clientCredential,
ActiveDirectoryServiceSettings.Azure);
}
How do I change this code to use the certificate?
I tried to reproduce the same in my environment and got the results like below:
I created an Azure AD Application and uploaded a certificate:
To generate the access token using certificate, you can declare the below parameters in your app.settings file:
"AzureAd": {
"Scope":"https://graph.microsoft/.default",
"Instance":"https://login.microsoftonline.com/",
"Domain":"XXX.onmicrosoft.com",
"TenantId":"YourTenantID",
"ClientId":"ClientID",
"ClientCertificates": [
{
"SourceType":"KeyVault",
"KeyVaultUrl":"https://xxx.vault.azure.net",
"KeyVaultCertificateName":"certName"
}
]
},
You can refer this blog by damienbod to know how generate the access token in detail.
I tried to generate the access token in Postman by using parameters like below:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:clientId
client_assertion_type:urn:ietf:params:oauth:client-assertion-type:jwt-bearer
scope:https://graph.microsoft.com/.default
grant_type:client_credentials
client_assertion:client_assertion
References:
Azure AD OAuth client credential flow with certificate by Nicola Delfino
App that calls MSGraph with a certificate by christosmatskas

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

Use a certificate in the keyvault to access multi-tenant application in other tenant

We have a multi-tenant application in our Azure AD tenant. It is authorized in some other tenants (we know which ones). And it has multiple certificates registered to it to be used as client credentials.
We want to remove the certificates from the local stores and use a certificate in the key vault to request a token for one of the external tenant. According to the documentation this is one of the use cases.
Our tenant (id: xxxx):
Has app registration (app id: abcd-xxx-xxxx-xxx)
has keyvault
has managed service principal (with access to the key vault)
other tenant (id: yyyy):
Executed Admin consent for our application.
Question 1:
How do I create a certificate in the Key vault that is connected to an existing application (app id: abcd-xxx-xxxx-xxx)? It is important to note that since the application is already approved by several third party admins, it cannot be recreated. Same counts for creating a new certificate after it would be expired.
Question 2:
How to I setup the Microsoft.Azure.Services.AppAuthentication library to:
Use the managed identity to access the key vault in our tenant (xxxx).
Use the certificate in the key vault to request a token for our app (abcd-xxx-xxxx-xxx) in other companies tenant (yyyy)
Answer 1:
You could use az ad sp credential reset command like below. If you don't want to overwrite the existing certificate of the App, please pass the --append parameter.
az ad sp credential reset --name '<application-id>' --keyvault joykeyvault --cert cer136 --create-cert --append
Answer 2:
1.To use the MSI access the keyvault in your tenant, just use the code below.
No code changes are required, when you run your code on an Azure App Service or an Azure VM with a managed identity enabled, the library automatically uses the managed identity, see this link.
The environment variable AzureServicesAuthConnectionString has to be set to any credential with access to the keyvault. RunAs=Developer; DeveloperTool=AzureCli for dev or RunAs=App; for managed service identity (automatically in azure).
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.KeyVault;
// Instantiate a new KeyVaultClient object, with an access token to Key Vault
var azureServiceTokenProvider1 = new AzureServiceTokenProvider();
var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider1.KeyVaultTokenCallback));
2.If you want to use the service principal along with its certificate stored in the keyvault to get the token for the resources in another tenant, the connection string on the AzureServiceTokenProvider has to be set to RunAs=App;AppId={TestAppId};KeyVaultCertificateSecretIdentifier={KeyVaultCertificateSecretIdentifier} then you can get tokens for other tenants like.
const string appWithCertConnection = "RunAs=App;AppId={TestAppId};KeyVaultCertificateSecretIdentifier=https://myKeyVault.vault.azure.net/secrets/myCert";
Then use the code to get the token, e.g. for the resource https://management.azure.com/.
var azureServiceTokenProvider2 = new AzureServiceTokenProvider(appWithCertConnection);
string accessToken = await azureServiceTokenProvider2.GetAccessTokenAsync("https://management.azure.com/", "tenant-id-of-thridh-party-tenant").ConfigureAwait(false);

Use Azure Vault Secret from onpremise Web Application

I would like to use an Azure Key Vault secret from an on-premise web application.
I created a Key Vault with a Secret, but in Access Policies I should specify an Authorized Application and in the samples is used an Azure WebApp.
I want instead use the Secret from on-premise MVC web app: shoud i specify nothing and it works ? i specified the Azure Vault and as Principal myself but i'm not sure if this is correct.
Well, something will need to authenticate to access the secret.
Either the current user, or you can use a service principal.
Since we are talking about an MVC app, the service principal is probably easier.
You will need to register a new app in Azure Active Directory via the Azure Portal.
Find Azure AD, and register a new app via App registrations.
The name and URLs don't really matter, but it needs to be of type Web app/API.
The sign-on URL can be https://localhost for example.
Then add a key in the Keys blade to the app (click Settings after the app is created, then Keys).
Copy the client id (application id) and the key somewhere.
Now you can go to your Key Vault, and create a new access policy, and choose the app you created as the principal.
Give it the rights you want, like Secrets -> Get.
Then you can save the policy.
In your app, you can then use the Key Vault library + ADAL like so:
var kvClient = new KeyVaultClient(async (authority, resource, scope) =>
{
var context = new AuthenticationContext(authority);
var credential = new ClientCredential("client-id-here", "key-here");
AuthenticationResult result = await context.AcquireTokenAsync(resource, credential);
return result.AccessToken;
});
SecretBundle secret = await kvClient.GetSecretAsync("https://yourvault.vault.azure.net/", "secret-name");
string secretValue = secret.Value;

Office 365, oauth2, where do I find Key+Secret?

I'm trying for the first time to get access to 365 using oauth2, for my Native Application.
I have registered my application in Azure AD.
The documentation says, "...In the Azure Management Portal, select your application and choose Configure in the top menu. Scroll down to keys."
But in (my) Azure Application, Configure properties, I only have Name, Client ID, URL and Logo, and the Permissions area - No "Keys" area.
Am I missing something?
Web Application And/OR Web API
As tou are looking for KEYS , You need to create your application in AD as Web Application or web API
then you can find the Key and secret.
Native Client Application
If you're developing a native client app, you don't need the keys because this auth flow doesn't require them.
So first of all you need to use ADAL (Active Directory Authentication Library) use the right version for your client program.
Then you should to reference your AD configuration for the App, note there are no KEYs required.
// Native client configuration in AzureAD
private string clientID = "3dfre985df0-b45640-443-a8e5-f4bd23e9d39f368";
private Uri redirectUri = new Uri("http://myUrl.webapi.client");
Then prepare AD authority URL and create the Auth Context.
private const string authority = "https://login.windows.net/cloudalloc.com";
private AuthenticationContext authContext = new AuthenticationContext(authority);
That's all, after that you need to ask for access tokens depending on the resource you want to access.
AuthenticationResult result = null;
try
{
result = authContext.AcquireToken(resource, clientId, redirectUri, PromptBehavior.Never);
}
catch (AdalException ex)
{
if (ex.ErrorCode != "user_interaction_required")
{
// An unexpected error occurred.
MessageBox.Show(ex.Message);
}
}
the resource could be a webapi or office 365 resource URI

Resources