15 Secure Oracle JET Apps

Oracle JET follows security best practices for Oracle JET components and provides the OAuth class to help you manage access to users' private data.

About Securing Oracle JET Apps

Oracle JET apps are client-side HTML apps written in JavaScript, and you should follow best practices for securing your Oracle JET apps.

There are a number of Internet resources available that can assist you, including the Open Web Application Security Project (OWASP), Web Application Security Project (WASP), Web Application Security Working Group (WASWG), and various commercial sites.

Oracle JET Components and Security

Oracle JET components follow best practices for security. In particular:

  • All JavaScript code is executed in strict mode using the use strict directive.

    Strict mode changes warnings about poor syntax, such as using undeclared variables, into actual errors that you must correct. For more information, see http://www.w3schools.com/js/js_strict.asp.

  • Oracle JET code does not use inline script elements.

    Because browsers can't tell where the inline script originated, the World Wide Web Consortium (W3C) Content Security Policy prohibits the use of inline scripts. For additional information, see https://w3c.github.io/webappsec/specs/content-security-policy.

  • Oracle JET code does not generate random numbers.

  • Any HTML generated by an Oracle JET component is either escaped or sanitized.

Oracle JET Security and Developer Responsibilities

Oracle JET components follow established security guidelines and ensure that strings provided as options and user input will never be executed as JavaScript to prevent XSS attacks. However, Oracle JET does not include a mechanism for sanitizing strings, and you should consult established guidelines for dealing with XSS attacks in your own code and content.

You can find more information about securing JavaScript apps in the DOM based XSS Prevention Cheat Sheet.

Oracle JET Security Features

The Oracle JET API provides the OAuth authorization plugin which supports the OAuth 2.0 open protocol. OAuth standardizes the way desktop and web apps access a user's private data. It provides a mechanism for users to grant access to private data without sharing their private username and password credentials.

OAuth 2.0 defines the following roles:

  • Resource owner: An entity that can grant access to a protected resource, such as the end user.

  • Client: app making protected and authorized resource requests on behalf of the resource owner.

  • Resource server: Server hosting the protected resources that can accept and respond to protected resource requests using access tokens.

  • Authorization server: Server that issues access tokens to the client after it successfully authenticates the resource owner and obtains authorization. The authorization server can be the same server as the resource server. In addition, an authorization server can issue access tokens accepted by multiple resource servers.

OAuth 2.0 Request for Comments (RFC) 6749 describes the interaction between the four roles as an abstract flow.

  1. The client requests authorization from the resource owner, either directly or through the authorization server. Note that the RFC specifies that the authorization server is preferred.

  2. The client receives an authorization grant, which is defined as the credential representing the resource owner's authorization.

  3. The client requests an access token from the authorization server by authenticating with the server and presenting the authorization grant.

  4. The authorization server issues the access token after authenticating the client and validating the authorization grant.

  5. The client presents the access token to the resource server and requests the protected resource.

  6. The resource server validates the access token and serves the request if validated.

The access token is a unique identifier issued by the server and used by the client to associate authenticated requests with the resource owner whose authorization is requested or has been obtained by the client.

The Oracle JET OAuth plugin provides functions for the following tasks:

  • Getting access token credentials if initialized by client credentials.

  • Caching access token credentials.

  • Creating the header array with bearer token.

For details about using the OAuth plugin, see Use OAuth in Your Oracle JET App. For additional information about OAuth 2.0, see https://tools.ietf.org/html/rfc6749.

Oracle JET Secure Response Headers

Oracle JET recommends the usage of HTTP response headers to securely host your JET web application. These response headers protect your web applications from cross scripting attacks (XSS) attacks, packet sniffing, and clickjacking.

You must configure these response headers on the server where the JET application is hosted. As the configuration of these response headers is dependent on the type of server, you must refer to the documentation of your server for configuration steps.

You must use the secure response headers to notify the user agent to only connect to a given site over HTTPS and load all resources over secure channels to control XSS attacks and packet sniffing. You can configure the response header in the server to specify the protocols that are allowed to be used; for example, a server can specify that all content must be loaded using HTTPS protocol.

It is highly recommended to host your JET app using the HTTPS protocol to reduce the cross scripting attacks or packet sniffing. Also some of the new browser features only work under HTTPS protocol. The below table lists some of the secure response headers along with the HTTPS column that indicates which of these headers are specific for HTTPS based configuration.

Table 15-1 Secure Response Header Options

Option Value HTTPS Related Description

Content-Security-Policy

See Table 15-2, Content-Security-Policy Header Options.

No

Specifies fine-grained resource access.

X-XSS-Protection

1; mode=block

No

Blocks a page when cross site scripting attempt is detected.

NOTE:

  • The X-XSS-Protection directive is a defense-in-depth mechanism to mitigate the effect of reflected XSS vulnerabilities and does not detect or block persistent or DOM based XSS attacks. Apps must still perform proper input validation on the server and output encoding as the primary defense against XSS.

  • Mozilla Firefox does not implement cross site scripting protection.

X-Permitted-Cross-Domain-Policies

none

No

Cross-domain policy file is an XML document that grants a web client permission to handle data across domains.

X-Frame-Options

deny

No

Prevents clickjacking for browsers. This directive can only be set using an HTTP response header. To frame your content from the same origin, use sameorigin. If hosted by known host(s), specify allow-frame hostname.

NOTE:

  • If a request contains both a CSP frame-ancestors and X-Frame-Options directive, browsers that support both will ignore the X-Frame-Options directive in favor of the standardized CSP frame-ancestors directive.

  • The allow-frame directive does not support wildcards.

X-Content-Type-Options

nosniff

No

Ensures browser uses MIME type to determine the content type. Use of this directive with images requires the image format to match its specified MIME type. Use of this directive on JavasSript files requires the MIME type to be set to text/javascript.

Strict-Transport-Security

max-age=<secs>; includeSubDomains

Yes

Tells the browser to communicate only with the specified site (and any subdomains) over HTTPS and prevents the user from overriding an invalid or self-signed certificate.

Referrer-Policy

no-referrer

No

Tells the browser to include referrer information on outbound link requests.

Public-Key-Pins

pin-sha256="<sha256>"; max-age=<secs>

Yes

Prevents use of incorrect or fraudulent certificates.

Expect-CT

max-age=86400, enforce

Yes

Signals to the browser that compliance to the Certificate Transparency Policy should be enforced.

Content Security Policy Headers

Content Security Policy (CSP) is delivered through an HTTP response header and controls the resources that an Oracle JET web app can use.

The CSP header provides a mechanism to restrict the locations from which JavaScript running in a browser can load the required resources, restrict the execution of JavaScript, and control situations in which a page can be framed. This can mitigate Cross Site Scripting (XSS) vulnerabilities as well as provide protection against clickjacking attacks.

You should enable CSP for browsers to help the server administrators reduce or eliminate the attacks by specifying the domains that the browser should consider to be valid sources for loading executable scripts, stylesheets, images, fonts, and so on. See the Browser Compatibility Matrix for the browser versions that support CSP.

Configuring CSP involves adding the Content-Security-Policy HTTP header to a web page and giving it values to control resources the user agent is allowed to load for that page. To add Content-Security-Policy HTTP header to a web page, configure your web server to return the Content-Security-Policy HTTP response header. For example, here is a basic CSP response header, where script-src directive specifies an executable script as the resource type and 'self' is a constant that specifies the current domain as the approved source that the browser may load script from:

Content-Security-Policy: script-src 'self'

CSP has some of the following commonly used constants:

  • 'none': Blocks the use of certain resource type.

  • 'self': Matches the current origin (but not subdomains).

  • 'unsafe-eval': Allows the use of mechanisms like eval().

    Note as an alternative to the unsafe-eval CSP domain, JET provides an expression evaluator that allows JET expression syntax to be evaluated in a way that is compliant with Content Security Policies that prohibit unsafe evaluations. The default CSP use of the unsafe-eval domain remains unchanged, but apps can opt into the JET behavior with some restrictions on the types of expressions that are supported. See details on creation, usage, supported expressions and limitations in the CspExpressionEvaluator API documentation.

Alternatively, you can also use the HTML meta tags to configure CSP. For example:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; frame-src 'none';">

Note that some of the CSP directives do not work with the HTML meta tags, for example frame-ancestors.

The below table describes the out-of-box settings required by a JET web app to run in its most secure mode without changing the JET functionality. The JET web app may need to modify these settings for additional resource origins. The table lists the different response header directives that can be used while enabling CSP based on the two following scenarios:

  • Co-Hosted: When the JET and the app source codes are hosted on the same server

  • Content Delivery Network (CDN): When the JET code is from the JET CDN and the app code is from a different server

Table 15-2 Content-Security-Policy Header Options

CSP Version Header Options Co-Hosted CDN Description

CSP 1.0

default-src

'none'

'none'

Serves as a default setting that ensures resource loading is blocked if the resource type is not specified. All other settings need to be explicitly enabled for specific resource origins.

CSP 1.0

connect-src

'self'

'self'

Manages the REST and Web Sockets to be accessed.

CSP 1.0

font-src

'self'

'self' static.oracle.com

Specifies valid sources for fonts.

CSP 1.0

img-src

data: 'self'

'self' data: static.oracle.com

Specifies valid sources for images. Allows JET inline images.

CSP 1.0

media-src

'none'

'none'

Specifies valid sources for loading media using the <audio>, <video>, and <track> elements.

CSP 1.0

object-src

'none'

'none'

Specifies valid sources for the <object>, <embed>, and <applet> elements.

CSP 1.0

script-src

'self' 'unsafe-eval'

'self' static.oracle.com 'unsafe-eval';

Specifies valid sources for JavaScript. This directive is used for knockout expressions and JET function creation.

Note: The use of unsafe-eval is currently required by Knockout to resolve expressions, but JET provides an alternative expression evaluator when you require your app to run in a strict Content Security Policy environment. For usage information, see the CspExpressionEvaluator API documentation.

CSP 1.0

sandbox

-

-

Runs the page as in a sandboxed iframe.

CSP 2.0

form-action

-

-

This directive is used for form submits. Not applicable for JET.

CSP 2.0

frame-ancestors

'none'

'none'

Specifies valid sources for nested browsing contexts loading using elements such as <frame> and <iframe> and prevents clickjacking for browsers. This directive can only be set using an HTTP response header. To frame your content from the same origin, use 'self'. If hosted by known host(s), specify the hosts.

When default-src is set to none, you must explicitly enable all the other needed settings for specific resource origins.

The following example shows how to set up CSP if a website administrator wants to allow content from a trusted domain and all its subdomains:

Content-Security-Policy: default-src 'self' *.trusted.com

The following example shows how to set up CSP if a website administrator wants to allow users of a web app to include images from any origin in their own content, but to restrict audio or video media to trusted providers, and all scripts only to a specific server that hosts trusted code.

Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com

Use OAuth in Your Oracle JET App

You can use the OAuth plugin to manage access to client (end user) private data. The Oracle JET API includes the OAuth class which provides the methods you can use to initialize the OAuth object, verify initialization, and calculate the authorization header based on client credentials or access token.

Initialize OAuth

You can create an instance of a specific OAuth object using the OAuth constructor:

new OAuth(header, attributes)

The attributes and header parameters are optional.

Parameter Type Description

header

String

MIME Header name. Defaults to Authorization

attributes

Object

Contains client credentials or access/bearer token.

Client credentials contain:

  • client_id (required): public client Credentials

  • client_secret (required): secret client credentials

  • bearer_url (required): URL for token bearer and refresh credentials

  • Additional attributes as needed (optional)

Access/bearer tokens contain:

  • access_token (required): Bearer token

  • Additional attributes as needed (optional)

The code sample below shows three examples for initializing OAuth.

// Initialize OAuth with client credentials
var myOAuth = new OAuth('X-Header', {...Client credentials...});

// Initialize OAuth with token credentials
var myOAuth = new OAuth('X-Header', {...Access/Bearer token...});

// Initialize OAuth manually
var myOAuth = new OAuth();

If you choose to initialize OAuth manually, you can add the client credentials or access/bearer token using methods shown in the following code sample.

// Initializing client credentials manually
myOAuth.setAccessTokenRequest({...Client Credentials ...});
myOAuth.clientCredentialGrant();

// Initializing access bearer token manually
myOAuth.setAccessTokenResponse({...Access Token...});

The OAuth API also includes methods for getting and cleaning the client credentials or access tokens. For additional information, see the OAuth API documentation.

Verify OAuth Initialization

Use the isInitialized() method to verify that the initialization succeeded.

var initFlag = myOAuth.isInitialized();

Obtain the OAuth Header

Use the getHeader() method to get the OAuth header. The method calculates the authorization header based on the client credentials or access token.

// Client credentials
var myOAuth = new OAuth('New-Header', {...Client credentials...});
var myHeaders =  myOAuth.getHeader();

// Access token
var myOAuth = new OAuth('New-Header', {...Access/Bearer token...});
var myHeaders =  myOAuth.getHeader();

// Manual initialization, client credentials
var myOAuth = new OAuth();
myOAuth.setAccessTokenRequest({...Client credentials...});
var myHeaders =  myOAuth.getHeader();

// Manual initialization, access token
var myOAuth = new OAuth('New-Header', {...Access/Bearer token...});
var myHeaders =  myOAuth.getHeader();

About Cross-Origin Resource Sharing (CORS)

CORS is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served. The same-origin security policy of JavaScript forbids certain cross-domain requests, notably Ajax requests, by default.

Rejected resource requests due to CORS can affect web apps. Apps that encounter a rejection receive messages such as the following example in response to resource requests:

No 'Access-Control-Allow-Origin' header is present on the requested resource.

Server-side administrators can specify the origins allowed to access their resources by modifying the policy used by their remote server to allow cross-site requests from trusted clients. For example, to access a remote service managed by Oracle’s Mobile Cloud Service (MCS), an MCS administrator configures MCS’s Security_AllowOrigin environment policy with a comma-separated list of URL patterns that identify the remote services that serve resources from different domains.

If you serve your web app to the local browser for testing, you may encounter CORS rejections. Some browsers provide options to disable CORS, such as Chrome's --disable-web-security and Firefox's security.fileuri.strict_origin_policy and some browsers support plugins that work around CORS.

Only use these options when testing your app and ensure that you complete further testing in a production-like environment without these options to be sure that your app will not encounter CORS issues in production.