When working on an Apache Tomcat SAML 2.0 based single-sign-on (SSO), I came across the property named 'IsPassive' under SAML 2.0 Authentication Requests. The SAML 2.0 spec introduces this as follows:
IsPassive [Optional] A Boolean value. If "true", the identity provider
and the user agent itself MUST NOT visibly take control of the user
interface from the requester and interact with the presenter in a
noticeable fashion. If a value is not provided, the default is
"false".
What is the most accurate meaning or example of this definition in terms of a single-sign-on scenario? Does this property have a connection with active and passive profiles in single-sign-on?
First, this has nothing to do with the Active or Passive SSO. Typically "Active" refers to Web Services based SSO (I usually think about desktop client apps for this) while "Passive" more typically refers to Browser-based SSO.
Second, by sending IsPassive=True, the SP is essentially telling the IDP, "Authenticate this user only if you can do it without have the user involved." I think the most common methods for Web SSO might be Kerberos (Integrate Windows Auth) or x509. Alternatively, if the IDP has already authenticated the user and the user has a valid session that can be re-used for the given SP AuthnRequest, then that qualifies as meeting the IsPassive=true requirements IIRC.
Related
I would like to build SAML request in such a way that it support both Windows based Authentication and Form Based Authentication.
Scenario 1
ADFS Authentication policies are set to Windows based Authentication and Form Based Authentication.
If both authentications are set first priority should be given to Windows based Authentication.
Scenario 2
ADFS Authentication policy is set to Form Based Authentication.
In this case Form based authentication should be done.
My Question is how to set RequestedAuthnContext in SAML AuthnRequest so that above scenarios are covered.
Which Comparison Type should be used (MINIMUM,EXACT,MAXIMUM,BETTER)?
This is code snippet
RequestedAuthnContext requestedAuthnContext = SAMLUtils.buildSAMLObject(RequestedAuthnContext.class);
requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM);
AuthnContextClassRef windowsAuthnContextClassRef = SAMLUtils.buildSAMLObject(AuthnContextClassRef.class);
windowsAuthnContextClassRef.setAuthnContextClassRef("urn:federation:authentication:windows");
AuthnContextClassRef passwordAuthnContextClassRef = SAMLUtils.buildSAMLObject(AuthnContextClassRef.class);
passwordAuthnContextClassRef.setAuthnContextClassRef(AuthnContext.PPT_AUTHN_CTX);
requestedAuthnContext.getAuthnContextClassRefs().add(windowsAuthnContextClassRef);
requestedAuthnContext.getAuthnContextClassRefs().add(passwordAuthnContextClassRef);
My Question is how to set RequestedAuthnContext in SAML AuthnRequest so that above scenarios are covered.
I tried all Comparison Types. But Expected scenarios are not working.
The SAML spec (Core with errata, section 3.3.2.2.1) says this about RequestedAuthnContext element:
If ordering is relevant to the evaluation of the
request, then the set of supplied references MUST be evaluated as an
ordered set, where the first element is the most preferred
authentication context class or declaration. For example, ordering is
significant when using this element in an AuthnRequest message but
not in an AuthnQuery message.
The part about evaluation as an ordered set was clarified in the errata revision of the spec
The comparison rules:
If Comparison is set to "exact" or omitted, then the resulting
authentication context in the authentication statement MUST be the
exact match of at least one of the authentication contexts specified.
If Comparison is set to "minimum", then the resulting authentication
context in the authentication statement MUST be at least as strong (as
deemed by the responder) as one of the authentication contexts
specified.
If Comparison is set to "better", then the resulting authentication
context in the authentication statement MUST be stronger (as deemed by
the responder) than any one of the authentication contexts specified.
If Comparison is set to "maximum", then the resulting authentication
context in the authentication statement MUST be as strong as possible
(as deemed by the responder) without exceeding the strength of at
least one of the authentication contexts specified.
Our translation of your scenario:
Windows auth should take precedence over form-based auth
Form-based auth should be the fallback
The most spec-compliant way of implementing the request is
requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT);
...
requestedAuthnContext.getAuthnContextClassRefs().add(windowsAuthnContextClassRef);
requestedAuthnContext.getAuthnContextClassRefs().add(passwordAuthnContextClassRef);
If your ADFS policy has Windows auth and Form-based auth as selected options, the IdP should select Windows-based auth since it's referenced first in the authentication request. If your ADFS policy contains only Form-based auth, the IdP should go with that since it still exactly matches one of the two auth contexts in your authentication request.
If you did NOT have control over ADFS setup and you could not guarantee the auth options chosen in ADFS policy, then a safer implementation would be to use Minimum as the comparison strength:
requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM);
...
requestedAuthnContext.getAuthnContextClassRefs().add(windowsAuthnContextClassRef);
requestedAuthnContext.getAuthnContextClassRefs().add(passwordAuthnContextClassRef);
So far we've talked about the spec perspective but does ADFS respect the spec and implement it correctly? ADFS 2.0 claims to do so with a short list of supported auth contexts. On ADFS 3.0 there's at least one report of this feature being broken (allegedly). Verification of this scenario on ADFS 4.0 and 5.0 would be an interesting bullet point, perhaps someone can comment.
First of all, the Authentication Context is an abstraction.
Which actual Authentication mechanism is really used by the IdP is totally up to the IdP.
Even if you request 'SPNEGO Kerberos' ("urn:federation:authentication:windows") the IdP may use a totally different mechanism.
Furthermore there is no specification that defines an order upon Authentication Context Class Refs ... again it's up to the IdP implementation to decide which mechanism it considers stronger than another.
From that respect you may use 'MINIMUM' as comparison. 'EXACT' may reduce the probability for successful SSO flow.
I want to have an architecture made up of these devices / programs with different roles (which are all separated, none of these roles must exist in one and the same instance):
CLIENT
AUTHENTICATION-SERVER
AUTHORIZATION-SERVER (there can be a multitude of these)
RESOURCE-SERVER (also many possible)
And:
I don't want to use any websites a user has to navigate to.
From my studies of OAuth and Open ID Connect I would assume that a Client could get an ID_TOKEN (after authorization) from an AUTHENTICATION-SERVER and could then request ACCESS_TOKENS to different resources from the AUTHORIZATION-SERVERs.
I guess the method I described allows identity theft on the client side.
I cant find a way to easily get id tokens from an authorization server to a client (which I could then use to authenticate to multiple authorization servers). My clients are trusted. I want to use native apps and implement open id connect among them anyway.
I do not want to use any websites as of now and still need to be able to have a secure communication with associations of claims to users and everything. Are OpenID Connect and its possible 'Flows' appropiate for this? Are there any other implementations that would allow the flow I described (or mabye derivations of OpenID Connect)?
It's not recommended but if you really don't want to use a browser (which is somewhat anti-OAuth/OIDC and is full of limitations) then ResourceOwnerPassword grant type is the one you'll need to use. This will not return an id_token though, just an access_token.
id_tokens exist to support front-channel browser-based sign in flows, they serve no purpose if using the ROP grant type.
Access tokens are issued by the authentication/secure token service (IDS4 in this case) and grant the client (optionally with user consent) access to the resource. The resource then has its own authorization rules to enforce scope and user-related ACL/business rule access controls.
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
We have several service providers using Saml 2.0 for single sign-on and they are all working fine. Our most recent addition is balking because we send a NotBefore attribute on the SubjectConfirmationData element. As far as I can tell, this is part of the xsd schema for Saml 2.0 (https://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd) but then it is marked as MUST NOT in this profiles PDF (https://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf).
What am I missing?
As you figured out, the Web Browser SSO profile - which is the one you are using to provide single sign on for your users as an Identity Provider - dictates that you should not set NotBefore. The profile sets further limitations to the schema defined for Assertion to be used generically, which is totally fine.
The service provider at hand strictly checks compliance and thus rejects your Assertion. The fact that it has been working so far probably means that the other service provider implementations were more lenient.
I am just getting started with SAML. AFAIK, in the authentication step, there is no direct communication between the IdP and the SP and the assertion happens via the browser.
In my applications (which will be the SP), I would like to store some user specific data (stuff like page size, other UI preferences). When the user is deleted from the IdP, I would like to purge this data from my application as well ? Is it possible to get this "event" from the IdP to the SP for such tasks ?
PS - My app is PHP based and I am likely to simplesamlphp.
Thanks,
~preetham
There is no support in the SAML 2.0 spec for having the Identity Provider call out to the Service Provider for events related to user provisioning or deactivation.
However, there is a SAML protocol called SubjectQuery and a request called NameIDMappingRequest which might serve the purpose if you had a nightly batch job or something that would query users which haven't logged on in x days to see if they still exist on the Idp.
You can find the details on these in the Profiles Section of the SAML spec but I don't know what support (if any) simplesamlphp has for these profiles.