I have and AngularJS application that talks to WebAPI. Both login using Identity Server 3. I have an Admin role, but I want to expand on this so I can hide certain admin functionality in the front end from some admin users. So I need to check user permissions for admin users. What's the best way to do this? Do I just create a table in my database and assign permssions to users there? Or is there something in identity server I should do to assign permissions.
It's my understanding that application permissions would be tracked in your application specific database. In that database, you could track permissions by role (rather than user). Then, you could use the role claim(s) that come back in the token to look up the proper permissions. However, that's just one method...
This is a really great post on the subject written by Dominick Baier, one of the authors of Identity Server: Identity vs. Permissions
Related
I'm adding an external identity provider, Azure multi-tenant, as a login option. I have local accounts right now and they know nothing about Azure AD users.
I want to create an Azure Enterprise App that other tenants can use to set up SSO using OpenID Connect. Also I want the app to support User Provisioning by setting up a SCIM API.
I can't really find any documents on how to handle linking Azure AD users with the existing accounts in my IDP. I've seen examples where users can login using their local account, authenticate with Azure, and then their local account is updated to have the Azure AD User ID. This approach still seems pretty manual. Another thought was to have a step in the login journey, where if no local account has the Azure AD User ID then find a local account with the same email. I don't like this approach either since the emails might not always match. Is there an approach where an admin can automatically link all accounts with a sync or upload?
SYSTEMS
First it's worth clarifying roles:
Role
Details
Authorization Server (AS)
Your UIs and APIs receive tokens from this. It is where accounts and linked accounts are stored. It is where you use SCIM to update account records. It is where you apply account linking logic.
Identity Provider (IDP)
There can be multiple of these. When your apps call the AS it manages connections to them, and exchanges IDP tokens for AS tokens that are returned to apps. It is not usual to use SCIM against an IDP.
You are using IdentityServer as the AS so your UIs and APIs will continue to use IdentityServer tokens and remain simple. Meanwhile Azure AD will become an alternative IDP. So on the data side of things your architecture is in a good place.
AUTHENTICATION ACTIONS
I would aim to solve your problems via custom authentication actions, and to design this in a vendor agnostic way. Not all providers support these concepts, but IdentityServer has some pretty good extensibility features, so hopefully it has what you need.
A bit of code, configuration and technical investigations in IdentityServer feel like the correct direction, with no complexity added to your applications. I will describe techniques in terms of Curity (where I work), but the same principles can apply to any system.
USERNAME AUTHENTICATOR
A great way to deal with user specific differences is to make the initial screen prompt only for an email. See this example for how that looks. Later, when authentication has completed, you could set a cookie so that this screen is not shown on subsequent logins.
Then, before asking for credentials, apply some scripted logic, eg to look up existing account attributes, and decide how the user should authenticate. You might decide to route unknown users to Azure AD or do something based on business partner email suffixes.
DATA UPDATES
Something simple that might work in advance of adding Azure AD support is to assign all users a Tenant ID, and perhaps existing users get a Tenant ID of 1. Only those users are allowed to sign in with Identity Server - all others have to use Azure AD.
SCRIPTED LOGIC AND ACCOUNT LINKING
For a worked example of how this looks, see this Account Linking with Facebook tutorial. In this example the objective is to update the main account with a new linked account. This account linking doc may give you some additional ideas for your scenario. It should be possible to run custom logic before triggering authentication or once your have the Azure IDP attributes.
INVOLVE THE USER IF NEEDED
It may also be useful to present a custom screen to ask the user if they have an existing account when they first login via Azure AD. If not then an Azure AD login can create the primary account in IdentityServer data in addition to a linked account.
USERS AND PARTNERS
How users onboard is interesting, and discussed in this detailed article. I always start by getting a feel for the type of assets involved:
Type
Description
Personal Assets
You allow any user to sign up and they only have access to their own assets
Corporate Assets
Users are provisioned by an administrator, eg a banker is granted access to financial data according to business rules
In your case it feels like users are from the second category, so to enable a user to fully sign up you need data from the partner, either fed in manually or by getting them to call your API, before you can assign the user the correct tenant ID. This might eventually result in TenantID=23, but there is nothing to stop you initially allowing users to onboard and placing them in a default TenantID=0 bucket.
Ultimately this all comes down to data, claims and API authorization. Eg APIs could return certain data to TenantID=0 users but only return privileged data to users whose tenant ID has been asserted by an administrator. Not sure if these thoughts of mine match your scenario but hopefully they provide a useful hint or two.
SUMMARY
Reliable account linking is tricky, but it should be solvable via the building blocks of the Authorization Server, using the above techniques. The end result should be deterministic user data, with no duplicate users.
I am doing login from Azure AD.Client is SPA(angular using MSAL). If user is not Authenticated, it redirect to Microsoft Login Screen (using MSAL). On successful login, it return an access token.
My roles will be stored in a database. I need to add the roles of that user as part of claim in access token. I am not finding the way to do it.
I do not want to make another call from SPA to API to get the DB roles.
Please suggest some good approach.
Any links explaining the approach will also be very helpful.
I am still in design phase but not able to find the best approach.
In one microsoft site, i found that we can fetch the roles from DB but details were not there.
most of the places, it is written that we need to provide roles in Azure AD users menifest file.
In regular Azure AD, the "roles" claim is exclusively sourced from app role assignments for the signed-in user (or groups the user is a member of), to the app roles for the app the user is signing in to.
There's no feature currently in Azure AD which will connect to an arbitrary database, make a database query in the appropriate form, and include the results in the roles claim in the resulting ID Token.
I can think of three options to achieve your scenario:
After sign-in, call an API to retrieve the roles. Though you mention this is not desirable, it's probably the simplest approach, so it's worth listing. As a result of the user's sign-to you app, you app will usually obtain an access token to an API. If you set up your API to be secured with Azure AD (directly, or through Azure API Management), your SPA could simply get the necessary access token as part of sign-in, and at that point it's trivial to make a REST call to retrieve the role details for the user (and possibly other information useful to rendering your app).
Synchronize (or copy) your role information from your database to Azure AD. For each role, create an app role in the Azure AD app registration. For each user-role association, either create an app role assignment to directly assign the user (user -> app role), or assign a group to the app role and add the user to the group (user -> group -> app role. Keeping this in sync is probably not trivial, so if your scenario allow to move the role information to Azure AD app role assignment, you can forget the database entirely (making Azure AD the authoritative location). Of course, this might not work for your specific case.
Use Azure AD B2C and a custom sign-in policy. You could create an Azure AD B2C tenant, set up a custom sign-in policy to use your (regular) Azure AD tenant as the identity provider, and configure the policy to enhance the claims by calling a REST API to retrieve your roles. In this approach, you still need to have a REST API which can provide the role information, so rather than doing the setup and migrating your app, you may prefer simply calling the API from your SPA (option 1, in this list).
I have a Xamarin app that uses Easy Table and uses "Allow anonymous access", this means anybody can access my Easy Table as long as they have the URL. So to increase the security of my app, I would like to allow only my Xamarin app to access the Easy Table I created.
Can this be done by changing the Easy Table option from "Allow anonymous access" to "Authenticated"? And if this is the case should I create an account in Active Directory/Facebook/Google and have the username/password embedded in my Xamarin app such that it can authenticate first before accessing the Easy Table?
Note, I have my own user authentication based on user email address and password and it is working okay, but this is on an application level authentication only(i.e., if users provides correct email address and password, they are able to order, view history, etc.). This obviously will not prevent other apps in accessing my Easy Tables as this authentication uses the Easy Tables in the first place.
Thanks everyone!
I'm building a small CRM SPA application using Angular 2 (front-end) and Web API 2 as back-end with ASP.Net Identity and OWIN for token based authentication.
I've got ASPNetUsers, ASPNetRoles and I'm able to grant access to users based on roles but I don't understand how to grant access to a certain user. For example:
a user logs-in with role 'Manager' and loads a page that makes a request for some resource that belongs to this Manager. This request reaches an API controller. How this controller method will know whether to grant access to this user or not? Is this user the owner of a ..say some Client. /api/Client/1
Is there a simple way of finding out (with EntityFramework) up the hierarchy of relations if a Client (or another resource) belongs to a current ASPNetUser or not?
This is how I plan the db relations will look like:
In the end the goal is to give user access to resources that he owns, and restrict other users to load them - sort of a personal account.
Is there a way to prevent users from logging into their own AAD tenants? For example, allow login to contoso.onmicrosoft.com but not fabrikam.onmicrosoft.com.
My customer has a highly-controlled Azure environment where they are running some servers and PaaS/SaaS applications. Users connect to those servers are use a variety of Azure services and some SaaS (primary concern is PowerBI). They’re concerned that a user could login with a non-company account (wahid#hotmail.com) and then upload sensitive data their own PowerBI workspace.
You cannot prevent a user who has already been in the tenant to login to that AAD tenant, except deleting the user from that tenant.
If one account was created/invited to one tenant, the user just can login to that tenant.
For the scenario you described, I suggest you could revoke the Product license for those users. If you don't assign product license to the user, the user cannot use that App or cannot see that app in My Apps panel. For other SaaS/PaaS app(Web App), you may use user assignment to allow specific users to access the App.
For others: Daniel answered this for me. Short answer, this isn't easy, you would need to inspect the response body for the tenant ID (or name) and then block it. This would also lead to a poor user experience but that's all we can do today.
Yes, you have a few options.
Option 1: Single tenant apps
If you have the ability to create apps in the tenant you want to accept users from, you can mark your app as available to only this tenant (the field is called availableToOtherTenants). This will notify the token service to only authorize access from users in the tenant the app was created in.
Option 2: Multi-tenant app w/ token validation
The other option is to mark your app as multi-tenant (same field as above, just set to true) and implement logic in your app to validate the user's tenant from which the token was issued.
In this scenario, you will need to have some kind of web service that can safely validate access tokens (.NET code sample on this). To check the tenant the user's account belongs to, you'll need to validate the iss field. It'll look something like this,
"iss": "https://sts.windows.net/7fe81447-da57-4385-becb-6de57f21477e/"
in which the GUID represents the tenant ID. This allows your web API to have an allow or deny list based off tenant IDs.
More help
Here's an excellent blog post on token validation.
Azure AD Developer Docs
.NET Web API Code Sample