PowerBi Embedded suspend and resume capacity using .NET SDK - azure

I'm trying to figure out whether there is a azure management NuGet package that I can use to communicate with this part of the API for suspending and resuming my powerbi embedded capacities.
I have been unable to find it. Does what I'm looking for exist?

Does what I'm looking for exist?
In short, No. As the link you provided, it need azure_auth to access to Power BI Embedded.
You could use the below code to get the access_token and call the rest api you provide.
private static string redirectUri = "https://login.live.com/oauth20_desktop.srf";
private static string resourceUri = "https://analysis.windows.net/powerbi/api";
private static string authorityUri = "https://login.windows.net/common/oauth2/authorize";
// Obtain at https://dev.powerbi.com/apps
private static string clientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
private static AuthenticationContext authContext = new AuthenticationContext(authorityUri, new TokenCache());
private async void btnAuthenticate_ClickAsync(object sender, EventArgs e)
{
var authenticationResult = await authContext.AcquireTokenAsync(resourceUri, clientId, new Uri(redirectUri), new PlatformParameters(PromptBehavior.Auto));
if (authenticationResult == null)
MessageBox.Show("Call failed.");
else
MessageBox.Show(authenticationResult.AccessToken);
}
You can refer to the article about Power BI for .NET. Also you could use powershell to Resume-AzPowerBIEmbeddedCapacity.

Related

Trying to authenticate with Azure for using Power BI Embedded

Below is the output from an error which is being generated whilst trying to authenticate credentials with Azure for allowing public access to a Power BI Embedded report:
It has initially displayed a pop to confirm that I want to give but after I have given permission the above error is displayed.
I have checked the credentials I have entered in the appsettings.json file and have confirmed that they are correct.
In the Startup.cs file I have added this section:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"), "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi(Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' '))
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
services.AddScoped(typeof(PowerBiServiceApi));
services.AddRazorPages()
.AddMicrosoftIdentityUI();
The error itself is being generated whilst acquiring the access token in the PowerBiServiceApi the code for which is provided below:
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Identity.Web;
using Microsoft.PowerBI.Api;
using Microsoft.PowerBI.Api.Models;
using Microsoft.Rest;
namespace NDTSM2.Services.Implementations.PowerBI
{
// A view model class to pass the data needed to embed a single report.
public class EmbeddedReportViewModel
{
public string Id;
public string Name;
public string EmbedUrl;
public string Token;
}
public class PowerBiServiceApi
{
private ITokenAcquisition tokenAcquisition { get; }
private string urlPowerBiServiceApiRoot { get; }
public PowerBiServiceApi(IConfiguration configuration, ITokenAcquisition tokenAcquisition)
{
this.urlPowerBiServiceApiRoot = configuration["PowerBi:ServiceRootUrl"];
this.tokenAcquisition = tokenAcquisition;
}
public const string powerbiApiDefaultScope = "https://analysis.windows.net/powerbi/api/.default";
// A method to get the Azure AD token (also known as 'access token')
public string GetAccessToken()
{
return this.tokenAcquisition.GetAccessTokenForAppAsync(powerbiApiDefaultScope).Result;
}
public PowerBIClient GetPowerBiClient()
{
var tokenCredentials = new TokenCredentials(GetAccessToken(), "Bearer");
return new PowerBIClient(new Uri(urlPowerBiServiceApiRoot), tokenCredentials);
}
public async Task<EmbeddedReportViewModel> GetReport(Guid WorkspaceId, Guid ReportId)
{
PowerBIClient pbiClient = GetPowerBiClient();
// Call the Power BI service API to get the embedding data
var report = await pbiClient.Reports.GetReportInGroupAsync(WorkspaceId, ReportId);
// Generate a read-only embed token for the report
var datasetId = report.DatasetId;
var tokenRequest = new GenerateTokenRequest(TokenAccessLevel.View, datasetId);
var embedTokenResponse = await pbiClient.Reports.GenerateTokenAsync(WorkspaceId, ReportId, tokenRequest);
var embedToken = embedTokenResponse.Token;
// Return the report embedded data to caller
return new EmbeddedReportViewModel
{
Id = report.Id.ToString(),
EmbedUrl = report.EmbedUrl,
Name = report.Name,
Token = embedToken
};
}
}
}
Does anyone have any ideas why the error is being generated (have looked for guidance but so far none of the advice has rectified the issue)?
Any help would be very much appreciated.
Further to original question:
Error Details:
Operation returned an invalid status code 'Unauthorized'
at Microsoft.PowerBI.Api.ReportsOperations.GetReportInGroupWithHttpMessagesAsync(Guid groupId, Guid reportId, Dictionary`2 customHeaders, CancellationToken cancellationToken)
at Microsoft.PowerBI.Api.ReportsOperationsExtensions.GetReportInGroupAsync(IReportsOperations operations, Guid groupId, Guid reportId, CancellationToken cancellationToken)
at Microsoft.PowerBI.Api.ReportsOperationsExtensions.GetReportInGroup(IReportsOperations operations, Guid groupId, Guid reportId)
at NDTSM2.Services.Implementations.PowerBI.PbiEmbedService.GetEmbedParams(Guid workspaceId, Guid reportId, Guid additionalDatasetId) in C:\Users\cryof\Desktop\NDTMS4\Service\NDTSM2.SERVICES\Implementations\PowerBI\PbiEmbedService.cs:line 41
at NDTMS2.Web.Controllers.EmbedInfoController.GetEmbedInfo() in C:\Users\cryof\Desktop\NDTMS4\NDTMS2.WEB\Controllers\EmbedInfoController.cs:line 40
The line that is generating the error in the PbiEmbedService is this:
var pbiReport = pbiClient.Reports.GetReportInGroup(workspaceId, reportId);
Follow the sample here
// For app only authentication, we need the specific tenant id in the authority url
var tenantSpecificUrl = azureAd.Value.AuthorityUrl.Replace("organizations", azureAd.Value.TenantId);
// Create a confidential client to authorize the app with the AAD app
IConfidentialClientApplication clientApp = ConfidentialClientApplicationBuilder
.Create(azureAd.Value.ClientId)
.WithClientSecret(azureAd.Value.ClientSecret)
.WithAuthority(tenantSpecificUrl)
.Build();
// Make a client call if Access token is not available in cache
authenticationResult = clientApp.AcquireTokenForClient(azureAd.Value.ScopeBase).ExecuteAsync().Result;

Azure AAD - Application Proxy to On-Premise Service

I've been trying to call an on-premise Api from another Api in Azure, using Application Proxy. I've followed several examples like the one listed below, with similar results. I can successfully acquire an access token but when I make an http call to on-prem Api via app proxy, I always get redirected to the sign-in page even though I've added an authorization header with bearer token. Anybody have thoughts on what I may be missing?
https://blogs.technet.microsoft.com/applicationproxyblog/2018/06/27/securing-api-access-beyond-intranet-with-azure-ad-application-proxy/
This is the code I'm running that was copied from the referenced example. The one thing I'm not 100% on is the todoListResourceId & todoListBaseAddress. I have them as the same value which is the "Homepage URL" of the configured Application Proxy app.
AuthenticationContext authContext;
private static string aadInstance = "https://login.microsoftonline.com/{0}";
private static string tenant = "xxx.onmicrosoft.com";
private static string clientId = "my app id";
Uri redirectUri = new Uri("http://replyurl");
private static string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
private static string todoListResourceId = "https://xxx.msappproxy.net";
private static string todoListBaseAddress = "https://xxx.msappproxy.net";
private async void GetTodoList()
{
AuthenticationResult result = null;
HttpClient httpClient = new HttpClient();
authContext = new AuthenticationContext(authority);
result = await authContext.AcquireTokenAsync(todoListResourceId, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
// Call the To Do list service.
HttpResponseMessage response = await httpClient.GetAsync(todoListBaseAddress + "/api/values/4");
//MessageBox.Show(response.RequestMessage.ToString());
string s = await response.Content.ReadAsStringAsync();
MessageBox.Show(s);
}

NullReferenceException in Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireToken

I'm trying to get some MSFT Power BI SDK samples working. Unfortunately, the Microsoft.IdentityModel.Clients.ActiveDirectory library is giving me a lot of trouble with the initial external authentication step.
I'm using Microsoft.IdentityModel.Clients.ActiveDirectory, Version=2.28.3.860, from NuGet; this is the last version of the library before AcquireToken was removed, and I haven't figured out how to use its replacement (AcquireTokenAsync) in a way that's equivalent to what I see in the samples.
When I take the following code and modify the TODO lines to specify my actual Azure Client ID and authentication redirect page, I get as far as the AcquireToken line.
using System;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
public class Application
{
public static void Main(string[] args)
{
try
{
string clientID = "abcdef01-1234-1234-abcd-abcdabcd1234"; // TODO: actual Azure client ID
string redirectUri = "https://acmecorporation.okta.com/login/do-login"; // TODO: actual redirect
string resourceUri = "https://analysis.windows.net/powerbi/api";
string authorityUri = "https://login.windows.net/common/oauth2/authorize";
AuthenticationContext authContext = new AuthenticationContext(authorityUri);
AuthenticationResult ar = authContext.AcquireToken(
resourceUri,
clientID,
new Uri(redirectUri),
PromptBehavior.RefreshSession);
string token = ar.AccessToken;
Console.WriteLine("Success: " + token);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
At this point:
A "Sign in to your account" window pops up with the name of the app I've associated in Azure with the clientID GUID
I'm redirected to my organization's ("acmecorporation") sign-on page
I sign in using my AD credentials
The AcquireToken method throws the following NullReferenceExpection:
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.RunAsyncTask[T](Task`1 task)
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.AcquireToken(String resource, String clientId, Uri redirectUri, PromptBehavior promptBehavior)
at PowerBISample.Application.Main(String[] args) in \\noxfile\users\ehirst\documents\visual studio 2015\Projects\PowerBISample\PowerBISample\Program.cs:line 18
Can anyone provide guidance on how to get past this? My goal is to get a POC working to determine whether we can integrate Power BI into a larger application, but so far it feels like I'm beta testing a pretty unstable system.
The NullReferenceException is a bug in the 2.x version of the ADAL library; it's fixed in current versions. It was triggered by an incorrect value of redirectUri; unfortunately the documentation was sparse on this one. A working code sample, adapted (thanks Kanishk!) to use the current 3.13.7 version of ADAL, is posted below.
namespace PowerBISample
{
using System;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Threading.Tasks;
public class Application
{
public static void Main(string[] args)
{
Run();
Console.ReadLine();
}
static async void Run()
{
try
{
string clientID = "abcdef01-1234-1234-abcd-abcdabcd1234"; // TODO: actual Azure client ID
/** THE REAL PROBLEM WAS HERE **/
string redirectUri = "https://login.live.com/oauth20_desktop.srf";
string resourceUri = "https://analysis.windows.net/powerbi/api";
string authorityUri = "https://login.windows.net/common/oauth2/authorize";
AuthenticationContext authContext = new AuthenticationContext(authorityUri);
AuthenticationResult ar = await authContext.AcquireTokenAsync(resourceUri, clientID, new Uri(redirectUri), new PlatformParameters(PromptBehavior.RefreshSession));
string token = ar.AccessToken;
Console.WriteLine("Success: " + token);
}
catch (Exception ex)
{
string error = ex.ToString();
Console.WriteLine(error);
}
}
}
}

Obtaining authorization token from Azure AD with Dotnetopenauth

I am trying to obtain authorization token from Azure AD through DotNetOpenAuth library. I do not want to use ADAL because I have a huge project in .net 3.5 and ADAL does not supports .net 3.5 (only .net > 4). However, I can't quite get it to work with Azure AD. I do not know what to configure. So far, this is what I have:
private static WebServerClient _webServerClient;
private static string _accessToken;
// Client ID (as obtained from Azure AD portal)
private static string clientId = "here goes my client id guid";
// Client Secret (as obtained from Azure AD portal)
private static string appKey = "here goes my secret";
private static string aadInstance = "https://login.microsoftonline.com/{0}";
private static string tenant = "mytenant.domain.com";
private static string authority = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
// Azure AD resource I am trying to access
private static string serviceResourceId = "https://mytenant.domain.com/protectedresource";
private static void InitializeWebServerClient()
{
var authorizationServer = new AuthorizationServerDescription
{
AuthorizationEndpoint = new Uri(""/* WHAT TO PUT HERE */),
TokenEndpoint = new Uri(""/* WHAT TO PUT HERE */)
};
_webServerClient = new WebServerClient(authorizationServer, clientId, appKey);
}
private static void RequestToken()
{
var state = _webServerClient.GetClientAccessToken();
_accessToken = state.AccessToken;
}
static void Main(string[] args) {
InitializeWebServerClient();
RequestToken();
}
The problem is I do not know what to place here. I do not know what values I should place here:
AuthorizationEndpoint = new Uri(""/* WHAT TO PUT HERE */),
TokenEndpoint = new Uri(""/* WHAT TO PUT HERE */)
Check if this GitHub sample assists you with authentication. It has 3 methods for authenticating and acquiring authentication token with detailed instructions. Check the app.config for sample values and method comments for details on what is required.
Link to the sample: Azure Authentication GitHub Sample
Related blog for the sample: Azure Authentication - Authenticating any Azure API Request in your Application
I believe the two endpoints you want are:
https://login.windows.net/{{tenantId}}/oauth2/authorize
https://login.windows.net/{tenantId}/oauth2/token
Where {tenantId} is your tenant's GUID identifier. It may also work with your domain as well, but I haven't checked that.

Azure active directory and owin authentication

Just faced an strange issue with azure ad applicationS and owin openid authentication.
To reproduce the issue.
1.create a web app with azure ad authentication in vs 2015 choosing cloud app template .
2.let the standard code be as is.
3.let startup.auth as is.
4.Run the app on local it works fine.
5.now change code in startup àuth as follows
public partial class Startup
{
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
public static readonly string Authority = aadInstance + tenantId;
// This is the resource ID of the AAD Graph API. We'll need this to request a token to call the Graph API.
string graphResourceId = "https://graph.windows.net";
private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public void ConfigureAuth(IAppBuilder app)
{
ApplicationDbContext db = new ApplicationDbContext();
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
logger.Debug("SetDefaultSignInAsAuthenticationType called");
//app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseCookieAuthentication(
new CookieAuthenticationOptions
{
Provider = new CookieAuthenticationProvider
{
OnResponseSignIn = ctx =>
{
//logger.Debug("OnResponseSignIn called");
////ctx.Identity = TransformClaims(ctx.Identity);
//logger.Debug("TransformClaims called");
}
}
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = Authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
// If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
AuthorizationCodeReceived = (context) =>
{
var code = context.Code;
ClientCredential credential = new ClientCredential(clientId, appKey);
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
logger.Debug("OnResponseSignIn called");
logger.Debug("signedInUserID =" + signedInUserID);
TransformClaims(context.AuthenticationTicket.Identity);
logger.Debug("TransformClaims called");
AuthenticationContext authContext = new AuthenticationContext(Authority, new ADALTokenCache(signedInUserID));
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);
return Task.FromResult(0);
},
// we use this notification for injecting our custom logic
SecurityTokenValidated = (context) =>
{
logger.Debug("SecurityTokenReceived called");
//TransformClaims(); //pass the identity
return Task.FromResult(0);
},
}
});
}
private static void TransformClaims(System.Security.Claims.ClaimsIdentity identity)
{
if (identity != null && identity.IsAuthenticated == true)
{
var usserobjectid = identity.FindFirst(ConfigHelpers.Azure_ObjectIdClaimType).Value;
((System.Security.Claims.ClaimsIdentity)identity).AddClaim(new System.Security.Claims.Claim("DBID", "999"));
((System.Security.Claims.ClaimsIdentity)identity).AddClaim(new System.Security.Claims.Claim("Super","True"));
}
// return identity;
}
}
6.Run the app on local it will work perfect.
7.Deploy the app on azure websites and the startup àuth owin notification methods will never be called.however app works but identity transformation not
Can somebody help out what's wrong with this is azure ad apps doesn't support cookies or notification not firing or anything wrong with code.
Just to re-assert else than startup.àuth no standard code is changed.
I know this is a bit old, but I had exactly the same issue recently and spent hours trying to understand why it wouldn't work in Azure but it worked absolutely fine in my localhost.
This is basically a configuration issue: in portal.azure.com select your app and then go to settings > authentication / authorisation and make sure that app service authentication is OFF.
It turns out that this setting will take over your startup.auth settings.
I have to give full credit to Vittorio Bertocci as pointed that out to me.

Resources