I am developing multitenant web application which is being hosted on azure app service.
It has 2 parts one is backend services which has pure APIs developed using .NET CORE and second is front end which consumes these APIs and is developed using Angular.
We are using Single instance , database per tenant concept where each user will have its own Database.
So there will be a catalog Db , which will hold information about each customer's tenant Id, tenant's Database connection string , customer Id etc.
We do not want to use Azure AD as of now, as our APIs are connecting to different ERPs to validate the user and data.
To achieve multitenancy, we are thinking of 2 ways
Unique Secret Id called TenantKey (for which we will be using some hashing function on TenanatId)
So every time they login, they need to enter this TenantKey along with UserId and password , so we authenticate this user based on that TenantKey and fetch DB connection string based on this.
We validate user by connecting to their own DB using Connection string fetched from CatalogDb.
Once we validate, we generate JWT token and this Connection string of Tenant's own Db is stored as Claim and will be used every time when user calls any API using this token.
This is working fine but
user has to remember and enter this TenanatKey along with UserId and password when they login everytime... which may not be user friendly...
As it is multitenant app, If another tenant gets to know the TenantKey they can access the info provided that they know the credentials(rare but possible)
Custom Domains
As Azure provides way to add custom domains to Azure App service through which we can identify the Tenant and Instead of TenatKey, we will be using this custom domain to find the Connection string in Catalog Db, create JWT token and store as Claim and use it
So question is , is there any way to secure these custom domains so only particular customer can access it? Like in their VPN?
I heard there is limit of 500 domains that can be added to an App service? will there be any way to extend if needed?
We will have load balancer going forward, will this customer domain have any effect on that?
Restrict your multi-tenant app to specific tenant
There are two steps to get started with tenant restrictions.
First, make sure that your clients can connect to the right
addresses.
Second, configure your proxy infrastructure.
To use tenant restrictions, your clients must be able to connect to the following Azure AD URLs to authenticate: login.microsoftonline.com, login.microsoft.com, and login.windows.net. Additionally, to access Office 365, your clients must also be able to connect to the fully qualified domain names (FQDNs), URLs, and IP addresses defined in Office 365 URLs and IP address ranges
For information on how to configure the proxy and the above process, refer here.
Output will be like this after configuring:
Restrict your multi-tenant app to specific users
If an app is secured with Azure AD, it's available to all users who authenticate successfully. But we will have the requirements to restrict access to specific users. This can traditionally be done within the application based on the roles.
Tenant admins and developers can restrict an app to a specific set of users or security groups in the tenant by also using this built-in Azure AD functionality.
Step 1
Log in to the Azure portal as a Global Administrator. In the top Azure bar search for the “Azure Active Directory”.
Step 2
From the properties left pane look for the “Enterprise applications” like below,
Step 3
Look for the AD application which you want, if you don’t find your application then select “All Applications” from the Application Type dropdown and use other filters also to find the application.
Step 4
Once you select the application, select “Properties” in the left menu and enable the “User assignment required” option to “Yes” and “Save” to update this configuration change.
Step 5
Make user assignments: Select “Users and groups” > Click “Add user”.
Step 6
It will direct you to the next page, where you may choose which users have access to the app services made available through this particular Azure AD app authentication.
Now, the user will be successfully authenticated when they attempt to log in to your Azure App Service with any legitimate AD user, but they will only be able to approve the application based on the configurations we just made.
For more information, refer here in Microsoft documentations.
I heard there is limit of 500 domains that can be added to an App service? will there be any way to extend if needed?
Yes, What you heard is correct!
You could try to contact Azure support to increase the limit:
Navigate to your subscription in the Azure Portal
Click on Usage + Quota
Click on Request increase
Select Other Request in the Quota Type field
Fill all other fields of the request
Related
Kick tires around. We want use Azure B2C for identity management for our web application that embeds PowerBI. PowerBi Embedded and the application are on a separate tenant that is used for our organization. Can this still be done?
You could use Embed content for your customers, also known as App owns Data.
User logs in using Azure B2C
Application back-end will verify user log-in and receive user details
Application back-end should generate embed token. This means that you need to understand how to link a B2C user to a report id / role etc. You can do this in your back-end based on metadata or a table lookup.
You can also include the username and roles if you would like to use Row Level Security (RLS).
Users in Azure Active Directory Azure
App Services for WebSite and Services
I am creating a Web Site that a Manager would authenticate with using an Azure Active Directory account. That website would offer up sales data on the staff they manage.
The service that returns the sales data for staff member A will be being called on behalf of the manager.
My question is what is the correct way to flow the "identity" of the logged in manager through the calls to the various services.
Do I simply protect the services with a System Level authentication at the level of the website and pass the manager's user identifier as a parameter in the request?
OR
Do I try and flow the oauth identity onward to the services so that they are called in the security context of the manager? If using this approach how would I do that?
In my opinion, if the your business doesn't have a high security requirement, the first option is great. But if you want higher security, you can use second option.
For second option, you need to register an application in your azure ad for your app service. Follow steps on this page. And register another application in AD to represent client app by following these steps. Then go to your client app and grant permissions to allow the client-app to call the backend-app. After that, the manager need to get access token before request the api in your app server to return sales data.
This Azure sample shows exactly what we want to acheive with an ASpNet Core Web Site calling own AspNet Core Service secured with our Active Directooy organisation
I am having some issues getting it to work but this sampple is what I was hoping for from asking this qeuestion. FWIW here is the seperate question covering the specific issue I am having implementing the sample, Why Http 401 when calling AspNet Core API secured with AAD. Our WebApp, Web API and AD Org
Azure requires multiple IDs to create application ServicePrincipal credentials.
What's the difference between the client id and tenant id?
Why does Azure require separate IDs?
An application ID is the ID of the specific application you have created in Azure Active Directory, you will likely have many applications for different purposes. Each application can have different users assigned access, different criteria for access (MFA, conditional access etc.) and will be configured to authenticate users for different real applications or purposes. Each Azure AD application has a unique ID, and this ID is what you give your application to use to talk to it when processing logins etc.
All of your applications sit within an Azure Active Directory instance, or as MS like to call it, a tenant. The tenant ID identifies which Azure AD instance the application sits under, so Azure knows where to look when you request things using that applicaiton ID.
I suppose in theory if Applicaiton IDs were unique globally then you could work out the tenant from the App ID, but that isn't how MS set it up.
I've utilized the Partner Center REST API to provision tenants with orders/subscriptions. Now I want to start configuring the domains and users for the tenant I just created. My first step was to get a list of users using the Graph API https://msdn.microsoft.com/en-us/library/azure/ad/graph/api/users-operations as a test expecting to see the admin account. If I pass in the domain of the reseller account in the request URL, it shows me the reseller users. But when I put in the domain of the account I just provisioned, I get Invalid domain name in the request url. I'm using the resellers AD token to do this. I'm confused as it gives me the option to specify a domain, but I can only access my own.
What credentials am I supposed to be using here? I tried to use the user/pass that was generated for the admin account from the provision, but I get unauthorized_client when trying to get an AD token from the Graph API.
It is hard to directly address your issues here since they are a little broad, and I would need more specific details about the various tenants you are working with, how your app is provisioned, permissions your app has etc...
However I think there a few principals you can follow which may help you debug your issues.
All AAD Authentication happens within the context of a specific tenant. This means whenever you get an access token for a resource, the scope of that token is limited to the boundaries of the tenant.
To authenticate with a client application in the context of a tenant, you must have the app registered in the tenant you are trying to access (line of business application / single tenant) or you have to make the app multi-tenant, in which case your app should be able to function in the context of any tenant... if the right provisioning has occurred.
Every tenant where your app is trying to function must have a service principal for the application provisioned in the tenant. This service principal represents your application's identity in the context of that tenant, and acts as a place to store the permission your application has in the context of that tenant. Most normally, this service principal gets provisioned into a tenant after a user from that tenant has consented to use the app as a part of the login experience.
If you are trying to use user context (authorization code grant flow) to retrieve details about a tenant, you must ensure that that user is present in the directory you are trying to query. For example a user U can exist in their home tenant T1. If you try to query another tenant T2 using that user account, you will get any number of errors describing that the user account does not exist etc. You can remedy this by creating a guest account for U in T2, in which case there will be a brand new user object created in T2 which links to the original user object in T1. None the less, the user object should always be present in the tenant you are trying to query.
If you are trying to sign into an application with a user account that is in T1 and T2, you need to be sure to specify the tenant you want to actually get the token for. By default, if you use the common endpoint, you will get a token for the users home tenant. However, it is perfectly valid to get a token for the secondary tenant, as long as you specify that to our Token Service when making the request.
Finally the client application you use to make these requests needs to have the right permissions to the Graph API if you want to make specific calls to the Graph API. Every tenant needs to individually consent to the application in their tenant context in order to provision the correct permissions to their application.
With those principals in mind:
The error you are getting with "unauthorized_client" seems to be an issue with application provisioning in the secondary tenant. Please make sure to first login to the application with a user from the secondary tenant, and make sure that user has the correct permissions to consent to your app (a tenant admin is best here).
For the second issue with "Invalid domain name in the request url" please try using some hints here.
Specifically this:
By using the myOrganization alias. This alias is only available when using OAuth Authorization Code Grant type (3-legged) authentication; that is, when using a delegated permission scope. The alias is not case sensitive. It replaces the object ID or tenant domain in the URL. When the alias is used, Graph API derives the tenant from the claims presented in the token attached to the request. The following URL shows how to address the users resource collection of a tenant using this alias:
https://graph.windows.net/myorganization/users?api-version=1.6.
I hope this puts you on the correct path to resolve most of your issues.
There are issues with sandbox accounts and Azure. Access to the Azure Management Portal for the sandbox isn't straightforward and at this time does not work properly. I had to create a free Azure account with my hotmail account, then link AD from the new account to my sandbox AD to bypass the bug. When adding a new directory to the new Azure account, select "Use existing directory", sign out, then sign into the sandbox account you want to link it to. Then create your app from the new account.
After getting my app setup properly and new credentials, I had to enable pre-consent with the instructions listed at the end of: https://github.com/Microsoft/Partner-Center-Explorer
Lastly, I had to login to the Graph API with the customers ID, but with the resellers credentials.
The scenarios on the Partner Center SDK website include a section "Manage user accounts and assign licenses" under the "Manage customer accounts" section.
These samples include creating users and assigning licenses and a link to a console test app.
As an aside, a new version of the Partner Center SDK has just become available here. It was released on July 5th. While there is no official change history that I can find, I can see that it includes some new classes such as CustomerUser. You may find it easier to use that library rather than hitting the REST API (depending on how much work you've already done).
I am currently trying to understand the combination of Azure ACS with Claims-based Auth and the option of using a custom STS and I am only slowly getting through the (unfortunately few) info sources.
Before I spend more hours on this I would like to confirm if my plan is even possible.
I have multiple azure roles (web+worker) that are being accessed over the internet by both employees and customers. Additionally, employees access these roles and desktop apps from inside our local network.
User data comes from two sources. Our azure app has user data about customers and employees, our (local) AD only from employees.
To make the login experience as efficient (and ergonomic) as possible, when accessed via our local network, employees should be automatically authenticated (Windows Integrated Auth?) on both the desktop app (automatically because of Windows User Profile Context) and on the azure apps (hopefully w/o login page).
Customers, on the other hand, should enter their user credentials when accessing the azure app, but should not have to decide between different "Credential-sources", they should just get the username+password form.
In other words
Employee visits Azure app from local network -> Auto-login with Integrated Auth / AD data
Employee visits Azure app from internet -> Username+Password form
Customer visits Azure app from internet -> Username+Password form
While writing this question, two more came to mind:
1) Is it even possible to auto-login based on source/cookie/wizardry or would that require a manual user choice for selecting the "Credential-Source"?
2) If Azure ACS "knows" that AD account with Username X is the same as Azure App User Y, does it matter with which one logins? Can the app access the same claim-data on either login route?
Are you sure you need a custom STS? It sounds like to start you just want to enable your AD users to sign in to your azure applications using their windows credentials if they are on the domain (no password prompt). ADFS 2.0 and WIF will facilitate this. In addition, if you set up an ADFS proxy server so that when those same users browse to your app from outside of the domain they will get prompted for their domain credentials.
Now your AD users are set up, but if you want your applications to be accessible to users outside of your domain, you can federate ADFS with another organization's ADFS server, or use ACS to enable login using consumer identity providers such as Google, Yahoo, and LiveID, which are provided as built in options. If you did introduce ACS like this, you would configure your corporate ADFS server as an identity provider on your ACS instance alongside google, yahoo and what not, so that when your users browse to your site they will be prompted to select which identity provider they wish to sign in with.
Here's a fantastic whitepaper that demonstrates using ADFS to authenticate to cloud applications:
http://www.microsoft.com/download/en/details.aspx?id=13789
More detailed info about deploying ADFS (such as deploying the ADFS proxy) can be found in technet.
And for ACS, there are guides and samples on how to integrate it into azure applications, and how to add ADFS identity providers: http://msdn.com/acs
One thing that you could do is look at the user credentials when a page is requested in order to get the authentication info.
If you look at...
HttpContext.Current.User.Identity
You can get info about the user's identity. If they are on the domain you will see that they have a domain name and you could programmatically choose to direct them to a login page.
Let me also say that I've never tried to do this so I don't know if there's a built in way to do this by simply configuring something in web.config.