Using SAML Federation as an alternative to the OAuth 2 SAML Extension Grant
We were recently approached by a client to develop an API management solution which would allow distinct user communities to authenticate against their chosen identity provider, some of which would support the OIDC standard while others would rely on the SAML standard.
Our first thought was that this could be achieved via the OAuth 2 standard by having the client application first authenticate to the appropriate IdP.
In the case of the OIDC standard, an access token would be delivered upon completion of the login process, which could then be used as proof of authorisation for REST API calls.
In the case of the SAML standard, upon receipt of the SAML Response from the IdP, the application could use the OAuth 2 SAML Extension Grant in order to exchange the SAML token for an access token which would then be used to authorise REST API requests.
For those unfamiliar with the OAuth 2 SAML Extension Grant Flow, here is a sequence diagram outlining how it works:
The first complication with this idea comes from the fact that the client application is an SPA, a Single Page Application running entirely within the user’s browser and with no backend, and the realisation that the SAML Extension Grant requires the caller to present both a client ID and a client secret in order to make the exchange. With no way to securely store the client secret, we were left contemplating either a change to the architecture to add a backend, or being forced to accept that the security of this solution would rely on the inability of a malicious third party to steal or forge an acceptable SAML Response token from the IdP in order to move forward with this solution.
Additionally, we were unhappy with forcing an application, written using a modern framework and interacting with REST APIs, to have to decode, parse, extract and re-encode the SAML elements required in order to make this solution work.
Finally, in the case of the SAML Extension Grant, the Resource Owner (the user) is not asked to provide consent to allow the application to act on their behalf and may not be aware of what precisely they are allowing the application to do.
It was at this point that another member of the team, Jérémie Denoyer pointed out that what we really had was two connected but distinct phases within our process, Authentication and Authorisation.
Whilst these two phases are usually witnessed in examples as being bound together in order to achieve the Authorisation requirement of OAuth 2 and by extension OIDC , there is no reason why they could not potentially be decoupled, since those standards makes no formal requirement on how authentication is achieved, only that it must occur.
Could it be possible to have a client initiate an OIDC authorisation at the relevant endpoint and have the authentication process be performed via SAML?
Could we use SAML Federation as a “protocol trampoline” to transition from the OIDC flow into SAML and back?
Once authenticated, would the OIDC flow be resumed correctly, the user prompted to provide their consent and the relevant tokens be returned to the client via the same OIDC flow that they had initiated?
This was something that we had never seen done before anywhere, but it seemed possible.
We quickly set about implementing a proof of concept, creating a trust relationship between an IdP configured to use SAML 2.0 and a second IdP configured with SAML Federation.
This second identity solution was also configured as an OP (Open ID Provider) in order to support the OIDC protocol and finally its user authentication process was configured to use the SAML Federation which we had previously enabled.
With everything configured we needed only to point our browser at the /authorize endpoint on the OP whilst providing the necessary parameters to initiate an OIDC Implicit Flow.
Our browser was immediately redirected to the login page of the OP. Since it was configured to use SAML as the authentication mechanism, it instantly redirected our browser to the other IdP sending along a SAMLRequest.
Having provided the necessary login details, our browser was redirected back to the second IdP, which accepted the supplied SAMLResponse as proof of authentication and redirected our browser back to the /authorize endpoint to continue the OIDC flow.
The OIDC flow resumed by asking for our consent to allow the application to operate on our behalf and, once provided, delivered to us the expected identity and access tokens (highlighted in red on the final screenshot).
Our Proof of Concept worked and we had coined a new term, “protocol trampoline”!
Whilst there are many examples available on the internet, which explain how the various OAuth 2 flows function, we have only ever seen demonstrations relying on a simple login form for user authentication.
The OAuth 2 SAML Extension Grant Flow is an excellent solution to the problem of how to integrate SAML IdPs and SAML clients with RESTful backend APIs but is poorly suited for use with RESTful clients authenticating to SAML IdPs.
We hope that this article has outlined a more appropriate alternative.