I can check user in active directory, if he exist then I give him permission to open app window, but what if an application has many levels of permission? Do I create special groups of permission in active direcotry and check if user belongs to one of them? . Can application log in automaticaly, or there is always need to enter password?
Active Directory can fulfill two related but seperate functions for an application: Authorization and Authentication.
Authentication is validating that the person using your application is a valid user. If you have the user's credentials (i.e. the application prompts the user for their username and password), you can authenticate them against AD by attempting a connection using their username/password.
Authorization is what lets you determine the level of permissions a particular user has in your application. Active Directory groups are a relatively straightforward and flexible way to implement the various permissions levels. Typically, I will create very fine-grained permissions groups that represent each securable action users can perform in the application (i.e. CanDeleteWidgets, CanAddWidgets, CanEditWidgets ). Then create functional or role groups where you place the users for that role (i.e. Managers, Coordinators, Technicians, etc). Finally, you just nest the role groups into the permissions groups so if, for example, the business requirement is that Managers can delete widgets, you would add the Managers group as a member of the CanDeleteWidgets group. While this may seem more complex, it makes it extremely simple to respond to changing business security requirements (i.e. "Technicians need to be able to delete widgets" - Piece of cake. Add the Technicians role group to the CanDeleteWidgets permissions group and you're done).
As far as logging in automatically, yes, there are a number of ways you can automatically log in a user. For winforms apps, you should just be able to grab the currently logged in user and use that. For web apps, if you can use integrated authentication, you end up with the same thing. Your web server will handle the authentication piece and send over the DOMAIN\USERNAME of the user in a server header variable.
Related
Is it just me who's finding AD group is very complex? ;-(
I have a web service that only allows a certain number of role groups to have access. Say we allow people within role group 'rGroupA' to have access.
At some point, a user logs on to our web server, and we have the user name. However, we would not like to ask the user to type in the password.
Is it possible for us to know if this user belongs to 'rGroupA' somehow?
Currently, I could logon our LDAP server with my username and password and see the list of groups I am in. However, I could not search for the groups for my colleagues.
I have searched google for a while but haven't found the answer. It could be that I don't understand LDAP mechanism very well.
Many thanks!
I have tried multiple times to get this to work, but I haven't figured it out yet, so I'm asking in here, hoping that someone will be able to help me out.
I am using Atlassian's Bitbucket, Jira and Bamboo and they're all synced with an AD. At the moment I am using my AD user to retrieve all the other users. It works, but it's not optimal, as the password expires every three months, and I have to change the LDAP user login info on all three applications. We have ordered a Service User, where the password doesn't expire, but the problem is that the Service User is in another group.
The picture below shows how the AD is set up. My Service User is in a group called Special Users. I would like to use this user as the login user in the settings. This way I would never have to think about changing password, when my AD password expires.
I would then like to retrieve all the users from the "Normal Users" group.
Let me know if more information is needed.
Thanks.
You could also add multiple user directories pointing to different parts of your Active Directory.
Jira has an internal Crowd out of the box.
You may let Jira connect to User directory and let all other application use Jira for authintication.
This would save time by only updating your LDAP password every 3 months on 1 application and reflected on all 3 applications
We are removing User, User Group and Permission models from our backend in favor of Auth0.
Our first idea was to just delete User, Group and Permission tables from DB and replace related foreign keys with varchar field. In this field we would then enter IDs that we get from Auth0 in JWT (pointing to something not present in our DB).
Is this good approach? I somehow feel that there must be more "relational" way of doing this.
Generally OAuth will not do all of the permission checks for you. Instead it gives you general mechanisms to sign the user in and issue + validate tokens.
In most real world architectures you also need to manage a second level of authorization in your back end - using domain specific user data for roles, permissions etc.
A couple of write ups of mine may help:
User Data Management
API Authorization
Auth0 Community Manager Dan here,
In this scenario you may be able to leverage the RBAC to replace your existing users/groups/permissions setup.
You would register a user's roles and the associated permissions of each role in the Auth0 dashboard or programmatically via the management API. Then you can setup a rule to add user roles to the token.
To connect this user to your existing user data store you can store the Auth0 id, similarly to how you have described.
This allows you to lookup the user when the token is received, and to associate any permissions or roles the user has. You can make roles API-specific by adding a prefix to the role, or have roles be general depending on your needs.
Our application (referred to as "XYZ_App" below) is a multi-tenant SaaS application. We are in the process of making it available for Microsoft AppSource as a multi-tenanted "Web app / API" (referred to as "AppSourceXYZ_App" below).
We started our OpenID Connect implementation with endpoints pointing to “common” as per stated in the documentation when multi-tenancy is desired/required.
In XYZ_App, we added information in the system to know what AAD instance each XYZ_App tenant is associated with (using the GUID Microsoft assigned to this AAD instance, we are NOT using the "rename-safe.onmicrosoft.com" representation).
When using the “common” endpoints, we had to manually validate the issuer from the JWT to make sure it was the expected one: a user could access XYZ_App requesting access to XYZ_App’s tenant associated with contoso.onmicrosoft.com, get directed to “login.microsoftonline.com/common” to authenticate and then decide to authenticate with a user from another AAD instance (referred to as "anotherAADInstance.onmicrosoft.com" below). In this scenario, even though a user could successfully authenticate on anotherAADInstance.onmicrosoft.com, XYZ_App’s redirect URI must make sure the JWT issuer is the one from contoso.onmicrosoft.com. I’ll refer to this setup as Scenario_1.
With that scenario in mind, we thought about NOT using “common” and customize the requests going to login.microsoftonline.com on the fly; attempting to “jail” requests to be forced to authenticate against a specific AAD instance. We would still need to perform our validation in the redirect URI to make sure the issuer is the appropriate one, but we thought this approach might make our lives easier. I’ll refer to this setup as Scenario_2.
Do you envision Scenario_2 is viable in the long run or is it too short-sighted ? Based on my current knowledge of OpenID Connect, one limitation I can see with Scenario_2 is that it would become problematic to support “broker accounts” into our app.
Explanation of “broker accounts”: in our industry, some external users are allowed access to the system. Let’s say I have a company called “BrokerCo” (with their own brokerco.onmicrosoft.com AAD instance) who has 2 employees: Broker1 and Broker2. BOTH anotherAADInstance and contoso hired Broker1 and Broker2 to get broker services to perform tasks in XYZ_App; requiring XYZApp to grant them access. What is the ideal way for authentication from an OpenID Connect standpoint ? If XYZ_App were to use “login.microsoftonline.com/common” for authentication (like in Scenario_1; as opposed to “jailed” access like in Scenario_2), Broker1 and Broker2 could authenticate with brokerco.onmicrosoft.com (no AAD "External users" for anotherAADInstance nor contoso), but they would then get to redirect URI with an issuer that is different than what XYZ_App’s anotherAADInstance and contoso tenants are configured for... I feel like I’m back to square 1...
Do you have suggestions or pointers to solve this issue ?
Background context:
While playing with OpenID Connect issuers, I got the following error message:
AADSTS50020: User account 'testuser#anotherAADInstance.onmicrosoft.com' from identity provider 'https://sts.windows.net/XXXXXXXX-fake-GUID-9bZZ-XXXXxxxxXXXX/' does not exist in tenant 'XYZ Publisher' and cannot access the application 'YYYYYYYY-fake0-GUID-YYYYyyyyYYYY' in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
Thanks in advance !
Your question has multiple layers, trying to address most of them:
AppSource is about trial experiences for new users: this mean that any corporate account around the globe can potentially be an user of your SaaS application - or at least to the trial experience of your application, therefore the first thing you need to think when integrating with AppSource is how easy it has to be for a potential user to experience your app for the first time.
With that in mind, AppSource recommends that the trial of application is build on such a way that allows any user from any organization to sign-in, and therefore a multi-tenant approach for your application is the recommended setup for any application.
The single-tenant approach requires more control on your side, and for a trial experience - it means that the user cannot try your application right away because the operation you have to do on your single-tenant application is to add the user to an Azure Active Directory tenant as a guest user. This guest account will need then to wait receiving an email to accept the invitation to join to this tenant you are adding the user to then sign-in to your application.
Therefore your scenario 1 is the best scenario thinking on a trial experience in general, and also in general require less management (as you'd not need to create/ manage each individual account that needs to access your application as guest users of your Azure AD instance).
However some concerns you listed - that this scenario bringing are valid: Because you are accepting the common endpoint, you are saying basically that any user can sign-in to any tenant to your application, and this may not be desirable. In addition, the scenario you listed that a user can generate a token for any application is also valid, however, you can add additional checks to make this more secure and that any token generated by another authentication is blocked:
You can validate the 'audience' claim to guarantee that the token was issued to your application
You can eventually check the 'tid'/'iss' claims against of a list of tenant Ids in your database to see if that the user's organization is a valid organization in your application -- this would be valid for non-trial users/ organizations.
More information in this article.
About scenario '2' and broker accounts:
This scenario could be interpreted in two different ways:
Broker accounts are guest accounts of a customers' Azure AD tenant
Broker accounts are third party accounts but are not actually added as a user of anotherAADInstance or contoso AD
If your case is '1' then you're right: if your application needs to authenticate guest users that belong to another Azure AD tenant, then common endpoint could not be used directly.
If your case is '2' then what you'd need to do is to continue using the common endpoint and somewhat after the user is authenticated ask them to choose the company. I am describing this on generic terms without fully understanding this scenario. Perhaps this is not simple as you want the remote company to control this and not the user - so some additional complexities may need to be handled here.
A note is that if your scenario is scenario 1. - in theory - you can still use an hybrid approach, where you'd ask user to type the username inside the application and the company that they want to sign-in, then check if you need to validate the user against common or tenant-id endpoint, preparing the request and then sending a login_hint argument when authenticating. More information here
Is there a way to get the Group the User is member of so we can process the authentication, or even throw exception so the token will not be created.
The reason we need groups is that we can not create OU in Azure AD whereas we could before in LDAP. We retrieved the distinguished name and therefore had very rich information about said user.
Lastly, we do see that you could create an OU on-premises but read that Graph API would not recognize it or could not retrieve it.
We are attempting to do logic within the SecurityTokenValidated stage of Authentication process and we break the process whenever we try to use:
string UPN = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value
Is this because we are using MSAL?
The best approach for you to take here is to make use of the group claims capability of Azure AD. (And for get OUs. OUs are not represented in Azure AD at all.)
Dushyant Gill's blog post on this is relatively old, but still very much relevant: http://www.dushyantgill.com/blog/2014/12/10/authorization-cloud-applications-using-ad-groups/. In short, the process is:
Enable group claims for your application by setting the groupMembershipClaims property in your application. After setting this, when a user signs in to your application, the list of groups they are a member of will be included in the token (if the number of groups is smaller than the limit).
Update your application's authorization code to make use of the group membership claims (if present).
Update your application to query the Azure AD Graph API if the groups membership claim is not present (i.e. if the "overage" claim is present). This happens only when the user is a member of more than 150-250 groups. (Use the _claim_name and _claim_sources claims as indications that the Graph API needs to be called directly.)
As described in the documentation for Azure AD Graph API permissions, in order for your application to call the getMemberGroups method, the app must have the "Read all groups" permission (Groups.Read.All). This permission requires admin consent, but once consent has been granted, the request can be made using the signed-in user's access token.