I'm trying to set up the Azure Media Service. I created the media service from Azure but I don't know where can obtain the account key.
client = new CloudMediaContext(new MediaServicesCredentials(accountName, accountKey));
I'm following this tutorial: Integrating applications with Azure Active Directory
But after get the secret key in step 4 in "To add application credentials, or permissions to access web APIs" doesn't works.
client = new CloudMediaContext(new MediaServicesCredentials(accountName, accountKey));
Azure Media Services announces support for AAD and deprecation of ACS authentication.
Because Azure Active Directory provides powerful role-based access control features and support for more fine-grained access to resources in your account compared to the ACS token authentication model ("account keys"), we strongly recommend that you update your code and migrate from ACS to AAD-based authentication by June 22, 2018.
Also, a key reason for the rapid migration is the upcoming announced deprecation of the ACS key based authentication system.
User Authentication with AAD in Media Services
A native application would first acquire an access token from Azure Active Directory and then use that access token to make all REST API calls.
The following examples show how a daemon application may use AAD web application credentials to authenticate requests with the REST service.
For a REST API request to succeed, the calling user must be a “Contributor” or “Owner” of the Azure Media Services account it is trying to access.
Users of the .NET client SDK for Media Services must upgrade to the latest version on Nuget (windowsazure.mediaservices version 4.1.0.1 or greater) to use AAD authentication for communicating with REST requests.
You could use the following code to connect to the Media Services account.
class Program
{
// Read values from the App.config file.
private static readonly string _AADTenantDomain =
ConfigurationManager.AppSettings["AMSAADTenantDomain"];
private static readonly string _RESTAPIEndpoint =
ConfigurationManager.AppSettings["AMSRESTAPIEndpoint"];
private static readonly string _AMSClientId =
ConfigurationManager.AppSettings["AMSClientId"];
private static readonly string _AMSClientSecret =
ConfigurationManager.AppSettings["AMSClientSecret"];
private static CloudMediaContext _context = null;
static void Main(string[] args)
{
try
{
AzureAdTokenCredentials tokenCredentials =
new AzureAdTokenCredentials(_AADTenantDomain,
new AzureAdClientSymmetricKey(_AMSClientId, _AMSClientSecret),
AzureEnvironments.AzureCloudEnvironment);
var tokenProvider = new AzureAdTokenProvider(tokenCredentials);
_context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider);
// Add calls to methods defined in this section.
// Make sure to update the file name and path to where you have your media file.
IAsset inputAsset =
UploadFile(#"C:\VideoFiles\BigBuckBunny.mp4", AssetCreationOptions.None);
IAsset encodedAsset =
EncodeToAdaptiveBitrateMP4s(inputAsset, AssetCreationOptions.None);
PublishAssetGetURLs(encodedAsset);
}
catch (Exception exception)
{
// Parse the XML error message in the Media Services response and create a new
// exception with its content.
exception = MediaServicesExceptionParser.Parse(exception);
Console.Error.WriteLine(exception.Message);
}
finally
{
Console.ReadLine();
}
}
NOTE: Applications will also need to update their references to include a new assembly "Microsoft.WindowsAzure.MediaServices.Client.Common.Authentication.dll" and add references to that namespace as well as reference to the "Microsoft.IdentityModel.Clients.ActiveDirectory" assembly to get access to the ITokenProvider interface.
Click API access and choose "
Connect to Azure Media Services API with user authentication".
This includes the API endpoint that you need to call, along with the ClientID, Domain, and Resource.
For more details about how to connect to Media Services with Azure AD, you could refer to this article.
Related
I have a scenario where I have asp.net core web api and a azure function. I call web api from azure time triggered function for every 1 hour. I do not have authentication enabled on the web api and I do not want public to access it. Only my azure function should be able to access the web api. How can I restrict web api to access from public but only from azure function with out implementing authentication.
I tried the below,
In webapi appsettings file, I updated "AllowedHosts":"https://testfuntionapp.azurewebsites.net". My testfuntionapp is unable to access web api with this change.
I am trying for a cost effective solution.
Please check if my findings help to:
How can I restrict web api to access from public but only from azure function without implementing authentication.
This is where the Azure Virtual Networks comes to.
Create the Virtual Network, configure the Azure Function to only be callable on this VNet and also can configure your core app access to the VNet.
By using Private Endpoints, resources are accessible only via your Virtual Network.
If Virtual Network Integration enabled, then the Azure Function is able to access the designated resource via the configured private endpoints, which is a higher level of security.
References:
Michael S Collier's article on Azure Functions with Private Endpoints.
Access an App Service integrated with a Virtual Network from other Azure resources like Azure Functions
I would also recommend private endpoints as suggested by HariKrishnaRajoli.
In theory it would also suffice to just configure http header filtering for access restriction rules and only allow requests containing a secret header known only to your azure function code. This is probably comparable to "basic" HTTP authentication security, and weaker than the other options.
As an alternative, you can use AAD authentication without really "implementing" much authentication code.
Configure Easy Auth on the WebApi
Configure ManagedIdentity for your Azure Function
Give your the Managed Identity access to call the WebApi using "App Role Assignments"
Extend your Azure Function to acquire and pass access token when calling the WebApi
If you only want your Azure function to be able to access your web API, you can restrict access to your web API by IP address.
In your web API's appsettings.json file, add the following:
"AllowedHosts": "https://testfuntionapp.azurewebsites.net"
This will restrict access to your web API to only requests coming from the specified Azure function.
The fastest and "dirtiest" way to do this, is to pass an API key as a header to your REST API from the function.
You can hardcode the API key to your config file or load it from your DB.
My implementation:
namespace CoreApi.Middleware
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequirePartnerApiKeyAttribute : Attribute, IAsyncActionFilter
{
private const string ApiKeyHeaderName = "x-partner-apikey";
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
//----------------------------------------------------
// Validate Api Key
//----------------------------------------------------
if (!context.HttpContext.Request.Headers.TryGetValue(ApiKeyHeaderName, out var apiKey) ||
string.IsNullOrEmpty(apiKey))
{
context.Result = new UnauthorizedResult();
return;
}
var partnerService = context.HttpContext.RequestServices.GetRequiredService<IPartnerService>();
var apiRequest = new PartnerAuthenticateRequest { PartnerApiKey = apiKey };
var partner = partnerService.Authenticate(apiRequest, new CancellationToken()).Result;
if (partner == null)
{
context.Result = new UnauthorizedResult();
return;
}
else
{
if (Enum.IsDefined(typeof(ApiKeyTypes), partner.PartnerName))
context.HttpContext.Items["APIKeyName"] = Enum.Parse(typeof(ApiKeyTypes), partner.PartnerName);
}
//----------------------------------------------------
await next();
}
}
}
You can access the API key from any middleware by calling: context.HttpContext.Items["APIKeyName"]
I am new to Azure and trying to protect/web api hosted in azure using oauth 2.0.
This web api will be called from other web api/deamon which is in control of other organization.
I am aware of client credential flow, but in this scenario external api is hosted outside azure ad. We have no idea of where it is hosted and how this third external web api/deamon is hosted? How should we do authentication/authorization for our web api, so that any external service can use it?
You know about client credential flow, then you should know that this kind of flow doesn't need a user to sign in to generate access token, but only need an azure ad application with the client secret. This azure ad application can come from your tenant, so it doesn't require the web api/deamon which is in control of other organization to have an application, you can create the app in your tenant then provide it to the external web api. What you need to make sure is that the external is really a daemon application.
Let's assume that the external app that need to call your api which is protected by azure ad is a daemon application, then client credential flow is suitable here.
Code for external api to generate access token
//you can see it when you add api permission
var scopes = new[] { "api://exposed_apis_app_id/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";
// using Azure.Identity;
var options = new TokenCredentialOptions{AuthorityHost = AzureAuthorityHosts.AzurePublicCloud};
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
var tokenRequestContext = new TokenRequestContext(scopes);
var token = clientSecretCredential.GetTokenAsync(tokenRequestContext).Result.Token;
Code for your api to add authentication for azure ad, you still have some more configurations, you can refer to my this answer, some related document: authorize the token with role and jwt token configuration.
[Authorize]
public class HelloController : Controller
{
public IActionResult Index()
{
HttpContext.ValidateAppRole("User.Read");//You set it when adding app role
Student stu = new Student();
stu.age = 18;
return Json(stu) ;
}
}
appsettings:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "2c0xxxxxxx57",
"Domain": "tenantname.onmicrosoft.com", // for instance contoso.onmicrosoft.com. Not used in the ASP.NET core template
"TenantId": "common",
"Audience": "8fxxxx78"
}
startup.cs, don't forget "app.UseAuthentication();app.UseAuthorization();" in Configure method
public void ConfigureServices(IServiceCollection services)
{
services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
services.AddControllersWithViews();
}
create an azure ad application in your tenant and expose an api with a role.
you can create another azure ad application, add client secret and add the application permission created before in the API permissions blade.
provide the application id and client secret to those external app and let them use these to generate access token, then they can use the access token to call your api.
modify your api to authorize the token if has the correct role.
I want to call this API from azure resource manager to get the storage keys:
https://learn.microsoft.com/en-us/rest/api/storagerp/storageaccounts/listkeys
I want to use user authentication for this call and possibly .net sdk.
Is there any .net sdk(Nuget package) I can include in my c# project to call this API? I am seeing many solution which is using .net sdk but they are using AAD app secret, but I cannot use secret in the app since it is a desktop app. I think there should be a way to call these API with user auth and .net sdk.
The Microsoft.Azure.Services.AppAuthentication for .NET library may meet your requirement. It uses the developer's credentials to authenticate during local development. When the solution is later deployed to Azure, the library automatically switches to application credentials.
The Microsoft.Azure.Services.AppAuthentication library supports local development with Microsoft Visual Studio, Azure CLI, or Azure AD Integrated Authentication.
Sample:
using Microsoft.Azure.Management.Storage;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Rest;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/").Result;
var Credentials = new TokenCredentials(accessToken);
var storageManagementClient = new StorageManagementClient(Credentials);
storageManagementClient.SubscriptionId = "subscription id";
var storageAccountKey = storageManagementClient.StorageAccounts.ListKeysAsync("resource grouop name", "storage account name");
string storage_Account_Key = storageAccountKey.Result.Keys[0].Value;
System.Console.WriteLine(storage_Account_Key);
}
}
}
For more details about the authentication, you could take a look at this link.
We have setup our application using Azure AD B2C and OAuth, this works fine, however I am trying to authenticate as a service in order to make service to service calls. I am slightly new to this, but I have followed some courses on Pluralsight on how to do this on "normal" Azure Active Directory and I can get it to work, but following the same principles with B2C does not work.
I have this quick console app:
class Program
{
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; //APIClient ApplicationId
private static string appKey = ConfigurationManager.AppSettings["ida:appKey"]; //APIClient Secret
private static string aadInstance = ConfigurationManager.AppSettings["ida:aadInstance"]; //https://login.microsoftonline.com/{0}
private static string tenant = ConfigurationManager.AppSettings["ida:tenant"]; //B2C Tenant
private static string serviceResourceId = ConfigurationManager.AppSettings["ida:serviceResourceID"]; //APP Id URI For API
private static string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
private static AuthenticationContext authContext = new AuthenticationContext(authority);
private static ClientCredential clientCredential = new ClientCredential(clientId, appKey);
static void Main(string[] args)
{
AuthenticationResult result = authContext.AcquireToken(serviceResourceId, clientCredential);
Console.WriteLine("Authenticated succesfully.. making HTTPS call..");
string serviceBaseAddress = "https://localhost:44300/";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpResponseMessage response = httpClient.GetAsync(serviceBaseAddress + "api/location?cityName=dc").Result;
if (response.IsSuccessStatusCode)
{
string r = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(r);
}
}
}
And the service is secured like this:
private void ConfigureAuth(IAppBuilder app)
{
var azureADBearerAuthOptions = new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters()
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
}
};
app.UseWindowsAzureActiveDirectoryBearerAuthentication(azureADBearerAuthOptions);
}
In my B2C tenant I have two different applications that are pretty much setup as this:
Both applications have been setup with secrets coming from the "keys" option. The keys generated are slightly differently structured than when using Azure Active Directory.
I can successfully get a token, but I get 401 when trying to connect to the other service. Do I have to do something different on the authorization side when using B2C compared to Azure Active Directory?
Azure Active Directory B2C can issue access tokens for access by a web or native app to an API app if:
Both of these apps are registered with B2C; and
The access token is issued as result of an interactive user flow (i.e. the authorization code or implicit flows).
Currently, your specific scenario -- where you are needing an access token to be issued for access by a daemon or server app to the API app (i.e. the client credentials flow) -- isn't supported, however you can register both of these apps through the “App Registrations” blade for the B2C tenant.
You can upvote support for the client credentials flow by B2C at:
https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/18529918-aadb2c-support-oauth-2-0-client-credential-flow
If the API app is to receive tokens from both the web/native app as well as the daemon/server app, then you will have to configure the API app to validate tokens from two token issuers: one being B2C and other being the Azure AD directory in your B2C tenant.
I found the following very clear article from Microsoft which explains how to set up a "service account" / application which has management access to a B2C tenant. For me, that was the use case for which I wanted to "Authenticating as a Service with Azure AD B2C".
It is possible that having management access to a B2C tenant doesn't allow you access a protected resource for which your B2C tenant is the Authorization server (I haven't tried that), so the OP's use case may be slightly different but it feels very close.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-graph-dotnet
For automated, continuous tasks, you should use some type of service account that you provide with the necessary privileges to perform management tasks. In Azure AD, you can do this by registering an application and authenticating to Azure AD. This is done by using an Application ID that uses the OAuth 2.0 client credentials grant. In this case, the application acts as itself, not as a user, to call the Graph API.
In this article, we'll discuss how to perform the automated-use case. To demonstrate, we'll build a .NET 4.5 B2CGraphClient that performs user create, read, update, and delete (CRUD) operations. The client will have a Windows command-line interface (CLI) that allows you to invoke various methods. However, the code is written to behave in a noninteractive, automated fashion.
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