Get a Power BI access token after logged into Azure AD - azure

I have code that logs me into Azure AD, but I cant' figure out how to get the access token to call the REST API's or PowerBI

There is the sample code to get access token for Power BI REST API.
//The client id that Azure AD created when you registered your client app.
string clientID = "{Client_ID}";
//RedirectUri you used when you register your app.
//For a client app, a redirect uri gives Azure AD more details on the application that it will authenticate.
// You can use this redirect uri for your client app
string redirectUri = "https://login.live.com/oauth20_desktop.srf";
//Resource Uri for Power BI API
string resourceUri = "https://analysis.windows.net/powerbi/api";
//OAuth2 authority Uri
string authorityUri = "https://login.microsoftonline.com/common/";
// AcquireToken will acquire an Azure access token
// Call AcquireToken to get an Azure token from Azure Active Directory token issuance endpoint
AuthenticationContext authContext = new AuthenticationContext(authorityUri);
var token = authContext.AcquireTokenAsync(resourceUri, clientID, new Uri(redirectUri)).Result.AccessToken;
Console.WriteLine(token);
For more details, see here.

Related

How does silent access token work for azure b2c

I would like to understand the authentication process for Azure B2C. It is my understanding that up to 50k authentication per months are free and you pay more if it goes over 50k.
I am developing two applications. One for front-end and another for back-end that will use Azure B2C to authenticate users.
Here is my scenario.
Users will go to UI portal to login with their social accounts.
Users can access back-end resources by making API call based on their permissions.
So it is my understanding that when you login to UI using your social account you receive an access token, which is one authentication in B2C. If they want to access back-end resources from API, it requires you to acquire access token by making another request as shown here. Below is the example code that acquires token silently.
// Retrieve the token with the specified scopes
var scope = AzureAdB2COptions.ApiScopes.Split(' ');
string signedInUserID = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new MSALSessionCache(signedInUserID, this.HttpContext).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(AzureAdB2COptions.ClientId, AzureAdB2COptions.Authority, AzureAdB2COptions.RedirectUri, new ClientCredential(AzureAdB2COptions.ClientSecret), userTokenCache, null);
AuthenticationResult result = await cca.AcquireTokenSilentAsync(scope, cca.Users.FirstOrDefault(), AzureAdB2COptions.Authority, false);
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, AzureAdB2COptions.ApiUrl);
// Add token to the Authorization header and make the request
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpResponseMessage response = await client.SendAsync(request);
My question is, when login in to UI using your social account and accessing back-end resources with another silent request. Does it count as 1 authentication? Or it counts as 2 authentication in Azure B2C?
After your web application handles the authentication response, the ConfidentialClientApplication.AcquireTokenByAuthorizationCodeAsync method retrieves the access token from Azure AD B2C and then writes it to a token cache, which is implemented by the MSALSessionCache class.
Before your web application invokes your web API, the ConfidentialClientApplication.AcquireTokenSilentAsync method reads the existing access token from the token cache and only requests a new access token from Azure AD B2C if:
The access token doesn't exist in the token cache;
It is about to expire; or
It has expired.
If the existing access token is read from the token cache, then you aren't charged for the issued token.
If a new access token is requested from Azure AD B2C, then you are charged for the issued token.

Authenticate Azure Function by Token with Resource

I have an Azure Function with Authorization/authnetication enabled via AD log in.
I am trying to authenticate by generating a token using client_credentials:
Refer to the following code below:
var tokenendpoint = "https://login.microsoftonline.com/172f05a2-f956-4856-b4c8-9580a54dbd56/oauth2/token";
string clientID = "eaeff78a-26ef-4bcb-b977-638316ff15b7";
string clientSecret = "HvVlipQkpuezmD4YiUcWVpZ5Cn1cP3vxiW61pSpDo8k=";
string resource = "eaeff78a-26ef-4bcb-b977-638316ff15b7"; //ClientID
string grantType = "client_credentials";
using (var reqToken = new WebClient())
{
NameValueCollection parameters = new NameValueCollection();
parameters.Add("client_id", clientID);
parameters.Add("client_secret", clientSecret);
parameters.Add("resource", resource);
parameters.Add("grant_type", grantType);
var responseTokenBytes = reqToken.UploadValues(tokenendpoint, "POST", parameters);
string responseTokenContent = Encoding.UTF8.GetString(responseTokenBytes).Replace(#"\", "");
azureFunctionTokenResponse = responseTokenContent.Deserialize<AzureFunctionTokenResponseBase>();
AzureFunctionToken = azureFunctionTokenResponse.access_token;
}
All works fine if I set the resource as the ClientID of my function.
However, in many examples online the Resource is set to the Azure Function Uri.
If I set my Resource to https://www.xxxxxx.azurewebsites.com then I get a 401 error.
Why is this?
I spent a whole day in getting this to finally work but nowhere in the docs does it say to enter the ClientID as the Resource??
If you use the same AAD app to enable Authorization/Authentication for your Azure Function and your client code to acquire the access_token for accessing your Azure Function, you could specify the resource to the Application ID (ClientID) or the App ID URI of your AAD app.
In general, we would use the ClientID as the resource, and App Service Authorization/Authentication would compare the Client ID you configured under Authentication / Authorization > Azure Active Directory Settings with the aud property of the incoming JWT bearer token, you could leverage https://jwt.io/ to decode your token.
However, in many examples online the Resource is set to the Azure Function Uri.
If I set my Resource to https://www.xxxxxx.azurewebsites.com then I get a 401 error.
I assume that those samples may use the App ID URI, you could set the App ID URI to https://www.xxxxxx.azurewebsites.com for your AAD app (Settings > Properties > App ID URI), then you could use App ID URI for the resource parameter.
Note: For this approach, you may need adjust the Azure Active Directory Settings for your Azure Function, you may keep the Client ID to the Application ID of your AAD app and add App ID URI to ALLOWED TOKEN AUDIENCES list or you could just replace it with your App ID URI.
Additionally, you could ADAL library for acquiring the token. Also, if you create each AAD app for your Azure Function and your client app, you could follow this issue.

AZURE AD ADAL "error":"invalid_grant","error_description":"AADSTS70000: Transmission data parser failure: Authorization Code is malformed or invalid

I am trying to Authenticate using AZURE AD. I took the java client code from the git [https://github.com/Azure-Samples/active-directory-java-webapp-openidconnect][1].
I am able to make the authorize call and get the Authorization code. By passing the authorization code to get the access token using the acquireTokenByAuthorizationCode method from the oauth2 jar. Here I am getting the below error.
"error":"invalid_grant","error_description":"AADSTS70000: Transmission data parser failure: Authorization Code is malformed or invalid.
How to pass the grant_type=authorization_code to the acquireTokenByAuthorizationCode method?
How to check the post request which got fired? I am not able to see it in the network section of the chrome?
Below is the code:
String authCode = authorizationCode.getValue();
ClientCredential credential = new ClientCredential(clientId,
clientSecret);
AuthenticationContext context;
AuthenticationResult result = null;
ExecutorService service = null;
try {
ThreadFactory factory = ThreadManager.currentRequestThreadFactory();
service = Executors.newCachedThreadPool(factory);
context = new AuthenticationContext(authority + tenant + "/", true,
service);
Future<AuthenticationResult> future = context
.acquireTokenByAuthorizationCode(authCode, new URI(
currentUri), credential, null);
The post request should be:
String redirectUrl = authority
+ this.tenant
+ "/oauth2/v2.0/token?p=b2c_1_abcd&grant_type=authorization_code&resource=https%3a%2f%2fgraph.windows.net&redirect_uri="
+ URLEncoder.encode(REDIRECT_URL, "UTF-8");
Not sure how to provide the information which is in bold.
EDIT after more info
If you are using v2 endpoints, you can't use ADAL.
If you have registered your app in the v2 dev portal, you need to register your app via Azure Portal's Azure AD interface. And then make sure your Azure AD URLs do not include v2.0.
To get a token with authorization code, you use acquireTokenByAuthorizationCode (https://github.com/Azure-Samples/active-directory-java-webapp-openidconnect/blob/master/src/main/java/com/microsoft/aad/adal4jsample/BasicFilter.java#L268-L270):
Future<AuthenticationResult> future = context
.acquireTokenByAuthorizationCode(authCode, new URI(
currentUri), credential, null);
You will not see the request in Chrome because it goes from your web server to Azure AD. The browser is not a part of the chain. And that's a good thing since we are passing the client secret to Azure AD. You can use tools like Fiddler to monitor the traffic.

Azure AD OpenId Connect Token Authentication

I am stuck with Azure Active Directory OpenId.
I Have a ReactJs Web Client that does Authentication to Azure AD, When signed in a token_id is return representing a JWT token. This will be passed back to a ASP.Net Core Web Api and then Authenticated with the JwtSecurityTokenHandler in System.IdentityModel.Tokens.Jwt.
This is wired up with the Middelware when the application starts. When you access the OpenIdConnectOption Events on TokenValidated call, the token is validated already in the back end. A TokenValidatedContext get passed in to the Event Method which contains the JwtSecurityToken and I have access to the whole JWT Token.
I created a separate validation service that takes in the token string.
public ClaimsPrincipal ValidateToken(string token)
{
SecurityToken validatedToken;
var sectoken = TokenHandler.ReadJwtToken(token);
var tokenValidationParams = new TokenValidationParameters()
{
ValidAudiences = sectoken.Audiences,
ValidIssuer = sectoken.Issuer,
};
return TokenHandler.ValidateToken(token, tokenValidationParams, out validatedToken);
}
Is that the SigningKey object is null and the ValidateToken fails. If I do the same validation in the Event call then the SigningKey is valid and the cert is set to Microsoft Cert that seems to be issues by the Azure AD Service.
The main objective is to have a separate Token Validation Service.
Thanks in advance.

Configuring ASP.Net application to support muliti tenant using Azure AD account

I created an ASP.NET MVC application and configured authentication with Azure AD using OpenIDConnect. I created a user in one Azure AD and added the same in another Azure AD with right privilege.
I store the claims returned after the Azure AD authentication, in ADAL cache. I use this claim(token cache)to call various Azure Service Management API.
ClientCredential credential = new ClientCredential(ConfigurationManager.AppSettings["ida:ClientID"],
ConfigurationManager.AppSettings["ida:Password"]);
// initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's EF DB
AuthenticationContext authContext = new AuthenticationContext(
string.Format(ConfigurationManager.AppSettings["ida:Authority"], organizationId), new ADALTokenCache(signedInUserUniqueName));
AuthenticationResult result = authContext.AcquireTokenSilent(ConfigurationManager.AppSettings["ida:AzureResourceManagerIdentifier"], credential,
new UserIdentifier(signedInUserUniqueName, UserIdentifierType.RequiredDisplayableId));
var token= result.AccessToken;
I have configured my application to support multitenant by adding the following in my Account/SignIn controller/action.
public void SignIn(string directoryName = "common")
{
// Send an OpenID Connect sign-in request.
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Environment.Add("Authority", string.Format(ConfigurationManager.AppSettings["ida:Authority"] + "OAuth2/Authorize", directoryName));
HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
Now, upon successful signin, the claims that are returned, belong to the original Azure AD in which the user is initially registered in. Thus, the claims used to call management api for any other Azure AD, in which the user is also added, does not work and throws exception as "Acquire Token failed to obtain token".
I added the name of the other Azure AD to the variable "directoryName" on runtime. This time the claims obtained worked for both the Azure AD.
How to get the SSO for multitenant application, without explicitly mentioning the Azure AD name while signing-in, which will provide me with the claims that can work for all the Azure AD in which the user is registered.
Kindly suggest.
Thanks in advance,
Rahul
I am not sure what your parameter signedInUserUniqueName is, I often write like this to get accesstoken:
AuthenticationContext authenticationContext = new AuthenticationContext("https://login.windows.net/" + Properties.Settings.Default.TenantID);
ClientCredential credential = new ClientCredential(clientId: Properties.Settings.Default.ClientID, clientSecret: Properties.Settings.Default.ClientSecretKey);
AuthenticationResult result = authenticationContext.AcquireToken(resource: "https://management.core.windows.net/", clientCredential: credential);
var token = result.AccessToken;

Resources