How do I ensure a SAML Assertion's Identity Provider with an embedded X509 Certificate is Legitimate? - validation

I am trying to implement a SAML Service Provider in order to allow for SSO to a cloud-based application, this application can host multiple tenants or companies. Normally, the user enters an e-mail address (which acts as their User ID) and their password to log in (the tenant would be identified by a URL parameter).
The SAML assertion that is received has the X509 certificate embedded in the payload, which is used to validate the signature of the SAML. While the signature can be used to verify that the assertion is valid, there is concern that someone other than the Identity Provider can generate their own public/private keys, sign their own assertion with a correctly "guessed" valid tenant ID and user e-mail address, then potentially gain access to the application.
What is a mechanism or technique used to identify that an assertion and its embedded certificate came from a specific identity provider other than the information contained inside the SAML payload? While I have read that certificates could be downloaded from identity providers, there is concern that those certificates would expire or become revoked, and additionally, we would also have to store them on our side. There is a legitimate concern that these scenarios would cause downtime for users.
One other small question, as we require a tenant ID to determine which tenant is signing on a particular user account, is it common (or proper) to provide that identifier through the URI, such as in the URL path or as a parameter on our endpoint receiving the SAML assertion?

SAML Trust
When you implement your SAML SP, you will be asked to pre-configure the signing certificate of your target SAML IdP. Therefore, your SP will only trust any incoming assertions signed with that particular signing certificate.
SAML Configuration
Configuration of a SAML SP can be done by setting up all IdP parameters including signing certificate manually, or by specifying a metadata file which contains all IdP parameters, including the signing certificate.
You may download the metadata file from IdP and use it locally in your SAML SP, or specify the URL of the metadata file and let your SAML SP to download and use it.
You may refer to Azure AD's SAML metadata URL as an example:
https://nexus.microsoftonline-p.com/federationmetadata/saml20/federationmetadata.xml
Obviously, this URL should be TLS/SSL protected and its content should only be modified by the IdP.
SAML Signing Certificate Rotation
When a signing certificate is rotated, the trust between IdP and SP is lost. You will need to re-configure your SP to trust the new certificate directly or refreshing the metadata file.
If you choose to configure your SAML SP by specifying an IdP metadata URL, you may consider configuring your SAML SP library to download and refresh the metadata regularly from IdP.
In this way, your SAML SP will have a trusted way to validate the latest signing certificate even though the certificate might be changed.

Related

Integrating SAML based SSO with Third party service provider

We have to integrate third party SP for SSO. Our application is a wrapper in spring(not springboot) and it has authentication/authorization module calling backend service using mongo as DB.
Now the requirement is to integrate SSO SAML based SP with a third party. The third party has given docs which asks to have IDP. In the provided requirement from SP, Nameid assertion has to be persistent ,unique and opaque and can be userid of client application (our application).
I believe we have to have an IDP like SSOCircle or Okta or some open source IDP in order to integrate with SP. And I think we can write a separate springboot SAML IDP and expose api to our legacy spring for login to SP.
Flow as I understand:
User from our portal access the third party SP website or API.
Third party SP will redirect the user to our IDP to log in .They will save NameId(UUID mapping of userids or userids) at their end which they will pass as SAML request along with other assertions.
Once User is successfully logged in , our IDP will redirect the user to third party SP with success response.
My questions :
Can (or should we )we bypass IDP ? I guess this would mean we write SAML IDP on our own. Please let me know my best options or whether this is a good idea to go without IDP and write our own equivalent.If we can't, I would assume we have buy paid proprietary or use open source IDP.
Nameid (unique, persistent, opaque) assertion : This is one of SP requirement.If we have to use IDP (which I think), and it SP consumer assertion requirement is to use persistent Nameid to be passed.It should be unique, persistent and opaque . So we are thinking that UUID mapping of userids in SAML request to IDP should be OK. If we go like this, we have to store UUID mapping in DB as nameid assertion . Do we have to use just our portal userids as nameIds or UUID in DP -SP integration to satisfy requirement? Please comment what approach is right.
Nameid persistence restrictions at IDP end as well as at SP end:There is one bottleneck at our end.Our IT security team would probably not allow NameId persistent mapping UUID forever due to security concern, In that case NameId mapping will change at our end. How should be address this if we have to use UUID as nameid?
NameId provisioning : when user from our portal request to login to SP - Would it be passed to SP as login request and then SP constructs saml request and pass nameids assertions to IDP ? If yes ,what is best approach for nameids be passed to SP as login request ? If no, how will SP know what UUID to pass in SAML to IDP? How will we address this if the mapping nameid are UUIDs which could change due to security concerns? . Another thing is though nameid is mentioned is mentioned as "persistent" in requirement but in the examples of requirement doc they are showing urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified . I think thats probably a mistake in doc. [?].
Any sample SSO SAML IDP (client ) application which we can refer which is close to above 1 ) and 2)?
Can (or should we )we bypass IDP ? I guess this would mean we write SAML IDP on our own.
No, you can't. If the 3rd party acts as a SAML Service Provicer, you need to or act as a SAML Identity Provider. Building your own implementation is quite a big tasks and you may either use an SAAS-based IdP like SSO Cirle (keep in mind that your customer needs to accept where the user idenity data is stored) or deploy your own SAML IdP. There are payed products/service or free-of-charge. Open source need not mean free-of-charge , that's often misunderstood.
If you need a SAML IdP anyway, you may think of making your own app act as a SAML SP as well to leverage authentication of the IdP.
Which NameId format to use is kind of agreement. The SAML spec propose the usage of specific NameId format for specific purposes, e.g.
'transient' NameId format is meant to be used for SSO flow only.
'persistent' is meant to be used when you want to link identities of different identity silos together
The SP may use the value of the NameId value in the subject to find a user's profile or to perform auto-federation (build a profile on its side). It could also use attributes from the SAML attribute statement to achieve the same. Many SP implementations offer this.

How does SAML Service Provider understand identity after initial authentication (vs OIDC)?

I'm looking to implement a plugin using OpenSAML for a 3rd party application that will enable the application to be treated as a SAML Service Provider, so that I can integrate it into AWS SSO.
The following image describes the SAML authentication process when the Service Provider (SP) and Identity Provider (IdP) use HTTP Artifact binding (taken from here):
After the initial authentication, the SP returns the protected resource to the user. My question relates to how subsequent requests for protected resources are processed.
With OIDC, the browser would receive a token and this would be sent to the SP for subsequent requests. The SP can inspect the token and confirm its integrity (assuming it is signed) and validity, without needing to make further calls to the IdP to re-authenticate the end-user.
With SAML, how do I achieve the same effect? How do I not have to make repeated calls to the IdP to check identity?
I suppose I could use a session, but I don't understand how I might ensure that such information is not tampered with within the client (i.e. how does the SP not have to rely on information provided by the client?). Does SAML have some sort of concept of a token that is safe for the user to store (the HTTP Artifact binding explicitly restricts the user from seeing the response from the IdP)?
What happens after the last step is not defined in the spec. You could say it's formally outside of SAML protocol. Even the last protocol-formalized step of SP supplying the resource is essentially a "do it yourself":
Section 3.4.5 (HTTP-Redirect binding):
Upon receiving the SAML response, the SAML requester returns an
arbitrary HTTP response to the user agent
Section 3.5 (HTTP-POST binding):
Upon receiving the SAML response, the SAML requester returns an
arbitrary HTTP response to the user agent
Section 3.6 (HTTP-Artifact binding):
[you can probably guess by now]
Most SPs will drop one or more cookies on the client during that last step. One of those cookies will contain a session ID or a more generic pointer that can be used to locate a session when sent back to SP. Subsequent resource "authorization" requests to SP will proceed by having the SP consult this server-side session. The session will usually hold the (authenticated) security context for this user/client.
For example, Shibboleth (built on top of OpenSAML) does so. The content of the cookie is up to the SP. It's arguable that token-based auth via e.g. local storage is more secure vs a cookie. There are pros/cons to both options and many factors specific to use case/context/technology stack impact the evaluation of risk and associated threat model.
Note: AWS SSO does not support the Artifact binding.

Token authentication and SSL

I'm relatively new to this area of securing API. Most of my career was in developing internal products for the use of the organization, or joining a product that has already implemented security (which usually does not change)
When reading about JWT and Identity server, I understood the role of signing and the need to separate authorization and authentication. But, one thing strikes me as odd:
If my user is about to get a signed token and use it to authenticate himself, and there is a "Man in the middle", listening and copying that token, could he impersonate my user? (I believe the answer is yes)
So my best option here is to use SSL on every call to my API. The token being temporary and all is not much less of a threat to security.
So, my question here is:
If I end up using SSL on my API calls, what is the signing good for? with SSL the traffic is hidden anyway and no one could tamper with it. The browser can possibly use the username and password as plain text and they won't be exposed.
What am I missing here?
I think all boils down to what purpose JWT serves in OpenID Connect protocol (OIDC).
In OIDC, ID token is a JWT. And if you go through RFC7519 - JSON Web Token, then you come across Trust Decisions section.
The contents of a JWT cannot be relied upon in a trust decision
unless its contents have been cryptographically secured and bound to
the context necessary for the trust decision
From OIDC perspective, trust decision is to authenticate the end user based on claims contained in the ID token. This can be only done if validation adhere to JWT specification. So basically it is a requirement by OIDC protocol and JWT specification.
Now about SSL. OIDC contains several other calls required to obtain final token response. These calls contain client identifiers, secrets and authorization code (depending on the flow). OIDC is built on OAuth 2.0 and OAuth 2.0 mandate SSL (TLS being the new name). Thus OIDC too require SSL.
In combination, SSL (TLS) prevents attacks during request and responses flow in wire. And JWT's signature guarantee token's authenticity independent of how it was received or which component of your application process it.

Is it necessary to validate a SAML Assertion

I, as a service provider, am trying to authenticate a user on my page by getting a SAML Assertion (SAML 1.0) from the identity provider (IdP). The following steps are performed (very abstract):
User visits my page
I redirect the user to the IdP where the user authenticates
I get a SAML Artifact with which I request the SAML Assertion from the IdP
The IdP sends the SAML Assertion directly back to my page
?
Is this process enough to ensure, that the users authentication is legit?
Do I just grant the user access to my service in step 5 or do I have to make sure, that the SAML Assertion is valid, by verifying the signature in the Assertion? If so, how do I do that? Do I miss any other steps?
No, if you are using the artifact resolution protocol you don't need to validate the signature of the assertion if you trust the transport. The transport can generally be trusted if it is a https url and your server has a correct set of trusted root certificates.
Details
The SAML2 standard (core, section 5.3) states that an assertion should be considered properly signed if it is contained in another element that is signed. In the artifact resulotion case it means that a signature covering the entire artifact resolution response message is enough to consider the assertion to be signed.The standard further says that an SAML message received over an authenticated SLL connection MAY be considered properly signed if defined by the profile.
Looking at the WebSSO profile it states that for artifact resolution (profiles, 4.1.4.4) "the dereferencing of the artifact using the Artifact Resolution profile MUST be mutually authenticated, integrity protected, and confidential.". Which IMHO is covered by a properly setup https connection.
But if you are doing SAML2 the full administrative way, you should also have a deployment profile for your specific setup that explicitly defines if an https connection is trusted or not.
My Short personal recomendation: If the IDP already signs the assertion, the key to validate it should be in the Metadata already, validating it should be a easy operation and have big security benefits. So do it.
However... (Long answer)
It is always hard to say what is secure and what isn't. That all depends on how secure you need to your site to be. Using assertion is a way of making it more secure.
This way the user itself can not edit the assertion. Signature is a step more secure, that ensures that the assertion came from the IDP and has not ben changed.
Without it there is the possebility of an attacker pretendending to be the IDP, redirecting the artifact to its own server. The attacker could then respond with what ever assertion he wants. Another scenario is that if the assertion is not protected by a signature it could be changed somewhere while on transit on the internet.
With any security controls you have to weigh how important authentication of users are for you and the consecuenses on someone circumventing it.

How to share a public key for OAuth2 JWT validation?

I am implementing an app that connects to an OAuth2 server and it gets back a Json Web Token (JWT). I am passing the token along and I want to independently validate that the token came from the issuing source.
I can do this, no problem, with the public key from the issuing source. I have it available to me for now. Everything works.
But what if the OAuth server changes the signing key? How does the validating app get the new key? Is there a "best practices" convention for sharing the public key from an OAuth2 server? Do we just expose it from an endpoint on the auth server?
There's no solution that is standardized as part of the OAuth 2.0 protocol suite (today).
It was considered to be a single-domain problem that would be solved in various ways that were considered to be out of scope for the core OAuth specifications (much like the API between Resource Server and Authorization Server is/was), and much like any PKI based mechanism in general works today.
But OpenID Connect is a cross-domain SSO protocol that was built on top of OAuth 2.0, which also defined a more standardized option of dealing with key distribution in the form of JWKs URIs as part of the Discover, see the jwks_uri entry at:
REQUIRED. URL of the OP's JSON Web Key Set [JWK] document. This
contains the signing key(s) the RP uses to validate signatures from
the OP. The JWK Set MAY also contain the Server's encryption key(s),
which are used by RPs to encrypt requests to the Server. When both
signing and encryption keys are made available, a use (Key Use)
parameter value is REQUIRED for all keys in the referenced JWK Set to
indicate each key's intended usage. Although some algorithms allow the
same key to be used for both signatures and encryption, doing so is
NOT RECOMMENDED, as it is less secure. The JWK x5c parameter MAY be
used to provide X.509 representations of keys provided. When used, the
bare key values MUST still be present and MUST match those in the
certificate.
This would expose the key material over HTTPs protected channel, effectively leveraging the SSL CA for publishing and rollover of JWT signing key material.
At some point the jwks_uri definition may be part of the standardized OAuth 2.0 protocol extensions as well, but for now you'd have to rely on a custom agreement between Client and Authorization Server to do so. That may not be too hard to implement yourself though.
You may get lucky if your Authorization Server happens to be an OpenID Connect provider as well and uses the same key material for signing ID tokens as well as JWT access tokens.
Updated 4/22/2019: the Authorization Server metadata document is now also standardized it its own OAuth 2.0 extension OAuth 2.0 Authorization Server Metadata RFC8414

Resources