Skip to main content
Skip table of contents

Securing Your Supported Complex Architecture

The more complex infrastructures tend to imply connecting applications that live under different private domains. This has some potential security impacts, that each user will appreciate based on the company’s rules and existing security measures.

A little reminder

OSLC interactions allow displaying previews of resource from OSLC Application B within OSLC Application A. To do that, OSLC Application A needs to be able to access the authentication token(s) from OSLC Application B. Those tokens are created using cookies when you log into OSLC Application B. Before the SameSite default value changed in modern browsers, the samesite default value was None and tokens from OSLC Application B were shared when OSLC Application A was displaying the preview of OSLC Application B’s resources. With the new default value Lax, the token is not sent anymore, hence the user enters sort of a login loop.

About the intent of this change

The major intent of this change is to contribute to securing web applications from CSRF vulnerabilities. This does not fix CSRF vulnerabilities but comes as a complement to CSRF tokens. OSLC Connect tools now provide support for these CSRF tokens, hence offering great security under a single private domain.

Resolving multiple domains architecture’s drawback

By using a reverse proxy on the same domain (recommended)

The most secure alternative is to avoid having to change the samesite value to None. To achieve that, we recommend creating a proxy server on the same domain as the other OSLC Application(s), then make sure this proxy server forwards all traffic to the OSLC Application it proxies. Taking the example of the Semi-SAAS architecture, we would end up with the below.

With this architecture, you will access oslc-b.servers.example.com which will silently forward to oslc-b.my.provider.cloud. As such, when OSLC Application A and OSLC Application B will interact, they will be on the same example.com domain. This requires both proxying OSLC Application B and updating its base url for OSLC services to run properly.

If not going for this solution, you will have to set SameSite to None on all OSLC Applications that are expected to communicate even though on different domains.

With SameSite=None set up as securely as possible… on SodiusWillert tools

In an effort to build the most secure solutions, we introduced the Web Security feature. For the “samesite”, what we have concluded is the following:

  • setting samesite to None by default for the whole OSLC Application allows for a proper OSLC interaction, but keeps the security limitation that lead to change the default value. That is particularly true of tools that are highly extensible and where we are one of many plugin providers, because other providers may be less careful on security as we are at SodiusWillert

  • only specific URLs are acessed by remote OSLC Applications so these ones, and only these ones, must get their samesite set to None

  • the consequence is that when you log into the OSLC Application, instead of going with a single cookie that provides the authentication token(s), that cookie will be duplicated for each path that needs to be accessed by remote OSLC Applications. All cookies have the same lifecycle since they are created at the same time, and with the same properties. This follows Google’s recommendation made after they introduced the None value, and avoids older browsers from failing to read the initial cookie.

Our Security feature has this strategy built right into our tools, offering them the most rigorous security possible without any change to the infrastructure.

With SameSite=None set up as securely as possible… using rewrite rules in a reverse proxy

When your application lies behind a reverse proxy that lives on a different domain as the other OSLC Application(s), you can still consider implementing some rules within the reverse proxy to enable sharing your application’s cookies as securely as possible.

For a SodiusWillert tool

At SodiusWillert, we provide plugins for applications that are highly extendable. As a consequence, we thrive to make our solutions as secure as possible by limiting the impact of our choices and recommendations on the operations of other plugins available on those applications. That led us to the implementation built inside our tools, which applies to most deployments out there. Still, some specific customizations might prevent a proper behavior of the built-in security features, which makes it handy to be able to reproduce that same behavior at the reverse proxy level.

Implementing a similar strategy as that of SodiusWillert’s tools at the reverse proxy level requires a few preliminary knowledge:

  1. what are the cookies that must be replicated?

  2. what are the path that should be remotely accessible?

  3. what are the URLs that should be checked for set-cookie headers with the aforementionned cookies? (optional - in case there’s a possibility to restrict those path)

A sample implementation of items 1 and 2 in Nginx would be similar to:

YAML
# In the below, we consider that we are interested in the cookie JSESSIONID,
# and that we want to open up 2 paths for OSLC Connect for Jira

# 1. capture the original cookie
http-response capture res.hdr(Set-Cookie) id 0

# 2. create rules based on a fixed variable to avoid having the changes we do to the set-cookie impact our actions
#    -> have we found the set-cookie header?
#    -> is this a set-cookie for the cookie I am interested in?
http-response set-var(txn.set_cookie) res.hdr(Set-Cookie)
acl foundSetCookie var(txn.set_cookie) -m beg "JSESSIONID="
acl foundSecure var(txn.set_cookie) -i -m reg "^JSESSIONID=(.*);\s+secure(.*)"
acl foundSameSite var(txn.set_cookie) -i -m reg "^JSESSIONID=(.*);\s+samesite=(.*)"
acl foundHttpOnly var(txn.set_cookie) -i -m reg "^JSESSIONID=(.*);\s+httponly(.*)"
acl foundPath var(txn.set_cookie) -i -m reg "^JSESSIONID=(.*);\s+path=(.*)"

# 3. alter the set-cookie to add SameSite=None;HttpOnly;secure (keeping Max-Age and Domain), and remove path
# 3.1 temporarily change the name of the cookie to avoid conflicts
http-response replace-header Set-Cookie (^JSESSIONID=.*) "SOWI1_\1" if foundSetCookie
# 3.2 remove path if present
http-response replace-header Set-Cookie (SOWI1_JSESSIONID=[^;]*)(;\s+[^;]*)*(;\ Path=/)(;\s+[^;]*)* "\1\2\4" if foundPath
# 3.3 add HttpOnly if missing
http-response replace-header Set-Cookie (SOWI1_JSESSIONID=.*) "\1; HttpOnly" if !foundHttpOnly
# 3.4 add samesite if missing
http-response replace-header Set-Cookie (SOWI1_JSESSIONID=.*) "\1; SameSite=None" if !foundSameSite
# 3.5 add secure if missing
http-response replace-header Set-Cookie (SOWI1_JSESSIONID=.*) "\1; Secure" if !foundSecure
# 3.6. set the path for that first samesite cookie
http-response replace-header Set-Cookie (SOWI1_JSESSIONID=.*) "\1; Path=/plugins/servlet/oslc/remote"


# 4. to replicate for each additional path to open
# 4.1 restore the original set-cookie
http-response add-header Set-Cookie "%[capture.res.hdr(0)]" if foundSetCookie
# 4.2 replay 3 with a different:
#      - SOWI key (SOWI1, SOWI2...) in all steps of 3 and
#      - path value in step 3.2
# e.g.:
http-response replace-header Set-Cookie (^JSESSIONID=.*) "SOWI2_\1" if foundSetCookie
http-response replace-header Set-Cookie (SOWI2_JSESSIONID=[^;]*)(;\s+[^;]*)*(;\ Path=/)(;\s+[^;]*)* "\1\2\4" if foundPath
http-response replace-header Set-Cookie (SOWI2_JSESSIONID=.*) "\1; HttpOnly" if !foundHttpOnly
http-response replace-header Set-Cookie (SOWI2_JSESSIONID=.*) "\1; SameSite=None" if !foundSameSite
http-response replace-header Set-Cookie (SOWI2_JSESSIONID=.*) "\1; Secure" if !foundSecure
http-response replace-header Set-Cookie (SOWI2_JSESSIONID=.*) "\1; Path=/rest/api/2/search"

# repeat for all urls that need to be accessible from outside the application

# 5. remove PATHX keys from each cookie
http-response replace-header Set-Cookie (SOWI\d_)(.*) "\2"
http-response replace-header Set-Cookie (SOWI\d_)(.*) "\2"
# here we do it twice because we have 2 paths to open up
# one must repeat this line as many times as the number of paths to open

# 6. restore the original set-cookie
http-response add-header Set-Cookie "%[capture.res.hdr(0)]" if foundSetCookie

To confirm proper behaviour after implementation, you may open a preview in a private browsing window in Firefox, then open the Browser Console (Ctrl+Shift+J), then do the login suggested by the preview page. Once done, go to the browser console and apply the filters in red in the below screenshot. You’ll see in the response headers multiple Set-Cookie headers: the original as well (in blue) as well as the new ones (in green).

The cookies and path to open up for each of the supported applications are the following:

Application

Jira

Cookies

JSESSIONID

Paths

/rest/oslc/1.0/remote

/rest/oslc/1.0/oauth/approveKey

/plugins/servlet/oslc/remote

/plugins/servlet/oslc/selectissue

/plugins/servlet/oslc/smallPreview

/plugins/servlet/oslc/largePreview

/rest/api/2/search

/rest/api/2/issue/picker

For a non SodiusWillert tool

When the OSLC enabled application is not provided by SodiusWillert, we recommend that you reach out to your solution provider for their recommendation. In 2021, their recommendation was:

Enabling Security Headers

There is quite a long list of headers that are meant to enhance the security to your websites. We only focus here on those that are related to OSLC

Content Security Policy

The Content-Security-Policy is an HTTP header that holds more than a few directives. Each directives serves a specific purpose to further strengthen the security of the web application.

The Web Security feature of OSLC Connect products will offer to manage that header directly. It will only manage the frame-ancestors and child-src directives. More directives may be added to further strengthen the security, but they are less related to OSLC, and hence were not included in the initial implementation.

frame-ancestors

The frame-ancestors directive tells modern browsers which websites are allowed to embed an OSLC Application’s data. This corresponds to the interactions an OSLC Application will have with its Consumers.

This can be directly managed by the Web Security feature in OSLC Connect tools.

child-src

The child-src directive tells modern browsers which OSLC Applications can be embedded by the current page. This corresponds to the interactions an OSLC Application will have with its Friends.

This can be directly managed by the Web Security feature in OSLC Connect tools.

Cross-Origin Opener Policy

This header controls the ability to share information between a document and any window it opens depending if they are on the same domain or not. OSLC interactions require that OSLC Application A is allowed to open a popup to OSLC Application B’s login and interact with the opened popup to achieve the OSLC authentication flow. As a consequence, if this header is present, its value must be same-origin-allow-popups.

Additional headers

The below additional headers are recommended to be added through the reverse proxy configuration.

X-Frame-Options

The X-Frame-Options header serves the same purpose as the CSP frame-ancestors directive, which superseeds it when both are available on most browser. It’s only useful where Internet Explorer 11 remains the mandatory browser. Anywhere an alternative browser is available, one should prefer the alternative since Internet Explorer 11 is end of life.

Strict-Transport-Security

The Strict-Transport-Security header is used to tell the browser that the website must only be accessed through HTTPS. As discussed above, OSLC Applications are expected to be accessed through HTTPS. As such, il makes most sense that this header is added by a reverse proxy.

Referrer-Policy

This header should always be set in modern deployments. Its value should be strict-origin-when-cross-origin. It is meant to avoid giving information about your server that is not required when your server redirects / opens a page to another website.

X-Content-Type-Options

This header should always be set in modern deployments. Its value should be nosniff.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.