I am attempting to implement a feature within our platform that will perform a Graph API lookup using an ObjectID to retrieve some additional information about the identity, such as display name. This works and is straightforward for local account identities, but not for federated identities. When a federated user signs in to our application using a custom SAML integration, we store their ObjectID in our database so that we may make these kinds of requests later. But when such a request is made, for a federated user, no results are returned.
In researching this problem, I came across a comment on this stack overflow post (AAD B2C adding / mapping claims from external / delegate Identity Provider?) which states "for each external identity, Azure AD B2C creates a user object in its own directory so that you can store claims that are asserted by the external IdP as well as claims that are asserted by the end user or your own application." This makes sense to me, and I can verify it myself in our development environment through the Azure portal. To be more specific, here's what I can observe when I sign in using a federated AAD user:
The ObjectID that’s passed to our system through the ID Token is 3d116a96-e9d6-4f12-8185-907f327dd522. This value is the object ID of my user in the AAD directory, not the B2C directory – it originates as the user.objectid field in the AAD IdP, where it’s mapped into the uid SAML claim, then mapped back into the B2C ObjectID claim in the SAML Technical Profile.
When I make a Graph API query for a user with that ObjectID, I get no results. This makes sense, given the previous point.
When I look at the B2C Users blade in the Azure portal, I can filter down to “external” users and locate my own. This user has sign-ins logged whenever I sign in to our platform using the AAD IdP, so I know it’s the correct external user entry. This user, however, has an ObjectID of a51ee747-bd73-481f-ac84-fce8cacd3309.
When I make a Graph API query for that user, I do get a result. I can even store an extension property on it and then retrieve that property as well.
It seems to me that the key here would be to store that second ObjectID in our database, rather than the first one, so that it may be used later to make Graph API requests for the custom attributes that are stored on that identity. The problem is that I can’t figure out how to access or refer to that second ObjectID within our custom policies.
Any advice would be appreciated.
Update
Rohit Prasad's answer below put on me on the right path, where I eventually found the B2C account linking sample, which was extremely helpful and which I was able to adapt to my own situation. Anyone else who's finding this should be aware that, at the time I'm writing this, that sample is slightly outdated - refer to this issue for more info.
When user authenticated with external IDP (Azure AD), you are creating the account in Azure AD B2C. When you create the account it generates an objectID which you can pass to next step to process further.
<OutputClaim ClaimTypeReferenceId="objectId" />
The ObjectID which is coming from Azure AD is the attribute which in general save under alternateSecurityID with identityProvider.
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="issuerUserId" PartnerClaimType="oid"/>
<OutputClaim ClaimTypeReferenceId="identityProvider" PartnerClaimType="iss" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId"/>
</OutputClaimsTransformations>
Here,
oid: Object ID of Azure AD
iss: Issuer of Azure AD
CreateAlternativeSecurityId : Use value of oid and iss and save it to alternatesecurityID.
Ensure the objectid claim is being output by your relying party definition:
<RelyingParty>
<DefaultUserJourney />
<TechnicalProfile>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />
</OutputClaims>
</TechnicalProfile>
</RelyingParty>
Related
I have an AD registered application which has an integration with Azure AD for SSO. It uses the Oauth2 strategy, by using the omniauth-azure-activedirectory-v2 gem.
I want to map a users security groups to my applications authorization model and for this I need the names of the security groups.
I want to reliably get a users security groups and the group names on login and I'm not able to. I get them sometimes correctly, sometimes in a uuid format and sometimes not at all.
I have an optional group claim set up for my application in Token Configuration and configured to return sam_account_name for all attached groups.
This seems to work fine for some clients, the groups are returned as for example "Admin_APP", but for others I seem to have the following issues:
A Users groups are returned but only as a ID(c5bb3738-59f1-4718-b34c-2dfac761e023), even tough I requested the name.
A User has "readable groups" but not all assigned in AD, some are missing.
Is this a configuration on my application side or should the organization adding my application to their AD configure their groups or my application? Or should I not rely on the token cliam at all and fetch the groups using the GraphQL API Azure offers?
I noticed when adding the application myself I need to give permissions for my user.profile but it doesn't show allowable permissions for groups. Also in the Enterprise application tab for the organization under permissions I can't seem to find the group claim I added. Only openid, profile and email.
I tried to reproduce the same in my environment and got the results like below:
I configured the Optional claims in Azure AD Application:
I generated the access token via Postman by using below parameters:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:ClientID
client_secret:ClientSecret
scope:user.read openid
grant_type:authorization_code
redirect_uri:redirectUri
code:code
When I decoded the token, I got the Group IDs instead of Group Name like below:
Note that: If you are configuring sAMAccountName as the claim value in the token, then it only returns the Group which is synced from on-premises AD. By default, Group ObjectID is returned in the group claim value.
By default, groups emitted in a token is limited to 150 for SAML
assertions and 200 for JWT.
I agree with junnas, you can make use of Graph API to get the user groups like below:
https://graph.microsoft.com/v1.0/users/UserID/memberOf
To get the only list of security groups user belongs to, you can make use of below query:
https://graph.microsoft.com/v1.0/users/UserID/memberOf?Filter("mailEnabled eq false and securityEnabled eq true")
References:
List a user's direct memberships - Microsoft Graph v1.0 | Microsoft Learn
How to get groups to appear as claims in the access_token by AmanpreetSingh-MSFT
Currently I have this setup:
At login, and in every subsequent request after login, a mobile application that I have built uses Basic Authentication to authenticate the user with a web service that serves the app with information it requests.
On every request the Authorization header is inspected, the password and username are extracted from the header, the password is hashed using a proprietary DLL (so the web service doesn't actually contain the hashing algorithm) and compared to the hashed password associated with the username that is stored in the database.
I have now been asked to include Azure AD SSO in the login options.
After reading much about the topic, this looks seems to me like the setup:
I'm curious about a few things:
Is this setup correct, more or less?
Does the app send the Identity Token to the web service? If so, how does the webservice validate that token?
Is it correct that the webservice can match the Azure Identity to the DB user using one of the claims in the Security Token?
Where do Access Token fit in this picture?
Thanks for the help!
(Side Note: I know that Basic Authentication is not the preferred way to go in the first scenario. This was a temporary decision till we developed the token handling code, it only works using HTTPS and this is an internal application - you wouldn't be able to activate the app unless you have a code we give you)
I have little experience in azure ad but I think we could talk about your case.
First, whatever id token and access token are both jwt token, so to your web service application, you need to use jwt decode library to decrypt the token and get claims it contains. Here we need to know the difference between id token and access token, and I think you'll know that for your web service application, if it's more likely to play the role of an api application, you need to use access token because this token also contains user information. Then you need to add code in your program to decode the token and check if it's a 'valid' token for the request.(Because you've used azure ad to achieve the login part, you don't need to use your custom login part.)
Next, the signing in feature provided by azure ad requires to use account and password in the tenant which azure ad belongs to, the user accounts may look like xx#xx.onmicrosoft.com, it doesn't required to keep sycn with the accounts in your database, so it's difficult and needless for you to compare the user name obtained from the decoded token with those in your database. Because when your web service received the token(id or access token), that means someone has passed the authentication from azure ad. The token contains user information including role, expired time etc. You need to check if the token has expired and if has the correct scope. (Let's see a common situation, microsoft provides many graph apis to call, when accessing these api, we need to provide access token in request head with matching scope, e.g. https://graph.microsoft.com/v1.0/me
requires a delegated api permission of User.Read)
To sum up here, if your web service just required the users in your database to sign in then can be access, id token and access token are both suitable for you because they both contains user name like 'xx#xx.onmicrosoft.com', what you need to do is decode the token and check if the token has expired and whether this user exists in your database(you may set up a mapping between them).
CompanyA is integrating with CompanyB where CompanyA's users will be buying devices of CompanyB.
CompanyA wants to show user's device(CompanyB) details on their app by calling
CompanyB's API on each user login.
CompanyA user is authenticated on CompanyA IAM.
CompanyA has to call register device when user tries to add an device first time.
Help me to identify the flow which i can use to query particular loggedin user's device only.
Do i need to create duplicate user account on CompanyB's IAM?
If i use client credential flow for API to API call, access token given by CompanyB is only provides access for API calls but it does not tell that on behalf of correct user only call is invoked.
Assume that CompanyA uses IdentityServer or any other provider as IAM and CompanyB uses Azure AD B2C.
Any other approach?
Please see below diagram,
You should be able to do this by making the Company B API multi-tenant in their Azure AD.
There are other options surely, this is just the first one that came to my mind.
Overview of the multi-tenant pattern
You would have to do admin consent on it to get the API's service principal in your Azure AD tenant.
The Company B API can give you an endpoint for doing this, redirecting you with the proper parameters to the authorization endpoint. How to send a sign-in request
After doing this, you should be able to then require permissions on the API from Company A API in your tenant (configured in Azure AD).
Configure a client application to access web APIs
After doing those things, your API should be able to use On-Behalf-Of grant flow to get an access token for Company B API.
Using Azure AD On-Behalf-Of flow in an ASP.NET Core 2.0 API
Company B API must be configured to accept access tokens from another issuer than their Azure AD of course.
In general multi-tenant scenarios, the issuer validation is commonly turned off.
If Company B wishes to have control over this, currently they will have to explicitly list the valid issuers.
Issuer values look like this: https://sts.windows.net/31537af4-6d77-4bb9-a681-d2394888ea26/, the GUID is your Azure AD tenant id.
The Company B API can extract the tenant id and user object id from the access token, and authorize the user to resources based on them.
I was looking at the AWS side and looks like they have something that could meet the requirements
https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_federated-users.html
Was wondering if something like this exists in Azure.
I'm trying to understand how to sign in with a developer authenticated identity using AWS mobilehub's iOS SDK as recently AWS changed this SDK and I cannot find any documentation on this.
The sample app fails to shed any light on this.
I have a REST API to retrieve the cognito ID and Token but I'm not
sure what to do with them once I have this.
AWS has the following different classes that futher complicate the issue:
AWSCredentialsProvider,
AWSCognitoCredentialsProvider (No longer available in new SDK),
AWSSignInProvider,
AWSAbstractCognitoIdentityProvider (no longer available in new SDK)
There's now something called AWSAbstractCognitoIdentityProviderHelper..
These are handled by the AWSIdentityManager which is part of AWSMobileHubHelper.framework however AWSIdentityManager doesn't let you
set the credentials provider so I don't understand how I am meant to
interact with it in this regard.
Any tutorials, documentation, etc. would be much appreciated
Your question exposes certain terminology problems:
When you say developer I am not sure you mean the same thing that AWS
means.
AWS use the term "developer" (as in "developer identities") to mean
externally maintained pools as opposed to privately maintained. AWS
has it's own product (Cognito User Pools) which you can privately
maintain as an AWS service. AWS does not consider user pools to be a
developer identity provider (but in practice, it is simply a fully implement renamed version of a developer identity provider).
Regarding maintaining tokens
The iOS SDK maintains the tokens you need for access to AWSServices.
You should use the Mobile Hub, (it has a much nicer object and
interface design than the SDK). But regardless of whether you use
mobile-hub-helper or the SDK directly, you never have to manage a
token (the SDK does it for you). The documentation (almost cruelly) obscures this fact (and yes, it is lagging behind the SDK).
3 ways to use Cognito
You must understand that there are 3 different interface apis.
COGNITO API and up to date API documentation (the RESTFUL interaction)
iOS SDK and out of date SDK documentation (the SDK is not RESTFUL, it has ton's of state).
Mobile Hub Helper (MHH) SDK - MHH is documented (a little) by the hub, and pretty well in the .h files used to produce appledoc documentation.
With respect to Identity and SignIn/Authentication (the topics of this question) aws-mobile-hub-helper (hereafter MHH) has an elegant design and works well. I would recommend anyone using Cognito start with the Mobile Hub site (or at least with aws-mobile-hub-helper). The MHH is basically a wrapper to the SDK and helps clarify and separate the issues of persistent federated identity and credentials/authorization for AWS services from issues of Identity, authentication and attributes/claims for that Identity.
Identity in MHH has only 1 class AWSIdentityManager.
SignIn in MHH has one protocol, AWSSignInProvider, and two implementations of that protocol (plus one I made):
AWSGoogleSignInProvider: OpenID-Connect/OAuth implementation of
AWSSignInProvider for Google+
AWSFacebookSignInProvider: An OAuth/Proprietary implementation of AWSSignInProvider for Facebook
AWSCUPIdPSignInProvider: OpenID-Connect/OAuth implementation of
AWSSignInProvider for Amazon AWS Cognito Your User Pools service (this is available on a forked repository)
The mobile-hub-helper is documented only in the .h files. These can be processed into documentation by appledocs, and the comments there are pretty good if you had an overview of the class structure (which does not exist but I will attempt to provide).
SDK Authentication Flow
The authentication flow documented by AWS, is an oversimplification and does not aid in understanding how the authentication is accomplished using the SDK and Mobile Hub Helper. The following diagrams attempt to convey how identity authentication(login) and authorization(credentials) to use AWS Services (like S3, and DynamoDB) works.
Understanding Cognito
Understanding Cognito is initially confusing for a variety of
reasons: Authentication, Authorization and Identity Management in a
distributed system is complex. There are many parties with different
roles and elaborate prescribed interactions with keys, tokens and
signatures. The end user, the relying party (RP) the Identity
Provider (IdP) the resource being used (RS) and the resource owner
(RO). This terminology is used by the OpenId Connect and OAuth2.0
standards documents. For reasons that will become clear, this
terminology is not consistently used by AWS. But they concepts and
the entities are all there when using Cognito.
There are some good OpenID connect overviews online (ex: http://nordicapis.com/api-security-oauth-openid-connect-depth/ ) and
a review of those will help.
Cognito allows non-OpenID Connect Identity Providers, this is
an advantage (ex: allowing the OAuth/Proprietary Facebook identity
API) but it also means that Cognito is playing a “federating”
role. This role is outside the scope of OpenID Connect standards
documents (Update 1: Lately I have begun to wonder whether the
Cognito Credentials Provider is really the RP (Relying Party) which
then issues credentials for AWS Services. But the main point here is
that OpenId Connect does not prescribe the way that Identities from
different IdP's could be combined.), Amazon are essentially inventing
the role, and in doing so have had some naming challenges.
Cognito Naming
Cognito is a single name created by AWS to cover many functionalities
and roles.
There is the RESTFUL web API to Cognito, but there is also the
Cognito SDK. The SDK calls and the API messages are not named the
same, and SDK calls make multiple and conditional API calls.
Cognito can federate identity providers. It can persist and
association betwene authenticated users from different identity
providers (So it can remember your google+ and your facebook
identities and associated them with a single Cognito identityId.)
Cognito can provide persistent identityId (which, if anonymous,
follow an iOS device using keychain data) for users as well as
authenticated users. These are stored in what is called an
Identity Pool (NOT to be confused with a User Pool). Your app
receives the same identityId for a user on different devices for
authenticated users. Unauthenticated (Guest) identityId’s follow a
single device.
Cognito can store (known as “Sync”) state data IdentityId’s (on
the AWS server), which works for authenticated and unauthenticated
users.
Cognito has a AWSCredentialsProvider (a source for AWS Credentials
for using AWS Services (Cognito but also S3, DynamoDB, etc)
Cognito can create an OpenID Connect server called a User Pool,
which can be used by Cognito Identity to Authenticate users.
Cognito is new, but AWS Federated Identities and AWS Identity
Management and AWS Credentials are not, so there are lots of classes
with overlapping responsibility. And the naming conventions are
confusing (consider the name
AWSCognitoIdentityCognitoIdentityProvider! ). The use of the “cognito”
brand name for userpools, really is a nightmare. An
AWSCognitoIdentity thing is Cognito Federated Identity CFI but an
AWSCognitoIdentityProvider thing is a thing like userpools an
authentication provider also called an identity provider.
SDK class names are confusing. But with few exceptions, classes starting with AWSCognitoIdentity (but NOT AWSCognitoIdentityProvider) are about the credentialsProvider/IdentityProvider, classes starting with AWSCognitoIdentityProvider relate to Oauth/Open Id Connect providers and other distributed identity providers (facebook).
Glossary/Synonyms
These terms are used loosely throughout the AWS documentation and marketing material. This is an attempt to sort out the terminology by grouping terms that are used interchangeably by AWS.
Identity provider, authentication provider, Login provider, federated
identity provider(s)
Amazon Cognito, Cognito credentials provider, cognito identity (all
seem to refer to the same class/process)
Cognito user pool, Cognito Your User Pools, user pool. CUP is an identity provider aka authentication provider
Cognito identity pool, pool, cognito pool, identity pool. Occasionally called an identity provider (which seems incorrect) but it is never called an authentication provider
Developer identity, developer authenticated identities, developer
provider, developer identity provider, all used to refer to private external Identity Providers.
Identity is a term often misused in Cognito documentation. It is important to understand there are two different kinds of identity that Cognito manages. identityId (which should be in lower case) is the persistent unique name that Cognito associates with credentials and uses to federate different Identity providers, and Identity (upper case) which is an authenticated identifier from an Identity Provider.
identityId Identity ID, id (as in get-id), identity, identityId
Identity
Federation means multiple things.
Web identity federation - an earlier way of federating identity at AWS
Cognito federated identities
BYOI (bring your own idenity) where a user may use google, facebook or another identity provider (perhaps a developer provided identity) usually through OpenId-Connect.
IdentityId Behaviors
An identity id looks something like this:
us-east-1:982396fs-841e-3cdd-9r43-e7ac41bhbcb28
The identityId is maintained on an iOS device in a keychain entry.
For an unauthenticated IdentityId it remains the same until you clear
the keychain (This can be done in simulator by Simulator -> Reset
Content and Settings…). At that point that IdentityId is abandoned.
It is not disabled, it is just never used again.
When the user authenticates, authenticating disables the unauthenticated identityId (the
identityId will be permanently marked with DISABLED in the Logins array in the
identityPool entry. You can see this in the Cognito console.) that is
currently on the device. There is one exception: If this is the first time the
authentication takes place for this Identity then the unauthenticated identityId is not abandoned but
is associated with the Identity and used as the authenticated
identityID going forward.
Merging multiple Identities (meaning usernames not IdentityId’s) from
different Identity providers abandons (disables) one of the identityId's, and
associates both Identities with the other identityId. Disabled
Id’s get created whenever this happens. These abandoned identityId's are marked with DISABLED in the Logins array in
the cognito identityPool.
In practice this process creates a reasonable use of unique identityIds with
disabled ones only getting created when a user authenticates on a new
device (It can be bothersome in testing as it creates a barrage of
disabled and unused identityId’s as the tester logs out and in
multiple times with multiple id’s). But in practice the common use case would not create this barrage of disabled identityIds. A user would:
Connect – get an unauthenticated id - authenticate – and use the same
ID. No abandoned id is created.
Connect on another device – here he/she would momentarily get a new
unauthenticated id – and when he/she authenticated and got the
identityId for his/her identity, that unauthenticated id would be
disabled and abandoned.
Each merging of identities from two identity providers would also
create a disabled and abandoned identityId.
AWSIdentityProviderManager
AWSIdentityProviderManager is the protocol that manages federated AWSIdentityProviders
In mobile-hub-helper AWSIdentityManager is the AWSIdentityProviderManager
All it needs to do is return to credentials provider a logins
dictionary, with providers name and ID Token. AWSIdentityManager
only returns the providername and token for a single identity
provider. It simply gets the name and token from the
AWSSignInProvider and returns. (There is a fork with a modification
that adds the ability to return all of the current logged in
providers in the logins dictionary.)
As modified AWSIdentityManager maintains an NSDictionary
called cachedLogins. Each new login adds an login (an identity
provider name and id token) to the cache. Then logins always returns
the whole loginCache. This is what supports identity merging.
When the credentials provider calls it’s associated
AWSIdentityProviderManager logins method, and finds a list of
logins instead of just one it will merge the identityId's for those logins
in it’s database and disable the identityId of one of them. How does
it know which ID goes with which login? The ID Token contains an
encoded decryptable (paste the token into https://jwt.io to see for
yourself) set of claims, one of which is the identity (ex: username)
Note: Even though you have an identityId that has multiple related logins, in Mobile Hub Helper you are only ever authenticated by one AWSSignInProvider. Credentials get associated with the merged identityId, but in mobile-hub-helper access to that identityId is always via the active AWSSignInProvider (authentication provider) even if you are logged with multiple identity providers. Your app can keep track of all of the AWSSignInProviders and access them independently of AWSIdentityManager, but from AWSIdentityManagers point of view you are logged in with one of them. In practice this has little impact (until you try to get "claims" like imageURL from different providers for instance).
About Merging Identities
Currently the AWSIdentityManager does not support identity merging. I have a forked repository https://github.com/BruceBuckland/aws-mobilehub-helper-ios from the github repository that adds that capability, and adds a Cognito User Pools Identity Provider AWSSignInProvider (AWSCUPIdPSignInProvider.swift).
You can probably think of all sorts of gotcha’s when merging
identities.
What if I try to merge two identities from the same provider
(wouldn’t the dictionary keys be the same?)
What if I try to merge two identities, each of which has a different
identity from the same provider associated with it (and again they
would create two entities with the same keys).
Cognito manages this beautifully and rejects attempts to merge
identites that cannot be merged. The rejection happens at login time
(when you would try get credentials, the credentials provider will
reject the logins dictionary that contains an un-mergeable
identityId)
Where Cognito buries its data
Cognito stores a keychain on the device that contains the last identityId that was used. This is used by the credentialsProvider/identityProvider object upon a call to credentialsProvider.credentials (iOS SDK name) to re-use an existing identity (for example unauthenticated) and avoid creating unused identities unless the user truly is not going to log in or resume.
Mobile-Hub-Helper’s AWSSignInProvider’s and AWSIdentityManager store an indication of an open session state in NSUserDefaults. These are used to re-start the session if the app is terminated and restarted.
AWSSignInProvider’s store NSUserDefaults too, and sometimes in the iOS Keychain, for their own internal purposes (like retaining easy persistent access to a username or imageURL or token)
I'ld like to implement SSO using SAML 2.0 in my web applications. I have seen spring-security-saml example [https://github.com/spring-projects/spring-security-saml.git]. There are a couple of things I wanted to know after I went through this sample:
Do I have to redirect all the user-registratons to the registration page of IDP as in this sample ? If not, how does the IDP know the credentials of the user?
Do the IDPs' like ssocircle (used in this sample) allow us to use customized attributes and change password kind of scenarios ?
What is the best IDP to use to implement saml sso in my application ?
Thanx in advance.
Q. Do I have to redirect all the user-registratons to the registration page of IDP as in this sample?
In SAML parlance, an application can be an identity provider (IDP) or a service provider (SP). An IDP authenticates users, which means that user identities and credentials are maintained by the IDP. An SP provides one or more service to the user.
From your question, it seems that you want to delegate the task of authenticating users of your application to an external party (the IDP). Therefore, your application will be the SP.
With that established, you will have to redirect all users to the IDP for authentication. The IDP's authentication page may have a link to the registration page, if required.
Q. How does the IDP know the credentials of the user?
The user must be registered with the IDP (after all, the purpose of the IDP is to authoritatively authenticate a user's identity, which it cannot do if the user is not registered with it). Users can be self-registered or registered by an administrator, such as, a Microsoft Active Directory Domain Administrator.
Q. What if I need to register the user in my system as well since I need to assign them roles specific to my system?
You can create your own implementation of org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler wherein you can check the authenticated user on successful single sign-on and register them with your application. Supply an instance of your implementation class as the redirect handler to the SAML entry point.
Do note that you will not have access to the user's password since that is stored by the IDP.
Q. Do the IDP's like SSOCircle allow us to use customized attributes?
SSOCircle is mostly a testing service for SSO (single sign-on). Although SAML supports custom attributes, SSOCircle only supports FirstName, LastName and EmailAddress (as of February 2016). Therefore no, you cannot use other custom attributes with SSOCircle.
Actual IDP's like Okta, OneLogin or Microsoft ADFS do support custom attributes. You must check their respective documentation for configuring and exchanging custom attributes between the IDP and the SP.
Q. Do the IDP's like SSOCircle support change-password kind of scenarios?
I am not sure about SSOCircle but an actual IDP will be a system that already has user identity management capabilities. Since password change is a common functionality for an identity management system, this should be supported with an actual IDP. However, you should consult the documentation for the actual IDP you use to make sure.
Q. What is the best IDP to use for my SAML application?
An IDP is not a product or a specification, making this question somewhat invalid. It is simply a type of actor in the SAML universe. If your users are part of a Microsoft Windows Active Directory forest, you can use Active Directory Federation Services (ADFS) to exchange SAML messages between Active Directory and your (SP) application(s).
If you want to support multiple Active Directory forests, or if you do not know in advance where your users will be, you can use delegation-based services like Okta or OneLogin, which allow your application to take incoming assertions from the delegation service.