Notes: Understanding Cross-site Scripting (XSS) Attacks And Secure Authentication With Refresh Tokens

A cross-site scripting (XSS) attack injects malicious code into vulnerable web applications.

The idea behind XSS attacks is to execute malicious JavaScript in the user’s web browser.

In general, XSS attacks are based on the victim’s trust in a legitimate website or web application that is vulnerable (the general XSS premises).

When they succeed, the executed script can sniff the user’s cookies. If critical data is in the browser storage, it can be accessed.

Stored (Persistent) Cross-Site Scripting attack

This attack stores malicious scripts in the application server. The script can later be executed on the browser. It can affect more than one person. An example is the Twitter XSS attack.

Reflected (Non-Persistent) Cross-Site Scripting attack

The reflected XSS condition is met when a website or web application employs user input in HTML pages returned to the user’s browser, without validating the input first.

With Non-Persistent cross-site scripting, malicious code is executed by the victim’s browser, and the payload is not stored anywhere; instead, it is returned as part of the response HTML that the server sends.

DOM-based XSS

DOM-based XSS vulnerabilities usually arise when JavaScript takes data from an attacker-controllable source, such as the URL, and passes it to a sink that supports dynamic code execution, such as eval() or innerHTML.

Your website is vulnerable to this attack if any user's inputs in the URL appear in the DOM via methods like innerHTML.

This attack happens on the browser. It does not need a request/response cycle with the server to execute.

Your application server is vulnerable if it doesn’t do the following:

  • If it doesn’t validate user request data.

  • If it doesn’t sanitize data stored on the database.

  • If it doesn’t enable HTTP content-security policy. This prevents scripts from executing in the browser.

Protecting the DOM from XSS injection with React

Modern JavaScript libraries/frameworks like React.js ensure data rendered by the DOM are sanitized by default.

React.js is inspired by XHP. And XHP is a security fix written to minimize XSS attacks as much as possible.

React provides a way to render markup in the DOM from data, even though it is not allowed out of the box. We use the dangerouslySetInnerHTML property on React elements.

Additional Protection Against XSS Attacks

If your application requires you to render markup from data in the DOM, below are some measures to take.

  • To properly secure a user’s cookie, use the HttpOnly response headers.

  • Avoid using browser storage to save sensitive user information.

  • Use HTTP security headers such as Content Security Policy (CSP).

Secure Authentication Flow With Refresh tokens

  • Your authentication has two tokens: the access token and the refresh token.

  • The access token is used to get resources that require authentication from the API. It has a short duration. They are first created with login credentials along with the refresh tokens. As long as the refresh token has not yet expired, credentials are not needed to create access tokens. It is returned in the authentication response body.

  • Use the refresh token to create new access tokens. It has a longer duration. Refresh tokens are created when the user logs in with credentials. They are in the authentication response cookie.

  • Set the refresh token cookie with the httpOnly flag to prevent access via browser JavaScript. Use the secure=true flag so it can only be sent over HTTPS.

  • Save the access token in memory on the front end. Avoid using local storage. Refresh the access token for each page by making a call to the API to refresh.