How to impersonate logged in user to manage other Azure service - asp.net

I have webapp to make changes in ADF (kinda deployment of objects in ADF). I want to authenticate user against ADF. I am able to detect who is accessing web app. I get Azure AD Id like user1#company.com. I want to validate if the same user has access to ADF and if yes, generate bearer token to make changes in ADF (using rest api) or using SDK.

You can use the way below to get the access token when the user login to the web app, no need to validate if the same user has access to ADF, because if he does not have the access, the token will not be able to call the rest api, he will get the 401 unauthorized error.
1.First, make sure you have configured your web app to use Azure AD login, then navigate to the resource explorer -> find your web app -> add ["resource=https://management.azure.com"] to additionalLoginParams like below -> PUT.
2.Navigate to the Azure Active Directory in the portal -> App registrations -> find the AD App corresponding your web app -> API permissions -> add the permission user_impersonation of Azure Service Management like below.
3.Then when the user login the web app, after he consents the permissions, you can get the token with endpoint https://webappname.azurewebsites.net/.auth/me, and use the token to call the data factory rest api.
4.Make sure the user has an RBAC role e.g. Contributor in your subscription/ADF, then the token will be able to call the rest api successfully.
For example, I test with Pipelines - List By Factory api, it works fine.

Related

Azure AD B2C with ASP.NET Web API issue token for both authentication in Web API and accessing MS Graph API

I'm new to ASP.NET and Azure AD B2C in general. My goal is to create ASP.NET 5 application which will be accessible through react-frontend with MSAL library. On frontend I have successfully issued both access and id tokens to authorize in my application without any problem, and they are accepted by ASP.NET backend and authorize user requests. I've encountered problem as soon as I tried to access user in current context of request on Back-end. This token does not simply allow me to call MS Graph API https://graph.microsoft.com/v1.0/me with token that I get, to get data about user. The error I get is
{
"error": {
"code": "InvalidAuthenticationToken",
"message": "Invalid x5t claim.",
"innerError": {
"date": "2021-11-29T15:48:41",
"request-id": "91b63eeb-0346-4ab2-9d31-ca58e8d1e30b",
"client-request-id": "91b63eeb-0346-4ab2-9d31-ca58e8d1e30b"
}
}
}
After additional research I found out that tokens that are used for authentication for Back-End are not usable for retrieval of user data from AD B2C or Graph API, since currently AD B2C does not support "on-behalf-of" flow.
How can I implement authentication flow where I still use AD B2C as authentication provider and user data provider for my application ? Additionally, in future, I want enable users to store their own secrets in Azure Key Vault, which can be done only, as far as I understood, via Graph API.
You can secure your app and API using the B2C tokens, then have the API itself generate its own token to access Graph API. The MS Docs have instructions for how to set your app up to get access without a user.
In your case your app would take the user's ID from the user-specific access token it was passed, then use it's own access token to make a call to https://graph.microsoft.com/v1.0/users/<useridfromtoken> to get the user's details.
If the information you need is stored in the B2C directory but not returned in the token, and you don't want to give your app access to the entire directory via Graph, then another option is to implement a userinfo endpoint.
If you want users to store secrets in Key Vault (assuming this is some function of your API) then you need to be looking at the .NET Key Vault secret client library.

Multitenant app issue accessing graph api

I have a multitenant application js client with masal and Web Api all is working good. User can log in and use the Api.
I'm trying to read the ad groups user belongs to with Graph Api.
It works fine for the user on the same tenant where the app has been registered but if I'm using user from different tenant I have 403 (Insufficient privileges to complete the operation.) error, trying to access /users/{userId}/memberOf endpoint.
After I registered applications on azure for client and server I set the appropriate permissions in Api permission section (Application permission) which I thought is the case but it must me missing something else.
Any idea what I'm missing?
Please refer to aricle below :
Understand user and admin consent
For a multi-tenant application, the initial registration for the application lives in the Azure AD tenant used by the developer. When a user from a different tenant signs in to the application for the first time, Azure AD asks them to consent to the permissions requested by the application. If they consent, then a representation of the application called a service principal is created in the user’s tenant, and sign-in can continue. A delegation is also created in the directory that records the user’s consent to the application.
Your application uses permissions(/users/{userId}/memberOf) that require admin consent, if an ordinary user tries to sign in to an application that requests a delegated permission that requires administrator consent, your application receives an error.
In Azure AD V2.0 , you can redirect the user to the Microsoft identity platform admin consent endpoint:
// Line breaks are for legibility only.
GET https://login.microsoftonline.com/{tenant}/v2.0/adminconsent?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&state=12345
&redirect_uri=http://localhost/myapp/permissions
&scope=
https://graph.microsoft.com/calendars.read
https://graph.microsoft.com/mail.send
See document : Admin consent on the Microsoft identity platform

Authorize request going from Resource App to Identity App

I have 2 ASP .Net projects each with its own database:
Identity App: acts as an authorization server with its own database that contains user info. Uses identity 4: Oauth 2.0 and OpenId (code flow)
Resource App: Api that returns access to multiple resources. (database doesn't include anything about users)
Our front end communicates with the resource app mainly and uses the identity app for authorization. Now we are developing the functionality to add a user from the front end and to get all the users.
My questions:
Should the frontend communicate directly with the Identity App to get the users?
If not, how can I get the user info through the resource app?
I tried the following flow for adding a user but it didn't work:
Frontend posts user to resource API (Note: the user is already
authenticated using the authorization server)
I use the authorization header in that request to build a rest sharp request
to the authorization server
The authorization server isn't recognizing the bearer token
I'd recommend storing the majority of user data in the resource app's database.
Over time this will contain lots of fields that are nothing to do with OAuth, such as app specific preferences.
Meanwhile you also need to store a few fields related to login in the identity app: name, password etc.
My write up may help you to understand the separation and achieve your goals: https://authguidance.com/2017/10/02/user-data/

Headless authentication with Azure AD (user/pass combination)

I'm following the guide and example provided by Microsoft here and I'm able to get the demo working, with the authentication happening in a console app, then making a request to a Web API with the correct token.
I'm looking to use this but the code in the console app would need to move to a Web App. Essentially: external server tries to access secure Web API, providing Azure AD username/password in the Authentication header of a HTTPS request. I pick up these credentials in the first insecure Web API, and attempt to authenticate the credentials against AD, obtaining the token. From here, I would then call the [Authorize]-protected Web API by making a request with the AD token.
At this point I'm using the same code from the example linked above, simply moving the code in the Console app up into the first insecure Web API controller, but I'm having no luck. I read on CloudIdentity that "You can only use those flows from a native client. A confidential client, such as a web site, cannot use direct user credentials.". Is this true? If so, is there another way to achieve my aim? I need to use the credentials as it may be likely that more services would use the API in the future, so each of these would need their own credentials to use that could be managed within Azure.
EDIT: In reading more around this, should I actually be aiming to use Client authentication, creating an "Application" within the Azure AD, and providing the client ID to each external service looking to call the API, to then authenticate with that, rather than credentials?
Yes, your edit is correct. The Resource Owner Password Credentials grant is meant to authenticate users, not applications. Typical use would be from an application that prompts you for username and password and then retrieves a token from Azure AD.
You can use the Client Credentials grant to get a token from Azure AD from a confidential client to call an API without user context. This flow requires that you register the application in Azure AD and generate a key (which will be used as the client secret). You can then use the ADAL library to ge a token from AAD as shown here.

Web API not recognizing new users when created by Web Portal

I have a Web API and an Azure Web App that access the same database. This database has all user information. I'm using ASP.NET Identity for user management. I'm having an issue where when a user is created by the web app the Web API requires a restart, or at least a relatively long while before the user becomes authenticated by it. This, of course, is entirely impractical. How can I update the environment immediately on the Web API so that the user can access their resources?
UPDATE 3:
Turns out it WAS authenticating with the API, but I didn't hold the correct claims because my user was not associated with a Google account. See Answer below.
Wow. Nevermind. We require Google accounts to sign on one kind of client, and we SHOULD require it on the web client, but I haven't set that up yet. If an account is set up without an associated Google account, AND that email has a Google account set up on the client then it will try to authenticate with those Google claims that don't exist in the DB. So while I CAN authenticate with that claim through the Google SSO, there are no claims set up in the DB, resulting in 401 errors. Authenticated, but unauthorized.
This means my auth filter is probably misconfigured because it should not authenticate with Google if my account does not have an associated Google account, no matter what my client requests. It also means that I need to refactor my SPA on my Web App that statically calls for Google authentication with the API.

Resources