okta/okta-spring-boot

Default configuration causes pre-flight CORS request OPTIONS fail with HTTP 401

indiepopart opened this issue · 2 comments

ℹ️ If you have a question, please post it on the Okta Developer Forum instead. Issues in this repository are reserved for bug reports and feature requests only.

I'm submitting a

  • bug report
  • feature request

Background info

Discovered while configuring a Spring for GraphQL server, and sending requests from a React client. Pre-flight CORS request OPTIONS, sent without authorization header, fails with okta-starter default auto-configuration. A workaround is to add explicit Oauth2ResourceServer configuration.

Expected behavior

Pre-flight requests should not require authentication?

What went wrong?

The API call fails, due to the pre-flight request failing with 401.

HTTP/1.1 401
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Length: 0
Date: Mon, 25 Sep 2023 22:47:02 GMT
Expires: 0
Keep-Alive: timeout=60
Pragma: no-cache
WWW-Authenticate: Bearer
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 0

Steps to reproduce

  1. git clone https://github.com/spring-guides/gs-graphql-server.git
  2. Add implementation 'com.okta.spring:okta-spring-boot-starter:3.0.5' to build.gradle
  3. Add spring.graphql.cors.allowed-origins=http://localhost:3000 to application.properties
  4. Configure the okta-starter in application.properties, add
    okta.oauth2.issuer, okta.oauth2.clientId, okta.oauth2.clientSecret, okta.oauth2.audience
  5. Run the application ./gradlew bootRun
  6. Request OPTIONS:
http -p Hhb OPTIONS http://localhost:8080/graphql \
  Origin:http://localhost:3000 \
  Sec-Fetch-Dest:empty \
  Sec-Fetch-Mode:cors \
  Sec-Fetch-Site:same-site \
  Referer:http://localhost:3000/ \
  User-Agent:"Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/117.0" \
  Host:localhost:8080 \
  Access-Control-Request-Method:POST \
  Accept:"*/*" \
  Accept-Language:"es-AR,en-US;q=0.7,en;q=0.3" \
  Access-Control-Request-Headers:"authorization,content-type" \
  DNT:1 \
  Accept-Encoding:"gzip, deflate, br"

Response is 401

Workaround:
Edit GraphqlServerApplication class and add resource server configuration:

	@Bean
	public SecurityFilterChain configure(HttpSecurity http) throws Exception {
		http.oauth2ResourceServer(oauth2ResourceServer -> oauth2ResourceServer.jwt(withDefaults()));
		return http.build();
	}

Response is 200

SDK Version

com.okta.spring:okta-spring-boot-starter:3.0.5

------------------------------------------------------------
Gradle 7.6
------------------------------------------------------------

Build time:   2022-11-25 13:35:10 UTC
Revision:     daece9dbc5b79370cc8e4fd6fe4b2cd400e150a8

Kotlin:       1.7.10
Groovy:       3.0.13
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.5 (Eclipse Adoptium 17.0.5+8)
OS:           Linux 5.4.0-163-generic amd64

@indiepopart you're right, Pre-flight requests should NOT require authentication. Can you clarify which server (Okta's?) is returning 401 in your above example?

Closing this due to inactivity, please reopen if necessary.