Pivotal Knowledge Base

Follow

Advisory: Recommended actions for applications secured by Single Sign-On Service for PCF

Are you affected?

You are affected if ALL statements below are true

  1. You are using Pivotal Single Sign-On Service on PCF
  2. You have created more than one SSO Service Plan on the same PCF deployment
  3. You have Spring Boot Applications utilizing the  @EnableResourceServer annotation

Problem Statement

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 issuer is one of the claims on the token and is unique per plan.

Detailed Description

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-4924-a209-a91f9b15c203
 origin: uaa
 user_name: demouser@acme.com
 email: demouser@
 auth_time: 1498585425
 rev_sig: 3c817c73
 iat: 1498585425
 exp: 1498586025
 iss: https://sso-domain-1.uaa.acme.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)
  3. 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:

  • Applications should be updated to use Spring Boot 1.5.5+ and directly include Spring Security OAuth 2.2.0+ as a dependency. We have performed this as part of our sample app build.gradle.
  • SSO connector dependencies should be updated for applications to version 2.1.1+. Resource servers should begin implementing SSO connector as a dependency to implement the IssuerClaimVerifier bean.
  • Applications should begin using the jwk.key-set-uri property instead of jwt.key-uri for Spring Boot to support token key rotation. We have provided examples as part of the application.yml for our resource server.

This has been tested to work with:

  1. SSO 1.4.2 (PCF ERT 1.11)
  2. SSO 1.3.3 (PCF ERT 1.10 and 1.9). Note that for SSO 1.3.3, client configurations and resources must be manually configured via the UI, as application manifest bootstrapping feature was not introduced until SSO 1.4.

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.

Frequently Asked Questions

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.acme.com/oauth/authorize",
 "token_endpoint": "https://uaa.acme.com/oauth/token",
 "token_endpoint_auth_methods_supported": [
  
  "client_secret_basic",

   "client_secret_post"
 ],  < … truncated response >
}

Comments

Powered by Zendesk