Use MSAL without bundle_id configured on Azure AD - azure

My iOS app has to address an application on an Azure AD server, upon which I don't have admin access. I know the client_id, tenant_id and redirect_uri (Azure AD application).
My iOS app's bundle_id is not registered for the required application (msauth.[bundle_id]://auth)
Aim: Get the bearer token in order to access the application directly from my iOS app.
That's the MSAL config:
let kClientID = [client_id]
let kGraphEndpoint = "https://graph.microsoft.com/"
let kAuthority = "https://login.microsoftonline.com/[tenant_id]"
let kRedirectUri = [redirect_uri]
let kScopes: [String] = ["user.read"]
Question: Is it an absolute requirement that the bundle_id is registered in Azure AD for a specific application, or are there other means getting the bearer token using MSAL, knowing client_id, tenant_id and redirect_uri?

Related

Get Access Token from Azure First Party App without user Interaction

We have a First Party App with Delegated Graph API Permission.
We want to get Access Token from this FPA.
As of now we are able to generate token from browser here user need to login in browser to generate token.
Problem: We want to generate token without user interference and want to find a way to get the Token having Delegated Permission on behalf of user also we are using power automate to achieving this functionality.
There is a way of getting access tokens and that is by using MSAL
Here we would need tenet id , client id , username and password and scope. Tenetidand client id can be aquired from the portal after clicking on your registered app.
After that we will also need MSAL which is auth library for azure ad it is available in all language now for example using MSAL for python we can get tokens like this:
client = # client id from app
tenant = # tenant id from app
username = # account username
password = # account password
scope = [ '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d/.default' ]
app = PublicClientApplication( client_id = client, authority = "https://login.microsoftonline.com/" + tenant )
acquire_tokens_result = app.acquire_token_by_username_password( username = username, password = password, scopes = scope )
# acquire_tokens_result['access_token'] this is your tokens
Refer this Ms Documentation on MSAL python

Azure AD, Multi-tenant, App Roles Assignment for users from another tenant

I'm working on web application that contains client side (SPA, angular 9) and backend (WebAPI, ASP.NET Core 3.0). Decided to use Application Roles feature to authorize users in our application. And i have requirement to be able to manage Application role assignments for users from our application UI via MSFT Graph API.
I registered MyAuthApp application in Azure AD TenantA. And created several App Roles there.
Authentication works fine. Client side gets token and attaches it to http requests to backend. Authorization also works fine i can extract app roles from the token and validate them.
Problem with adding Application role assignments for users from other AzureAD tenant -- TenantB. Seems that problem in GraphServiceClient configuration due to GraphApiAuth registered in TenantA.
Question: is this possible to add application role assignment for user from TenantB using GraphServiceClient authorized by Client Credentials in TenantA?
Right now when i do add role assignment i'm getting exception like resource with some Guid not found. This resource is a user (from TenantB).
This is a piece of code that adds user app role assignment. I see possible problem in GetGraphServiceClient function. It uses as authority URL with TenantA Id.
public async Task<AppRoleAssignment> AssignAppRoleToUser(Guid userId, Guid appRoleId)
{
var graphClient = await this.graphClientProvider.GetGraphServiceClient();
return await graphClient.Users[userId.ToString()].AppRoleAssignments.Request().AddAsync(
new AppRoleAssignment()
{
PrincipalId = userId,
AppRoleId = appRoleId,
ResourceId = this.graphAppSettingsProvider.GetAppRoleResourceIdAsGuid()
});
}
df0b3e71-fd2d-41a4-bfa9-0310b31395ae is Id of user from tenantB.
UPDATE:After further investigation i was able to assign App role for user from TenantB. But i had to change settings in the code that returns GraphServiceClient and provide TenantB Id and Application Service Principal Id from TenantB (instead of values from TenantA). But that's a problem. We would like to be able to assign application roles for users from any tenant and it will be not doable if we will have to provide TenantId and Service Principal Id for each tenant separately.
Is it possible to do this some how with some common settings?
This is how i get GraphServiceClient:
public async Task<GraphServiceClient> GetGraphServiceClient()
{
var clientId = this.graphAppSettingsProvider.GetClientId();
var clientSecret = this.graphAppSettingsProvider.GetClientSecret();
var tenantId = this.graphAppSettingsProvider.GetTenant();
var app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithTenantId(tenantId)
.Build();
string[] scopes = {"https://graph.microsoft.com/.default"};
return new GraphServiceClient(
"https://graph.microsoft.com/v1.0",
new DelegateAuthenticationProvider((requestMessage) =>
{
var ar = app.AcquireTokenForClient(scopes).ExecuteAsync();
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", ar.Result.AccessToken);
return Task.FromResult(0);
}));
}
UPDATE 2
Changed a little requirements and now we just need to manage App Roles list for users from current user tenant. So, we changed permissions type from Application to Delegated to be behalf of authenticated user.
As i said earlier we have Angular app in pair with ASP.NET Core WebAPI backend. Angular app gets access token and sends it to backend in Authorizaiton header. When i attach with access token to GraphServiceClient request (header) i'm getting error "Access token validation failure. Invalid audience."
Question: is this correct flow to use access token from client for Graph API requests or should i get new access token for Graph API at backend using access token from client?
Any help/ideas appreciated. Thanks in advance!
First, you need to set up the MyAuthApp application as a multi-tenant application.
Next, run admin consent url in the browser, and then you need to log in with another tenant's administrator account and consent. The multi-tenant application will then be added to the target tenant as an enterprise application. https://login.microsoftonline.com/common/adminconsent?client_id={client-id}.
At the same time, the app role you created in tenant A will also be synchronized to the target tenant (for example, tenant B). Next, you only need to grant the app role of MyAuthApp to the users of tenant B through the Azure portal of tenant B or use ms graph api.

Get bearer token with MSAL.NET to access App Service with EasyAuth

I have an Azure App Service which is authenticated using Azure AD EasyAuth.
I am trying to send a request from another App Service using C# and MSAL.NET (Microsoft.Identity.Client).
The authentication code looks like this
var app = ConfidentialClientApplicationBuilder
.Create(config.ClientId) // The Client ID in the App Registration connected to the App Service
.WithClientSecret(config.ClientSecret)
.WithAuthority(new Uri(config.Authority)) // https://login.microsoftonline.com/tenant.onmicrosoft.com/v2.0
.WithTenantId(config.TenantId) // Tenant Id Guid
.Build();
// Used Scopes: ["https://graph.microsoft.com/.default"]
var credentials = await app.AcquireTokenForClient(config.Scopes)
.ExecuteAsync(cancellationToken);
I get a bearer token successfully, but when I try to call the App Service with token injected to the headers I get a 401 and You do not have permission to view this directory or page. :(
Update 1:
I tried #Jim Xu answer and it's still giving me 401. It returns a www-authenticate header with the following value
The resource id is the same ClientId in the App Reg
Update 2 - Solution
So to summarize the fix:
The requested scopes when calling AcquireTokenForClient should include {Application ID Uri}/.default
In EasyAuth configuration, the Allowed Token Audiences needs to be set to the Application ID Uri as well
If you want to call the Azure API app which enables easy auth, please refer to the following steps
Get the Application ID URI of the AD application you use to enable easy auth
a. In the Azure portal menu, select Azure Active Directory or search for and select Azure Active Directory from any page.
b. Select App registrations > Owned applications > View all applications in this directory. Select your web app name, and then select Overview.
code
var app = ConfidentialClientApplicationBuilder
.Create(config.ClientId) // The Client ID in the App Registration connected to the App Service
.WithClientSecret(config.ClientSecret)
.WithAuthority(new Uri(config.Authority)) // https://login.microsoftonline.com/tenant.onmicrosoft.com/v2.0
.WithTenantId(config.TenantId) // Tenant Id Guid
.Build();
// Used Scopes: ["{Application ID URI}/.default"]
var credentials = await app.AcquireTokenForClient("{Application ID URI}/.default")
.ExecuteAsync(cancellationToken);
For more details, please refer to here.

Get a Power BI access token after logged into Azure AD

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.

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.

Resources