You are affected if all the statements mentioned below are true:
The Pivotal Single Sign-On Service defaults to using a shared private key when signing tokens within a PCF deployment. Tokens are signed with the same private key, and validating the token signature is not sufficient to prove the source of the token across plans.
The Pivotal Single Sign-On Service provides a sample application for the Resource Server which utilizes Spring Boot and performs offline validation of the token. As part of the offline validation, it checks the signature and expiry but not the issuer. The issue is one of the claims on the token and is unique per plan.
The OAuth standard describes four roles: resource owners (users), clients, resource servers, and authorization servers. In a typical flow, an OAuth client will obtain a token on behalf of a user and then send that token in the Authorization header when making requests to a Resource Server (An API or a Microservice). The security of this model depends on the Resource Server verifying the authenticity, validity, and source of the token before granting access to protected API endpoints.
The tokens issued by the SSO Service are JSON Web Tokens which contain three parts: a header, a body containing claims, and a signature. These tokens may be decoded to find claims that a Resource Server must validate. For example,
$ uaac token decode jti: be209a40e73e42c5ba11505506256999 sub: f4be8b07-adbb-4924-a209-a91f9b15c203 scope: openid uaa.user cloud_controller.read password.write cloud_controller.write client_id: cf cid: cf azp: cf grant_type: password user_id: f4be8b07-adbb-####-a209-a91f9b15c203 origin: uaa user_name: demouser@####.com email: demouser@######### auth_time: 1498585425 rev_sig: 3c817c73 iat: 1498585425 exp: 1498586025 iss: https://sso-domain-1.uaa.#####.com/oauth/token zid: uaa aud: cloud_controller password cf uaa openid
Resource servers have the option of calling the /check_token endpoint to validate a token, but for performance reasons, applications may validate tokens offline by ensuring all of the following:
1. Signature Validation (using a public key obtained from the UAA’s token keys endpoint)
2. Expiry Check (using the exp claim from the decoded JWT token body)
Issuer Validation (using the iss claim from the decoded JWT token body)
The Pivotal Single Sign-On service provides a sample application for the Resource Server which utilizes Spring Boot and performs offline validation of the token. As part of the offline validation, it performs signature validation and expiry check but not the issuer check.
Root Cause
Unless a key is specifically configured per SSO Service plan, all plans in SSO Service within the same PCF deployment default to using a shared private key when signing tokens. Since tokens from all plans are being signed with the same private key, validating the token signature is not sufficient to prove the source of the token.
Mitigation
Customers are recommended to perform an upgrade of any Spring Boot applications using Single Sign-On for PCF service to Spring Boot 1.5.5+ using Spring Security OAuth 2.2.0+ and implement the IssuerClaimVerifier bean to enforce issuer checks for token validations.
We have implemented an override for this bean in our SSO connector for customer convenience and changed our authorization code and resource server applications for our identity sample applications to show what changes should be made.
The summary changes that customers should perform are below:
This has been tested to work with:
Customers may also change their token keys for SSO Service Plans using the instructions here until they can implement the above changes to their applications.
What is the impact on Spring Boot application?
Applications should perform dependency changes listed above for Spring Boot, Spring Security, and the SSO connector, and confirm the application is able to run on the updated Spring Boot version. This may require additional code changes based on Spring Boot’s required upgrade. Following that, the application should be re-deployed, which may involve application downtime.
What is the impact on the SSO service tiles?
With the implementation of the issuer check for your applications, no changes will be required for your existing SSO service tiles and configurations.
Why can't I switch my resource server to switch to check_token instead?
There are performance implications regarding calling into a central point for validating every API request, and this problem becomes worse in a distributed context. We recommend that you call into check_token only when performing highly privileged operations whose frequency is low.
What if my resource server is not running on Cloud Foundry?
If your application runs outside of Cloud Foundry but is using Spring Boot, you can still include SSO Connector as a dependency to take advantage of the IssuerClaimVerifier logic we have implemented that works with PCF ERT 1.9+.
What if my resource server is not running on Spring Boot?
If your application does not use Spring Boot, check if your library supports the issuer check and make sure it is implemented for your resource server. The issuer for your Service Plan can be identified via the OIDC well-known endpoint at https://<plan_subdomain>.login.<your_domain.com>/.well-known/openid-configuration to find the UAA’s OIDC metadata. The response should be something like:
{ "issuer": "https://sso-domain-1.uaa.acme.com/oauth/token", "authorization_endpoint": "https://uaa.####.com/oauth/authorize", "token_endpoint": "https://uaa.####.com/oauth/token", "token_endpoint_auth_methods_supported": [ "client_secret_basic", "client_secret_post" ], < … truncated response > }