GithubHelp home page GithubHelp logo

openliberty / guide-cors Goto Github PK

View Code? Open in Web Editor NEW
7.0 6.0 10.0 277 KB

A guide on how to enable Cross-Origin Resource Sharing (CORS) in Open Liberty: https://openliberty.io/guides/cors.html

License: Other

Java 74.63% HTML 17.85% Shell 7.52%

guide-cors's Introduction

Enabling Cross-Origin Resource Sharing (CORS)

Note
This repository contains the guide documentation source. To view the guide in published form, view it on the Open Liberty website.

Learn how to enable Cross-Origin Resource Sharing (CORS) in Open Liberty without writing Java code.

What you’ll learn

You will learn how to add two Liberty configurations to enable CORS. Next, you will write and run tests to validate that the CORS configurations work. These tests send two different CORS requests to a REST service that has two different endpoints.

CORS and its purpose

Cross-Origin Resource Sharing (CORS) is a W3C specification and mechanism that you can use to request restricted resources from a domain outside the current domain. In other words, CORS is a technique for consuming an API served from an origin different than yours.

CORS is useful for requesting different kinds of data from websites that aren’t your own. These types of data might include images, videos, scripts, stylesheets, iFrames, or web fonts.

However, you cannot request resources from another website domain without proper permission. In JavaScript, cross-origin requests with an XMLHttpRequest API and Ajax cannot happen unless CORS is enabled on the server that receives the request. Otherwise, same-origin security policy prevents the requests. For example, a web page that is served from the http://aboutcors.com server sends a request to get data to the http://openliberty.io server. Because of security concerns, browsers block the server response unless the server adds HTTP response headers to allow the web page to consume the data.

Different ports and different protocols also trigger CORS. For example, the http://abc.xyz:1234 domain is considered to be different from the https://abc.xyz:4321 domain.

Open Liberty has built-in support for CORS that gives you an easy and powerful way to configure the runtime to handle CORS requests without the need to write Java code.

Types of CORS requests

Familiarize yourself with two kinds of CORS requests to understand the attributes that you will add in the two CORS configurations.

Simple CORS request

According to the CORS specification, an HTTP request is a simple CORS request if the request method is GET, HEAD, or POST. The header fields are any one of the Accept, Accept-Language, Content-Language, or Content-Type headers. The Content-Type header has a value of application/x-www-form-urlencoded, multipart/form-data, or text/plain.

When clients, such as browsers, send simple CORS requests to servers on different domains, the clients include an Origin header with the original (referring) host name as the value. If the server allows the origin, the server includes an Access-Control-Allow-Origin header with a list of allowed origins or an asterisk (*) in the response back to the client. The asterisk indicates that all origins are allowed to access the endpoint on the server.

Preflight CORS request

A CORS request is not a simple CORS request if a client first sends a preflight CORS request before it sends the actual request. For example, the client sends a preflight request before it sends a DELETE HTTP request. To determine whether the request is safe to send, the client sends a preflight request, which is an OPTIONS HTTP request, to gather more information about the server. This preflight request has the Origin header and other headers to indicate the HTTP method and headers of the actual request to be sent after the preflight request.

Once the server receives the preflight request, if the origin is allowed, the server responds with headers that indicate the HTTP methods and headers that are allowed in the actual requests. The response might include more CORS-related headers.

Next, the client sends the actual request, and the server responds.

Enabling CORS

Navigate to the start directory to begin.

You will use a REST service that is already provided for you to test your CORS configurations. You can find this service in the src/main/java/io/openliberty/guides/cors/ directory.

You will send a simple request to the /configurations/simple endpoint and the preflight request to the /configurations/preflight endpoint.

Enabling a simple CORS configuration

Configure the Liberty to allow the /configurations/simple endpoint to accept a simple CORS request. Add a simple CORS configuration to the Liberty server.xml configuration file:

Replace the Liberty server.xml configuration file.
src/main/liberty/config/server.xml

server.xml

link:finish/src/main/liberty/config/server.xml[role=include]

The CORS configuration contains the following attributes:

Configuration Attribute Value

domain

The endpoint to be configured for CORS requests. The value is set to /configurations/simple.

allowedOrigins

Origins that are allowed to access the endpoint. The value is set to http://openliberty.io.

allowedMethods

HTTP methods that a client is allowed to use when it makes requests to the endpoint. The value is set to GET.

allowCredentials

A boolean that indicates whether the user credentials can be included in the request. The value is set to true.

exposeHeaders

Headers that are safe to expose to clients. The value is set to MyHeader.

For more information about these and other CORS attributes, see the cors element documentation.

Save the changes to the server.xml configuration file. The /configurations/simple endpoint is now ready to be tested with a simple CORS request.

The Open Liberty instance was started in dev mode at the beginning of the guide and all the changes were automatically picked up.

Now, test the simple CORS configuration that you added. Add the testSimpleCorsRequest method to the CorsIT class.

Replace the CorsIT class.
src/test/java/it/io/openliberty/guides/cors/CorsIT.java

CorsIT.java

link:finish/src/test/java/it/io/openliberty/guides/cors/CorsIT.java[role=include]

The testSimpleCorsRequest test simulates a client. It first sends a simple CORS request to the /configurations/simple endpoint, and then it checks for a valid response and expected headers. Lastly, it prints the response headers for you to inspect.

The request is a GET HTTP request with the following header:

Request Header Request Value

Origin

The value is set to http://openliberty.io. Indicates that the request originates from http://openliberty.io.

Expect the following response headers and values if the simple CORS request is successful, and the Liberty instance is correctly configured:

Response Header Response Value

Access-Control-Allow-Origin

The expected value is http://openliberty.io. Indicates whether a resource can be shared based on the returning value of the Origin request header http://openliberty.io.

Access-Control-Allow-Credentials

The expected value is true. Indicates that the user credentials can be included in the request.

Access-Control-Expose-Headers

The expected value is MyHeader. Indicates that the header MyHeader is safe to expose.

Because you started Open Liberty in dev mode, you can run the tests by pressing the enter/return key from the command-line session where you started dev mode.

If the testSimpleCorsRequest test passes, the response headers with their values from the endpoint are printed. The /configurations/simple endpoint now accepts simple CORS requests.

Response headers with their values from the endpoint:

--- Simple CORS Request ---
Header null = [HTTP/1.1 200 OK]
Header Access-Control-Expose-Headers = [MyHeader]
Header Access-Control-Allow-Origin = [http://openliberty.io]
Header Access-Control-Allow-Credentials = [true]
Header Content-Length = [22]
Header Content-Language = [en-CA]
Header Date = [Thu, 21 Mar 2019 17:50:09 GMT]
Header Content-Type = [text/plain]
Header X-Powered-By = [Servlet/4.0]

Enabling a preflight CORS configuration

Configure the Liberty to allow the /configurations/preflight endpoint to accept a preflight CORS request. Add another CORS configuration in the Liberty server.xml configuration file:

Replace the Liberty server.xml configuration file.
src/main/liberty/config/server.xml

server.xml

link:finish/src/main/liberty/config/server.xml[role=include]

The preflight CORS configuration has different values than the simple CORS configuration.

Configuration Attribute Value

domain

The value is set to /configurations/preflight because the domain is a different endpoint.

allowedOrigins

Origins that are allowed to access the endpoint. The value is set to an asterisk (*) to allow requests from all origins.

allowedMethods

HTTP methods that a client is allowed to use when it makes requests to the endpoint. The value is set to OPTIONS, DELETE.

allowCredentials

A boolean that indicates whether the user credentials can be included in the request. The value is set to true.

The following attributes were added:

  • allowedHeaders: Headers that a client can use in requests. Set the value to MyOwnHeader1, MyOwnHeader2.

  • maxAge: The number of seconds that a client can cache a response to a preflight request. Set the value to 10.

Save the changes to the server.xml configuration file. The /configurations/preflight endpoint is now ready to be tested with a preflight CORS request.

Add another test to the CorsIT.java file to test the preflight CORS configuration that you just added:

Replace the CorsIT class.
src/test/java/it/io/openliberty/guides/cors/CorsIT.java

CorsIT.java

link:finish/src/test/java/it/io/openliberty/guides/cors/CorsIT.java[role=include]

The testPreflightCorsRequest test simulates a client sending a preflight CORS request. It first sends the request to the /configurations/preflight endpoint, and then it checks for a valid response and expected headers. Lastly, it prints the response headers for you to inspect.

The request is an OPTIONS HTTP request with the following headers:

Request Header Request Value

Origin

The value is set to anywebsiteyoulike.com. Indicates that the request originates from anywebsiteyoulike.com.

Access-Control-Request-Method

The value is set to DELETE. Indicates that the HTTP DELETE method will be used in the actual request.

Access-Control-Request-Headers

The value is set to MyOwnHeader2. Indicates the header MyOwnHeader2 will be used in the actual request.

Expect the following response headers and values if the preflight CORS request is successful, and the Liberty instance is correctly configured:

Response Header Response Value

Access-Control-Max-Age

The expected value is 10. Indicates that the preflight request can be cached within 10 seconds.

Access-Control-Allow-Origin

The expected value is anywebsiteyoulike.com. Indicates whether a resource can be shared based on the returning value of the Origin request header anywebsiteyoulike.com.

Access-Control-Allow-Methods

The expected value is OPTIONS, DELETE. Indicates that HTTP OPTIONS and DELETE methods can be used in the actual request.

Access-Control-Allow-Credentials

The expected value is true. Indicates that the user credentials can be included in the request.

Access-Control-Allow-Headers

The expected value is MyOwnHeader1, MyOwnHeader2. Indicates that the header MyOwnHeader1 and MyOwnHeader2 are safe to expose.

The Access-Control-Allow-Origin header has a value of anywebsiteyoulike.com because the Liberty is configured to allow all origins, and the request came with an origin of anywebsiteyoulike.com.

Because you started Open Liberty in dev mode, you can run the tests by pressing the enter/return key from the command-line session where you started dev mode.

If the testPreflightCorsRequest test passes, the response headers with their values from the endpoint are printed. The /configurations/preflight endpoint now allows preflight CORS requests.

Response headers with their values from the endpoint:

--- Preflight CORS Request ---
Header null = [HTTP/1.1 200 OK]
Header Access-Control-Allow-Origin = [anywebsiteyoulike.com]
Header Access-Control-Allow-Methods = [OPTIONS, DELETE]
Header Access-Control-Allow-Credentials = [true]
Header Content-Length = [0]
Header Access-Control-Max-Age = [10]
Header Date = [Thu, 21 Mar 2019 18:21:13 GMT]
Header Content-Language = [en-CA]
Header Access-Control-Allow-Headers = [MyOwnHeader1, MyOwnHeader2]
Header X-Powered-By = [Servlet/4.0]

You can modify the Liberty configuration and the test code to experiment with the various CORS configuration attributes.

Great work! You’re done!

You enabled CORS support in Open Liberty. You added two different CORS configurations to allow two kinds of CORS requests in the Liberty server.xml configuration file.

guide-cors's People

Contributors

ahmad-ayyoub avatar andrewdes avatar austinseto avatar cajaygle avatar chyt avatar dependabot[bot] avatar evelinec avatar gkwan-ibm avatar jakub-pomykala avatar justineechen avatar kinueng avatar kubik42 avatar maihameed avatar nimg98 avatar proubatsis avatar rutavshah avatar saumyapandyaa avatar sishida avatar siwany avatar t27gupta avatar tt-le avatar wasdevb1 avatar yeekangc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

guide-cors's Issues

Re-review for cors guide

What you’ll learn

  • perhaps instead of "Next, you will write and run tests..." you can say "Then, you will write and run tests..."

CORS and its purpose

  • "However, you cannot request resources from outside of your website domain without asking for permission from the other website domains." -> maybe change it to "However, you cannot request resources from another website's domain without proper permission"
  • "CORS is enabled on the server that is receiving the request"
  • maybe add "For example" to "A web page that is served from ..."
  • I think "Types of CORS requests" should be made into its own section

Enabling CORS

  • "Find the service in the start/src/main/java/io/openliberty/guides/cors/ directory." -> "You can find this service under the directory"
  • "Send the simple request to the /configurations/simple endpoint and the preflight request to the /configurations/preflight endpoint." -> this should probably use future tense like "You will send a simple request..."
  • "The simple CORS configuration contains the following attributes:" -> add these attributes into a table, it will look nicer
  • add "indent=0" to the code blocks to remove the indent
  • "The testSimpleCorsRequest test passes and prints ..." -> "If the testSimpleCorsRequest test case passed, then it will print ..."
  • "The preflight CORS configuration has different values than the simple CORS configuration." -> also put these into a table
  • "The testPreflightCorsRequest test passes and prints..." -> "If the testPreflightCorsRequest test case passed, then it will print ..."
  • "If you want, modify the server configuration and the test code to experiment with the various CORS configuration attributes." -> "Feel free to modify the server ..."

Great work! You’re done!

  • "You just enabled ..."

Incorrect statement

the following line is incorrect:

When clients, such as browsers, send simple CORS requests to servers on different domains, the clients include an Origin header with the client host name as the value.

The Origin header's value should not be the client (browser) host name - it should be the original (referring) host name.
So, for example, suppose I'm the client (on host: mymacbook), and I'm accessing weather.com which has a web page with some javascript in it to get the current time from time.gov. The Origin header on the request to time.gov would be weather.com , not mymacbook.

Multipane Issues

Enabling a simple CORS configuration

  • "Now we will test the simple CORS configuration that you added. Add the testSimpleCorsRequest method to..." -> The testSimpleCorsRequest hotspot does not highlight the method, it just changes to the file. This should either be re-worded, or the hotspot should highlight the method.
  • Should the true and MyHeader in the value section of the 3rd table be hotspotted? Similar values are hotspotted in the enabling a preflight CORS configuration section

Enabling a preflight CORS configuration

  • "Add two new attributes:" -> The bolded hotspots look really awkward. I think this might work better in a bulleted list or something similar.

mvn package does not work as it describes.

mvn package does not work as it describes.
I found that the problem is caused by missing some configuration in the pom.xml file.

             <goals>
                <goal>package-server</goal>
              </goals>
         //this part is missing in pom.xml files for some guides, need to be added
             <configuration>
               <outputDirectory>target/wlp-package</outputDirectory>
             </configuration>
           

Not enough explanation of CORS values

I have forwarded another IBMer to this guide as they did not know much about how CORS works in Liberty. They came back to me stating that the guide does not really go into any detail about what all these CORS settings actually do and just tells you to set specific vaules. CORS in my opinion has very specific configuration for different environments so not having an explanation about what all these configurations do make this guide pointless and as a result I have then had to go and Google most of the information I require about CORS.

My advice is to just give one sentence about each configuration setting rather than saying just set this and the user just presume that is what they need.

Remove TM and R symbols in the guides.

The first sentence in this guide contains a "TM" next to "Java." We have decided to avoid using trademark symbols, so this symbol should be removed along with any others that might be present.

Change end section title

Change “Congratulations! You’re done!“-> “Great work! You’re done!”
And drop "Congratulations!" below it.

simple CORS example should use a scheme+hostname

finish/src/test/java/it/io/openliberty/guides/cors/TestData.java and the server.xml CORS config should use http://openliberty.io rather than a bare hostname.

Origin request headers and Access-Control-Allow-Origin response headers are scheme + host + optional port.

Unfortunately if you simulate a cross-origin request with a non browser and make the same mistake on both ends, the CORS Feature will echo back the hostname in the Origin header.

[a11y] Add headers to tables

For a11y, headers in the tables need to be marked as such, but currently they are just another row. Need to add options="header" to mark them as headers so that those columns render as <th> instead of <tr>

Multipane Issues

Checklist for Post-Review

Through the browser:

  • Read through guide, making sure that the flow of the guide is good
  • Click all links to make sure they lead to the correct place
  • Make sure hotspots, code_commands and files are correct
  • Run Acrolinx

Accessibility Verification Testing (AVT)

  • AVT 1 = Automated testing
  • AVT 2 = Manual testing
    • a picture requires alternative text to describe the image
    • table requires alternative text
    • test color contrast
    • test using keyboard instead of mouse
  • AVT 3 = Screen Reader testing
    • use JAWS screen reader

Daily build automation test failure

The recent daily build test automation for this guide has been failing with the following error:

[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.68 s <<< FAILURE! - in it.io.openliberty.guides.cors.CorsIT
[ERROR] testPreflightCorsRequest  Time elapsed: 0.22 s  <<< FAILURE!
org.opentest4j.AssertionFailedError: Unexpected value for Access-Control-Allow-Max-Age header ==> expected: <10> but was: <null>
	at it.io.openliberty.guides.cors.CorsIT.lambda$checkCorsResponse$0(CorsIT.java:69)
	at it.io.openliberty.guides.cors.CorsIT.checkCorsResponse(CorsIT.java:68)
	at it.io.openliberty.guides.cors.CorsIT.testPreflightCorsRequest(CorsIT.java:59)

After some investigation, looks like one of the header name had been changed from Access-Control-Allow-Max-Age to Access-Control-Max-Age (showed in the following output).

--- Preflight CORS Request - EC ---
Header null = [HTTP/1.1 200 OK]
Header Access-Control-Allow-Origin = [anywebsiteyoulike.com]
Header Access-Control-Allow-Methods = [OPTIONS, DELETE]
Header Access-Control-Allow-Credentials = [true]
Header Content-Length = [0]
**Header Access-Control-Max-Age = [10]**
Header Date = [Thu, 02 Jan 2020 21:07:37 GMT]
Header Content-Language = [en-CA]
Header Access-Control-Allow-Headers = [MyOwnHeader1, MyOwnHeader2]
Header X-Powered-By = [Servlet/4.0]

After updating the header name in the TestData.java, the test passed.

Links to docs for further config options

Consider linking from the guide to the config options doc: https://www.openliberty.io/docs/latest/reference/config/cors.html Eg in this guide there's a small table showing what config options have been used and what they mean. But there are other config options too that might be of interest (but shouldn't be included in the guide) so you could link to the docs for them.

This issue could be applied to all guides where there are other config options - just find the relevant config options in the OL docs.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.