In The News

Session Tokens - Balancing Usability & Security

Learn from Okta's 2023 breach—stolen session tokens exposed in HAR files. Lessons on JWTs, session cookie security, and vital config changes for Okta, Keycloak, and AWS Cognito. Dive into defense in depth with CoGuard for configurations across your infrastructure layers.

Albert Heinle
Written by
Albert Heinle

In October 2023, Okta reported a breach of their support system:

This breach contains lessons for system administrators and a reminder about the shared-responsibility policy for cloud vendors that we already touched on in Shared Responsibility for PaaS configuration.

Session tokens: Balancing Usability & Security

The bad actor in the Okta breach compromised user sessions by capturing session tokens from customer’s administrators accounts. The credentials were accessed by stealing HTTP Response Archive (HAR) files, the most common mechanism for troubleshooting, on Okta’s customer support system. HAR files contain a record of a user’s browser session, a step-by-step audit that a user can share with the help desk to debug or diagnose an issue. HAR file captures can contain a lot of information including: request and response headers, payload content, timing information and within this information they contain session cookies. Session cookies allow web applications to maintain stateful information across web sessions, like how you’re able to stay logged in for a period of time even if you close the page. HAR files are an incredibly useful tool for developers, support teams and administrators providing a common one-click solution to share diagnostic information between an end user and the team. 

Where it gets really interesting is these HAR Files contained JSON Web Tokens (JWT). A lot of web applications use JWTs to manage user sessions, authentication, authorization and single sign on. JWTs are a convenient, structured way to transmit data securely over the web. A JWT consists of three parts – header, payload and a signature. JWTs are stateless and can contain user data directly. And it’s really, really bad if someone steals your JWT. JWTs are used to identify users and if an attacker has stolen the JWTs they have access to the accounts and services in the same way as the user. The attacker can make service changes, account updates, access sensitive information, etc. The only real protection is that JWT can be configured to automatically expire. 

We were surprised that the session tokens were in the HAR files and that the tokens were still valid. 

There are 2 quick changes to the support team and infrastructure as a result of this breach. 

  1. Sanitize your HAR files

    Before a user uploads a file, the files should be sanitized by the user to remove sensitive information including access tokens. Cloudflare has published a HAR Sanitizer which can be remove sensitive information client side (source repository). Support documentation should be updated to include similar tools.

  2. Review / Update Authentication System Access Token Settings

    Most authentication systems, including Okta, Auth0, AWS Incognito and Keycloak, follow the OAuth2 standard. The OAuth2 standard defines both an access token and a refresh token. These token have a deliberately short lifespan because anyone with a token can access the resources that the token allows. The disadvantage to setting both tokens to a short period is that each time an access token expires you need to request user credentials. Refresh tokens can help balance usability with security, allowing users to stay authenticated for longer periods without repeating the authentication process.

    “You might notice that the “expires_in” property refers to the access token, not the refresh token. The expiration time of the refresh token is intentionally never communicated to the client. This is because the client has no actionable steps it can take even if it were able to know when the refresh token would expire. There are also many reasons refresh tokens may expire prior to any expected lifetime of them as well.” -- OAuth2 Refresh Tokens

    We recommend the following expiration settings for access and refresh tokens.

    1. Access token expiration: 15 minutes, never longer than an hour
    2. Refresh token expiration: 10 hours , never longer than a day
    3. Inactivity expiration: 2-3 hours, expire if the refresh token is not used. Inactivity should be something like half the refresh expiration time. It needs to account for reasonable inactivity, would you get annoyed if you came back from lunch and needed to relog in? Our guess is probably.

Not all of the authentication systems support an inactivity policy, despite it being defined in the OAuth2 standard (it is currently not supported by Cognito). 

Adjusting Access Token Settings in Okta

Okta settings must be reviewed via their Web UI and you need to have API access. The Okta access policies apply to a particular OpenID Connect application and can define different access and refresh token lifetimes.

  • The default access token expiration is 60 minutes; 
  • the default refresh token expiration is 7 days;
  • And the default inactivity expiration is 10800 minutes (7.5 days).  

These settings are very permissive. They leave open the exact opportunity that was exploited in the breach at Okta. We recommend shorter token expirations (see above). 

Adjusting Access Token Settings in Keycloak:

Keycloak allows the configuration of these settings in the Sessions and Tokens tabs in the Realm settings menu. 

  • Access Token Lifespan default is 1 min 
  • SSO Session Max is the refresh_token expiration: 10 hours by default
  • SSO Session Idle is 30 minutes (equivalent to refresh token inactivity expiration in Okta)

Much more secure by default, but you are allowed to shoot yourself into the knee and create less secure configurations. 

Adjusting Access Token Settings in AWS Cognito:

The default access token expiry and refresh token expiry are: 

  • Access tokens: 10 hours
  • Refresh tokens: 30 days
  • There appears to be no idle setting 

These settings are what we would call dangerous defaults, basically, please, please, please don’t do this. You need to update the AWS default settings to something that is more secure. .

For Keycloak and AWS Cognito, the access token expiry settings can be managed via configuration files (Keycloak) or cloud orchestration tools like CloudFormation/TF/Ansible (Cognito). All of these settings can be extracted and evaluated using CoGuard. 

pip3 install coguard-cli
coguard cloud aws 

Defense in Depth

Defense in depth is a security strategy that employs multiple layers of protection to safeguard systems. It involves a combination of technical measures, such as access limitation by VPN or IP address along with procedural controls. This multi-layered approach aims to mitigate the impact of a security breach by creating obstacles at various levels, making it harder for adversaries to compromise the entire system. It's like having a series of locked doors—each providing a barrier, enhancing overall security.

At CoGuard, we believe that the configuration of the authentication system can include these additional protections of robust authentication mechanisms across all layers of the infrastructure. 

The first step is to uncover any blind spots in your configurations of your infrastructure, containers and applications. CoGuard uses your existing configuration files or cloud configurations to evaluate the state of your infrastructure including your authentication system. 

Get started today by scanning your cloud configurations in 2 quick steps:

pip3 install coguard-cli
coguard cloud aws 

(Or switch aws for gcp or azure as your situation requires.)

Photo credit: Matteo Catanese on Unsplash

Explore a test environment

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Check out and explore a test environment to run infra audits on sample repositories of web applications and view select reports on CoGuard's interative dashboard today.