SAML service provider signature verification - security

This is a basic question about SAML protocol and how it specifies verification of a SAML token.
Looking an different diagrams and resources, it looks like the service provider doesn't need to make calls to the Identity Provider (IdP) in order to verify a SAML token.
I am interested in clarifying step 5 (Request the Assertion Consumer Service at the SP) from wikiSAMPL_wiki.
Mainly token verification is done on Service Provider without additional calls to IdP.
Token validation consists of the 3 steps:
1.Verify token is well-formed
2.Verify token is coming from the intended authority
3.Verify token is meant for the current application
Is this assumption right ?

From a very high level, yes, your three steps are correct.
More specific:
1 will include decoding the base64 encoded response, checking against
schema, etc.
2 will be done via signature validation, checking the authority,
seeing if it's a response to a sent AuthnRequest and matching it,
etc.
3 comes from checking the relay state and ensuring that it is a
location that is "protected" by the service provider

Related

Secure API with OpenID Connect - RP trust of OP

Getting to grips with OpenID Connect with a third party IdP ( OP ) and securing APIs. I'm comfortable with the client and user agent component and the OAuth2.0 flows and scopes to get an access token and an id token issued to my client from an IdP
What I'm struggling with is the Resource Provider end and how the secured API trusts the access token that the client passes. I keep equating the trust element to SAML and the initial exchange of static configuration data between the IdP and the SP. That appears to be missing in OpenID Connect so I'm missing the trust element. I'm reading about dynamic discovery but again I'm missing a trick as to the trust between the RP and the IdP. What's to stop me setting up a rogue IdP ? Why should the API provider trust tokens coming from my IdP ?
Final question is on a local representation of the unique identifier in the RP. Does the account ID need to exist ahead of presentation of the access token ? I expect it does ( again using the SAML analogy which requires a local account representation ahead of authentication success ) so account management on the relying party is also a requirement for an end to end authentication to be successful.
Boils down to two questions. How does the API trust the access token presented ? Does the API provider need to have accounts provisioned ahead of successful authentication of those requests for resource ?
Thanks in advance.
Dynamic Client Registration is used exactly in cases where there is no pre-established trust between parties and one wants to allow any OP that has a valid certificate to play.
When you want to restrict the set of OPs, you'd statically register with those in advance, thus doing the same type of bootstrapping to create pre-established trust as in SAML.
A unique identifier can be created by the (<sub>,<iss>) tuple as found in the id_token that the RP receives.
For dynamic registration of the RP with the OP there is no trust metric described. There are two HTTP trust levels that can be enforced.
HTTPS is required with a certificate that chains up to the root of trust certs.
HTTPS has an EV certificate. This required in-proofing as defined by CAB.
I have proposed the use of a trust ecosystem in the IDESG, but that is some ways away.
It would be interesting to see if Kantara has any kind of solution in mind.
From an OpenID Connect perspective you are correct. That does not imply that any relying party code that you construct needs to be insecure. I mentioned two ways that you can verify the OP.
A similar set of security rules could be enforced by the OP, but as others have said, most OPs do not enable dynamic registration for this reason.
The id_token is a JWS signed JWT. It is signed by an OpenID Connect OP (IdP), generally using its private key. You MUST verify the signature so that you're sure you know the JWT/id_token emitter. After that it's up to you to decide if you can trust this emitter for the action the client is willing to achieve.
The id_token contains a claim (at_hash) which is a reference to the access_token, so that you're sure the access token was generated by the same OP.

OpenID Connect ID Token: What's the purpose of audience [aud] field validation

I'm trying to implement OpenID Connect Implicit Flow. The frontend Single Page App passes the ID Token down to the backend server (using Authorization header) where I need to validate it.
The documentation requires me to check that I trust the audience of the token (aud & azp fields). I'm struggling to understand the significance of this validation step and what are the security implications of not doing so. Why should I distrust the token if I'm not the intended recipient?
My reasoning is that if I trust the issuer it doesn't matter who was the token issued for. I would expect the claims to be the same for any clientId (is this wrong?). Ideally when I pass the ID Token around my microservices all they should know is what issuers to trust (and use discovery protocol for figuring out the keys).
What is the attack vector if I skip this validation step?
The issuer could be issuing tokens to different applications and those applications could have different permissions. Not checking the audience would allow an attacker to use a token issued for application A at application B and may lead to permission elevation.
To your suggestion: the claims may indeed differ per Client.
Here's another reason: If you check that aud claim only contains your client, it prevents other apps' stolen tokens from being used on your app. If a user's token gets stolen from another app, nobody will be able to impersonate the user on your app because the aud claim will not be correct.
I'm answering this for posterity.
You should check the issuer and if your client_id is the only one in the audience if you are receiving tokens from an external OpenId Provider. One that could have more than your client.
Claims are not global to the OpenID Provider, they can be per-client. A user can have "Admin" role on app-A, gets a token there, then tries to send app-B (your application) the same token hoping that your are not checking to which client it was issued for (its audience).

SSO - Industry practice with SP side SAML response validation

we are implementing SSO solution with our customers.Due to its complex nature and time sensitivity, we employed a third party security partner firm that can act as SP and redirect the request after authenticating the user.
The third party firm is now telling me they are going to send SAML response to our application to further validate.
My question is , Given that SAML response is already validated at our third party provider(who is acting as SP on our behalf), why we(application owner) again have to do SAML assertion?
I was expecting it is going to be a redirect from the third party with some token to validate so that our application can skip the login validation part.
but I wanted to talk to them with research facts and industry practice. Can anyone help? please let me know if i am missing something here.
The usual practice when using such intermediary SP for SSO to (typically a legacy) application is to:
process and validate the SAML Authentication Response and the Assertion at the SP
SP then encodes a cookie on a common domain or a token provided as a request parameter/HTTP header
cookie/token is typically constructed using a symmetric cryptography with a shared secret and e.g. HMAC
SP redirects user to the application which verifies the provided cookie or token and grants access
I don't think you're missing anything. Perhaps your provider just confused things and gave you wrong information. It makes sense to include the SAML token itself in the response from SP to your application (e.g. for audit purposes), but it makes no sense to expect your application to understand or validate the SAML message once it's been done already by the intermediary SP.

Exchange IP-STS JWT token for ACS JWT token

I have an azure ACS service, which trusts an IP-STS.
For an active scenario, I first get a JWT token from my IP-STS using username, password credentials. There is Oauth2 endpoint and everything works quite well.
Is it possible to "exchange" this IP-STS token for a JWT token issued by my azure ACS ? If so, is there an example of code that does this. (To make things worse, all my code is in JavaScript (actually TypeScript) but that doesn't really matter).
Update :
I'm working on your hint with the ACS OAuth2 draft 13 endpoint.
I proceed as follows : I ask my custom STS (ThinkTecture STS) to give me a JWT token for the "ACS OAuth2 draft 13 endpoint" realm. This requires an oAuth client id and secret which are global in the TT STS and I assume they are irrelevant. In the TT STS management I have a symmetric key configured for this realm : key1. I receive the 3-part JWT token. The signature on the token is indeed made with key1.
I then pass this token to ACS with client id and secret from a service identity and parameters as specified
var form = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "grant_type", "http://oauth.net/grant_type/jwt/1.0/bearer" },
{ "assertion", rawtoken (the header dot body dot signature form TT STS },
{ "scope", "http://localhost"}
});
Unfortunately I now get
{"error":"invalid_client","error_description":"ACS50027: JWT token is invalid. \r\nTrace ID: b107cda5-393b-4b50-b14a-ebaa0ac41913\r\nTimestamp: 2012-12-05 08:58:10Z"}
I understand JWT is in beta and therefore ACS50027 is not yet documented. The hard part is that there is no known way to debug this. Thanks for nay help.
This is definitely possible, but I don't think any of the existing ACS samples do it so you're slightly in uncharted territory.
The approach I would recommend is to use the ACS OAuth2 draft 13 endpoint (as in this sample, but JWT instead of SAML and IdP instead of service identity). The request would be something like:
grant_type=http://oauth.net/grant_type/jwt/1.0/bearer&assertion=(JWT)&scope=(RP realm).
You'll need the issuer of the JWT to match your registered identity provider, along with an associated signing key, plus rules to pass through or change any claims as necessary and the RP to have a token type of JWT.
Ok, I finally found a way to do this. Your hint was crucial for the success. The (very) tricky part is that the IP-STS uses a symmetric key to sign the JWT token. I had to programmatically (using the odata api) insert this key in the ACS backoffice under the Identity provider. (the managament console does not show this key anywhere) Everything is nearly fine. The only trouble is that the ACS copies the audience ("aud") from the original token, while I request a token for a different audience ("scope"). Any ideas there ?
Nope,
You can't Exchange tokens in ACS. The only possibly viable way of doing so, is if you are able to register your IP-STS as an IdP in ACS (you will be able to do so, if your IP-STS supports WS-TRUST protocol). This will throw you on the passive scenario.
The only possible active scenario way is to get JWT token directly from ACS using Username/Password authentication with Service Identities. Well managing service identities in ACS is not as managing ASP.NET Membership provider, but it has a Management API.
The possible ways for authenticating with a Service Identity is Password, Symmetric Key, X.509 Certificate. So, if you twist enough your original IP-STS, to give you a Symmetric Key as a Claim in its JWT token, you will be able to get JWT token from ACS using Service Identity authenticating with that Symmetric Key.
But, if you already have a JWT token, why you need another one from ACS?
UPDATE
Well, the claims transformations are only option in the "Passive" mode. For active mode, the only way (that I know) is to use Service Identities, thus no claims transformations.
The issue with Passive is that because of security reasons, ACS will create a hidden POST form to POST submit transformed token to your Relying Party Application (RP). So there is no way to Actively get a Passive behavior. What you could do just for the sake for trial, and that will fail because of the passive POST in hidden form is the following:
If you are willing to experiment (and I have not tested and I am totally unaware of the result), you may try simulating wsignin1.0 action providing the original JWT token. You can look at the WS-Federation Passive Requestor Profile, section 3.1 on how to construct a Sign-In request. You can also use Fiddler to fully track a Passive scenario chain of events. The one that you shall try reconstruct is the wsignin1.0 request that goes from the registered IdP back to ACS.
At some point you will have the resulted HTML, which contains a FORM element. That form will have two hidden fields - wa with value of wsignin1.0 and wresult which will contain URL encoded <t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">.... This is what you want.
If you succeed in recreating the original SignIn request to ACS from your IdP, than this will work.

Do I need Federation Authentication if I have a custom STS? If so, why?

If I have a custom Secure Token Service that specifically lists out allowed audiences and checks if the token is coming from one of of those audiences and also checks the thumbprint and issuer of the X509 certificate, do I need WSFederation?
Since my STS is checking that the the token already came from a specific application and was routed through my ACS, aren't I verifying all of the things I need to? I know that Application A sent a request to the ACS which sent a request to Application B all from the custom STS, so where does Federated Identity fit in this picture?
Edit for clarity:
Sorry I was a bit unclear in the orignal post. I think the confusion came because I used STS instead of security token handler (Way different things, just a typo).
Application A is a custom login service, which displays the login options for the user, google/facebook/yahoo/etc. Logging in through these service gets the token from the ACS and returns it to application B, the Relying Party. This RP has a custom security token handler which accepts the token and validates that it is has an audience URI matching application A. It also validates that the issuer was the ACS and the thumbprint matches the one of the cert used to sign the token via the ACS.
This means that theoretically application B knows, that application A was used to login (as it came from that audienceURI) and that the ACS sent the token (as it was the issuer and the thumbprint matches). What I am asking is if federated identity is necessary for application B? What exactly do you gain by using it, if you've already proved where the token came from?
your question might need some clarification.
First, you might want to explain specifically what you mean by application A and application B, and how your STS fits in this scenario. Applications don't typically issue tokens, only STSes do. In this sense, ACS doesn't connect applications to each other, it connects relying party applications to third party identity providers.
Second, if you're talking about authentication over the web, and you have a custom identity provider STS that's issuing tokens for ACS, then you're probably already using WS-Federation. If however your token acquisition is not browser based, and you're making back-end HTTP calls to ACS, then WS-Federation is not relevant to the scenario.
Third, from the point of view of the STS, the set of allowed audiences is not about token issuers, it refers to entities that will consume tokens issued by that STS. That is, it's the set of subjects that the STS will issue tokens to. This could be applications themselves, or other intermediary STSes along the federation chain. (ACS for example acts as such an intermediary)
Fourth, when you're validating the issuer's certificate on an incoming token, you must do more than just compare the thumbprint. The thumbprint is not part of the token's cryptographic proof. You must validate the token's digital signature in order to verify that the token issuer owns the private key of the certificate.
I hope this clears things up, but if it doesn't answer your question please let me know.

Resources