Get Access Token for Azure - c#

I am trying to access the Azure access token to get some information related to APIs hosted in Azure.
I used the code below in Visual studio and I get the token since I logged into VS with my credentials.
However, when I deployed this code I don't get the token and it throws an error, since the deployed environment does not have VS and just has the executable running there.
Sample code:
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/", "tenantId").Result;
What is the best practice to get the azure access token?

Here is the code that worked for me
var tenantId = "<Your Tenant ID>";
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var token = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com", tenantId);
var tokenCredentials = new TokenCredentials(token);
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(new AzureCredentials(
tokenCredentials,
tokenCredentials,
tenantId,
AzureEnvironment.AzureGlobalCloud))
.WithDefaultSubscription();
Note : Make sure you install Microsoft.Rest.ClientRuntime for "TokenCredentials".
REFERENCES:
Using AzureServiceTokenProvider to authenticate with the Azure Libraries for .NET

Related

How to authenticate correctly in SharePoint Online from Azure Function with API Graph?

Ciao,
I'm working on a Azure Function that need to read/write to a SharePoint Online list using API Graph. I've some problems on authentication.
I've followed this steps:
Created one SharePoint Online site and one list
Registered my app in Azure Active Directory (single-tenant)
Generated one secret
Added Sites.Selected authorization to my app
Requested permissions to my administrator following this link
Wrote code for use API Graph
Below app's authorizations:
Below my code:
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "my-tenant-id";
var clientId = "my-client-id";
var clientSecret = "my-secret";
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var graphServiceClient = new GraphServiceClient(clientSecretCredential, scopes);
var test = await graphServiceClient
.Sites["my-site-id"]
.Lists["my-list-id"]
.Items.Request().GetAsync();
When I execute this code I obtain this error: Message: Either scp or roles claim need to be present in the token.
How can I resolve this error?
Thank you a lot
I tried to reproduce the same in my environment and got the same error as below:
To resolve the error, I created an Azure AD Application and granted API Permissions like below:
Note that, you can only add Sites.Selected API permission based on your requirement.
I generated the token with scope as https://graph.microsoft.com/.default by using below parameters:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:ClientID
client_secret:ClientSecret
scope:https://graph.microsoft.com/.default
grant_type:client_credentials
Using the above generated access token, I am able to authenticate to SharePoint successfully like below:
https://graph.microsoft.com/v1.0/sites/

Using authProvider with MS SDK for graph calls in C#

I'm trying create a C# console application to connect to graph API and get a list of users from AzureAD from a tenant. I have registered the app and the admin has given me the following
Tenant Name and Tenant ID
Client ID (also sometimes called App Id)
Client Secret
Using the sdk the C# code I need to use looks like this (https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=cs):
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var users = await graphClient.Users
.Request()
.GetAsync();
However, the console application will run as a batch process so there will be no user interaction at all. So in order to provide the authProvider I followed this article on MS docs site: https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=CS
And I think for my purpose I need to go for the "Client Credential OAuth flow". The code which is shown on that URL. But here it is too.
IConfidentialClientApplication clientApplication = ClientCredentialProvider.CreateClientApplication(clientId, clientCredential);
ClientCredentialProvider authProvider = new ClientCredentialProvider(clientApplication);
The trouble is that Visual Studio does not recognise ClientCredentialProvider class. I'm not sure which assembly to import. I'm using the following usings in the top.
using Microsoft.Identity.Client;
using Microsoft.IdentityModel.Clients;
using Microsoft.IdentityModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
I'm not very experienced with GitHub repos and I'm using Visual Studio 2015. I would be interested in sample code; I have looked but cannot find any. MS have some lectures but they use another type of auth Provider which is authenticating interactively which is not what I'm looking for. I want obtain the token using the TenantId/ClientId and Client Secret.
ClientCredentialProvider is part of the Microsoft.Graph.Auth package. You can read more about this package at https://github.com/microsoftgraph/msgraph-sdk-dotnet-auth
Note that this package is currently (as of 2019-05-15) in preview, so you may want to wait before using this in a production application.
Alternatively, the following example uses the Microsoft Authentication Library for .NET (MSAL) directly to set up the Microsoft Graph SDK using app-only authentication:
// The Azure AD tenant ID or a verified domain (e.g. contoso.onmicrosoft.com)
var tenantId = "{tenant-id-or-domain-name}";
// The client ID of the app registered in Azure AD
var clientId = "{client-id}";
// *Never* include client secrets in source code!
var clientSecret = await GetClientSecretFromKeyVault(); // Or some other secure place.
// The app registration should be configured to require access to permissions
// sufficient for the Microsoft Graph API calls the app will be making, and
// those permissions should be granted by a tenant administrator.
var scopes = new string[] { "https://graph.microsoft.com/.default" };
// Configure the MSAL client as a confidential client
var confidentialClient = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithAuthority($"https://login.microsoftonline.com/$tenantId/v2.0")
.WithClientSecret(clientSecret)
.Build();
// Build the Microsoft Graph client. As the authentication provider, set an async lambda
// which uses the MSAL client to obtain an app-only access token to Microsoft Graph,
// and inserts this access token in the Authorization header of each API request.
GraphServiceClient graphServiceClient =
new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) => {
// Retrieve an access token for Microsoft Graph (gets a fresh token if needed).
var authResult = await confidentialClient
.AcquireTokenForClient(scopes)
.ExecuteAsync();
// Add the access token in the Authorization header of the API request.
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
})
);
// Make a Microsoft Graph API query
var users = await graphServiceClient.Users.Request().GetAsync();
(Note that this example uses the latest version of the Microsoft.Identity.Client package. Earlier versions (before version 3) did not include ConfidentialClientApplicationBuilder.)
As mentioned above - at the time of writinf Sept 2021, the package: Microsoft.Graph.Auth is deprecated. This means ClientCredentialProvider is no longer available.
https://www.nuget.org/packages/Microsoft.Graph.Auth/
The alternative is to use the solution propsed by Philippe above.
If you wanna cycle trough the users, replace the var users with the following code:
IGraphServiceUsersCollectionPage users = graphServiceClient.Users.Request().GetAsync().Result;
foreach (User user in users)
{
Console.WriteLine("Found user: " + user.Id);
}

Create Azure web app SSL binding using certificate from key vault

I'm trying to add SSL to an Azure web app using a certificate retrieved from the key vault. I don't see a way to do this via the portal so I've have been trying to do it with the Azure API.
I'm able to get the certificate secret and convert it to a X509 certificate using the following code:
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
SecretBundle secret2 = await keyVaultClient.GetSecretAsync(KEY_VAULT_IDENTIFIER);
string pass = null;
X509Certificate2 certificate = new X509Certificate2(Convert.FromBase64String(secret2.Value), pass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
I honestly don't know what to do next. I've been looking into the Microsoft.Azure.Management.Fluent library but haven't been able to get anything working.
Am I headed in the right direction? Are there any examples out there that may help?
For C# code, you can make use of Azure Management Libraries for .NET
You can use following 2 Nuget packages:
Microsoft.Azure.Management.Fluent
Microsoft.Azure.Management.ResourceManager.Fluent
Authentication
You can read the guidance here
First step will be to create a Service Principal for RBAC, give it permissions on the relevant resource group and then use the clientId, secret and tenant information in code ahead.
az ad sp create-for-rbac
Code
string clientId = "xxxxx-xxx-xxxx";
string clientSecret = "xxxxx-xxx-xxxx";
string tenant = "xxxxx-xxx-xxxx";
string subscriptionId = "xxxxx-xxx-xxxx";
var creds = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenant, AzureEnvironment.AzureGlobalCloud);
var azure = Azure.Authenticate(creds).WithSubscription(subscriptionId);
var app1 = azure.WebApps.GetByResourceGroup("rgAppService", "MyAPIServiceName");
app1.Update()
.DefineSslBinding()
.ForHostname("MyHostName")
.WithExistingCertificate("<Thumbprint of the certificate>")
.WithSniBasedSsl() // could use different method .WithIpBasedSsl in case that is relevant
.Attach()
.Apply();
Detailed Code Sample on GitHub
Managing Web Apps with custom domains in C#
This sample does a lot of things like creating the Apps, domains etc., so pick the parts that are applicable for you.

MSAL + Azure App Services

I've posted this before, but the thread became pretty extensive and confusing and a resolution was never met. I'm reposting with a clear and concise block of code and my desired outcome.
I'm looking to use client-flow authentication for an Azure App Services backend.
I'd like to use MSAL, to support both Microsoft Accounts (MSA) and AAD accounts. Been stuck on this for weeks with no resolution in sight.
PublicClientApplication myApp = new PublicClientApplication("registered-app-id-in-apps.dev-portal");
string[] scopes = new string[] { "User.Read" };
AuthenticationResult authenticationResult = await myApp.AcquireTokenAsync(scopes);
JObject payload = new JObject();
payload["access_token"] = authenticationResult.AccessToken;
payload["id_token"] = authenticationResult.IdToken;
user = await MobileService.LoginAsync(MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload);
Why doesn't this work?
What do I have to do to get it to work?
Getting a 401 exception, tried with MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory as well as MobileServiceAuthenticationProvider.Microsoftaccount
--App Service Auth Config for Microsoft Account:
ClientID and ClientSecret as it appears in apps.dev.microsoft.com
--App Service Auth Config for AAD:
ClientID as it appears in apps.dev.microsoft.com
Issuer URL: https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
Client Secret: (Blank)
Been having the same issue, having set up Azure Active Directory authentication on the App Service & attempting to authenticate from a WinForms client using MSAL. Turns out that, as of the time of this writing, Azure App Service does not support AAD V2 (including MSAL). Found the below note here:
At this time, AAD V2 (including MSAL) is not supported for Azure App Services and Azure Functions. Please check back for updates.
So ADAL seems to be the only viable option at the moment, unless you handle the authentication inside your backend code yourself.

Azure Graph with B2C AD

When I try to acquire a token from my Azure AD B2C app using
Microsoft.IdentityModel.Clients.ActiveDirectory - 3.13.1
Microsoft.Azure.ActiveDirectory.GraphClient - 2.1.0
like this:
var authUri = "https://login.microsoftonline.com/6b7403d6-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/token";
var clientId = "59e08b82-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
var appKey = "XXXX-MyAppKey-XXXX";
var graphUri = "https://graph.windows.net/6b7403d6-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
var authenticationContext = new AuthenticationContext(authUri, false);
var clientCred = new ClientCredential(clientId, myAppKey);
var authenticationResult = await authenticationContext.AcquireTokenAsync(graphUri, clientCred);
I get
[AdalServiceException: AADSTS70001: Application '59e08b82-xxxx-xxxx-xxxx-xxxxxxxxxxxx' is not supported for this API version.
Is there a library I can use in ASP.NET MVC 5 (.NET 4.5) to get access to the B2C Active directory I created using the UI of the new Azure Portal, not PowerShell from this example?
(The xxxx's are just for privacy here)
You don't need power shell creation any more, MSFT have given permission to add a new application in Azure AD(not in azure b2c), which can be used to access Graph API in azure B2C. You need to follow below steps IN https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-graph-dotnet
Only for Deleting access for your graph api you need to do some power-shell magic...
The example you referenced: https://azure.microsoft.com/en-us/documentation/articles/active-directory-b2c-devquickstarts-graph-dotnet/
only uses powershell to set up a Service Principal.
After you have the Service Principal, you can use that in your code to access the Graph API. The example does this from a console app, but this works as well from MVC 5

Categories

Resources