How to provision salesforce prmission sets using okta? - salesforce

I'd like to have multiple salesforce "apps" in okta, each configured with provisioning. There will be a "base" one which actually provisions the base salesforce account. But then I want additional salesforce "apps" configured in okta which just provision (or remove) additional permission sets - adding or removing permission sets to the base account. These permission sets represent granting or revoking access to custom force.com apps hosted in the same salesforce org.
I have tried doing this using the following mapping:
Okta User Profile / user
Arrays.add(salesforce_1.publicGroups,'My perm set')
maps to:
Salesforce.com (add my perm set) / appuser
salesforceGroups
the idea being that the above would just add the "my perm set" permission set to whatever permission sets the salesforce account already has.
but its giving me the following error:
Unable to resolve salesforce_1 in expression Arrays.add(salesforce_1.publicGroups,
'My perm set'). Attributes from the same profile cannot be mapped to each other.
I'm also not seeing where I would have the opportunity to configure the deprovisioning logic... which would be:
Arrays.remove(salesforce_1.publicGroups,'My perm set')
Is there any way to achieve what i'm trying to do here?

The provisioning in Okta is tied to a named account in SFDC. What you are trying to do will not work because each SFDC app in Okta will provision or deprovision the actual SFDC account of the user. You can't really split things up as you've intended within Okta.
You will need to rely on updating the user profile in a single okta app instance - keeping track of the consolidated permissions needed each time you update the user to make sure "all the permissions" governing "all the custom force apps" are captured.

Related

Azure B2C - Can't get a B2C user flow to work with another Azure AD instance as a custom identity provider

I have set up a B2C instance OK and managed to get a basic Blazor (server) app working with it a using the Microsoft Identity Platform (using AD groups for permissions - it was a hassle but works).
However, I'm trying to use an external Azure AD as a custom identity provider in the user flow, so that I am not just restricted to just email/id/social accounts, but can have guest accounts from other directories use the app without having to manage their sign-in's. To do that I performed a web app registration in the AD tenant that I wanted to use to authenticate those accounts against (as suggested in a couple of tutorials).
The application I registered in the external AD has a Redirect URI in the format "https://{My B2C Directory Name}.b2clogin.com/{My B2C Directory Name}.onmicrosoft.com/oauth2/authresp", which matches the name of my B2C instance, and I have added the client id and secret generated from that app registration and put the details into the custom identity provider I have created for the sign-in flow, as per the instructions here (including the mappings etc.):
https://learn.microsoft.com/en-us/azure/active-directory-b2c/identity-provider-azure-ad-single-tenant?pivots=b2c-user-flow
I also found a slightly older tutorial here, which is pretty similar (different mappings) that I've tried to follow (and adapt the bits that are out-of-date).
https://medium.com/the-new-control-plane/connecting-azure-ad-b2c-to-azure-ad-via-the-b2c-custom-identity-provider-42fbc2832e32
However when I run the user flow I get "AADSTS900971: No reply address provided." - this happens even when I run the flow directly from the User Flows tab in B2C with a 'Reply URL' explicitly set to "http://jwt.ms" (just to capture the token contents).
I'm confused about the reply URL being missing because they exist in both registered apps. Also, it's not saying they're mismatched, just that one isn't set at all (but appears to be).
It feels like I'm missing something simple - does anyone have any idea what that might be?
Ok so I did a couple of things to resolve this:
Re-registered the application in the AD I want to authenticate with (following this tutorial again: https://learn.microsoft.com/en-us/azure/active-directory-b2c/identity-provider-azure-ad-single-tenant?pivots=b2c-user-flow)
I was careful to ensure that the redirect URI in the format:
https://{B2C Instance Name}.b2clogin.com/{B2C Instance Name}.onmicrosoft.com/oauth2/authresp
was all lower case.
I also had to change from just a 'sign-in' user flow to the 'sign-up, sign-in' one, and then applied the custom identity provider to that flow. Apparently you need that even for users from another AD to be able to complete their invite process (otherwise you just end up with a user doesn't exist error - even if you've invited/added them to the B2C users list).
I also elected to 'Grant admin consent for Default directory' under the API Permissions tab for the application being registered in the external AD (to be used for the custom identity provider).
The flow seems to work now. The only thing that would be useful would be to have an invite only sign-up, sign-in flow so that you could invite specific people without breaking the invite process.
If anyone knows how to do that please do post something.

Restricting Microsoft Graph (or Azure AD Graph) read permissions

Further to the question raised here
Get all user properties from microsoft graph
Yes, I can obtain full user profile data using the graph query but from the perspective of the tenant, can I restrict the graph query to only be able to access the basic profile data?
Azure AD graph has delegated permissions for user.readBasic.all which restricts this. We have a 3rd party app that accesses the Azure directory to retrieve basic data to set up accounts in its user directory and we need to restrict this to the basic data due to the security risk. We cannot rely on the 3rd party just doing the right thing all the time.
So I need a way to set the app to allow app permissions (not delegated as the read occurs every 4 hours without human involvement) for user.readBasic.all.
If you want restrict the returned field from the "user.readBasic.all", the best way is you implement a custom handler(API/Service and so on). No directly official channel to do this now. (user.readBasic allows the app to read the full profile of the signed-in user, because after the user sign-in it means he has authorized the APP to get his information.)
You can check the blog for graph permission for here: https://blogs.msdn.microsoft.com/aaddevsup/2018/05/21/finding-the-correct-permissions-for-a-microsoft-or-azure-active-directory-graph-call/
And for the detail of the "user.readBasic.all" you have pointed from official link(https://developer.microsoft.com/en-us/graph/docs/concepts/permissions_reference#user-permissions) Allows the app to read a basic set of profile properties of other users in your organization on behalf of the signed-in user. This includes display name, first and last name, email address, open extensions and photo. Also allows the app to read the full profile of the signed-in user.

Identify admin permissions required by an Azure AD app registration

How can I find out what admin permissions are blocking the user from signing in to an Azure AD app?
I am setting up an App Registration in the Azure AD portal to be used with my Service Fabric cluster. The app registration does basic auth and only has one Required Permission configured: Sign in and read user profile (which does NOT require admin permission).
My tenant has the "Users can consent to apps accessing company data on their behalf" setting to "Yes", so it's not that.
Also, the /authorize request doesn't have any resource parameter, so it's implicitly asking for the permission I configured: Azure AD's Sign in and read user profile.
However when an non-admin user attempts to sign it, I still get the error:
AADSTS90094: The grant requires admin permission
I reproduced the scenario and this is what I observed. Found a workaround, hope it helps.
First I created a Service Fabric (SF) cluster secured with AAD authentication using the steps described here, using an AAD tenant where I am not a global admin.
Then I tried to login to Service Fabric Explorer (SFX) and I got this error:
AADSTS50105: The signed in user is not assigned to a role for the
application 'f8c79129-deb7-4a21-a6e0-ec29e88298ef'
This is expected, because the user must be assigned to a role (Admin or ReadOnly) in the SF application that represents the cluster. So I went to AAD > Enterprise Applications > found my cluster app and under Users and Groups I added myself to the Admin role. Notice that the fact that a regular user can administer the roles of an application that the user owns is something new, it's available since a month or so -- before that, a regular user couldn't administer the roles of an application.
Then I tried to login again to SFX and I got a different error:
AADSTS65005: Invalid resource. The client has requested access to a
resource which is not listed in the requested permissions in the
client's application registration. Client app ID:
f8c79129-deb7-4a21-a6e0-ec29e88298ef. Resource value from request: .
Resource app ID: 00000002-0000-0000-c000-000000000000. List of valid
resources from app registration: .
00000002-0000-0000-c000-000000000000 is Windows Azure Active Directory. For some reason SetupApplications.ps1 doesn't assign the Sign in and Read User Profile permission to the SF cluster application. So I edited the application and I assigned that permission, just like you showed in your print screen. Notice that SetupApplications.ps1 has a parameter AddResourceAccess (not mentioned in the doc) that adds that permission, not sure why it doesn't add it by default. Perhaps it isn't needed when you run SetupApplications.ps1 as a global admin, and the scripts/doc assumes that you are a global admin.
Then I tried to login to SFX again and I got the same error that you observed:
AADSTS90094: The grant requires admin permission.
So I checked the SF application under AAD > Enterprise Applications > found the SF cluster app > Properties. User assignment required is configured "Yes". I changed it to "No" and tried to login to SFX. This time it worked OK, I could consent and access the SFX console. Then I changed User assignment required again to "Yes".
One can argue if the SF app really needs User assignment required > Yes because anyway if a user is not assigned to the Admin or ReadOnly role, SFX will try to fallback to client certificate authentication.
In either way, the AAD behavior is confusing. At least, the error should be more descriptive and point to the User assignment configuration. Perhaps the current behavior has to do with what I mentioned before, that regular users can now administer roles. Perhaps the behavior is being improved.

How to support multiple login scenarios in multi-tenanted Azure Active Directory (AAD)

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

Authentication Process Get Azure AD group the user is a member of and do logic

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.

Resources