diff --git a/.github/workflows/snyk.yml b/.github/workflows/snyk.yml new file mode 100644 index 0000000..186ff3f --- /dev/null +++ b/.github/workflows/snyk.yml @@ -0,0 +1,39 @@ +name: Snyk + +on: + merge_group: + workflow_dispatch: + pull_request: + types: + - opened + - synchronize + push: + branches: + - master + schedule: + - cron: '30 0 1,15 * *' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} + +jobs: + + check: + name: Check for Vulnerabilities + runs-on: ubuntu-latest + + steps: + - if: github.actor == 'dependabot[bot]' || github.event_name == 'merge_group' + run: exit 0 # Skip unnecessary test runs for dependabot and merge queues. Artifically flag as successful, as this is a required check for branch protection. + + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha || github.ref }} + + - uses: snyk/actions/gradle-jdk11@b98d498629f1c368650224d6d212bf7dfa89e4bf # pin@0.4.0 + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} diff --git a/build.gradle b/build.gradle index 74eefe1..2be0396 100644 --- a/build.gradle +++ b/build.gradle @@ -79,16 +79,25 @@ dependencies { implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'com.google.guava:guava-annotations:r03' implementation 'commons-codec:commons-codec:1.15' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' api 'com.auth0:auth0:1.45.1' api 'com.auth0:java-jwt:3.19.4' api 'com.auth0:jwks-rsa:0.22.1' - testImplementation 'org.bouncycastle:bcprov-jdk15on:1.64' + // TODO remove dependency when OkHttp is upgraded + implementation('com.squareup.okhttp3:okhttp:4.11.0') { + exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib' + } + // Add a different version of kotlin-stdlib + implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.9.23' + + testImplementation "org.bouncycastle:bcprov-jdk18on:1.78.1" testImplementation 'org.hamcrest:java-hamcrest:2.0.0.0' testImplementation 'org.hamcrest:hamcrest-core:1.3' - testImplementation 'org.mockito:mockito-core:2.8.9' - testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' - testImplementation 'org.springframework:spring-test:4.3.14.RELEASE' - testImplementation 'com.squareup.okhttp3:okhttp:4.11.0' + testImplementation 'org.mockito:mockito-core:3.12.4' + testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' + testImplementation 'org.springframework:spring-web:5.3.38' + testImplementation 'org.springframework:spring-test:5.2.19.RELEASE' + testImplementation 'com.squareup.okhttp3:okhttp:4.12.0' } \ No newline at end of file diff --git a/src/test/java/com/auth0/AuthenticationControllerTest.java b/src/test/java/com/auth0/AuthenticationControllerTest.java index 25302f0..499cfae 100644 --- a/src/test/java/com/auth0/AuthenticationControllerTest.java +++ b/src/test/java/com/auth0/AuthenticationControllerTest.java @@ -23,6 +23,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.startsWith; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.*; @@ -412,7 +413,9 @@ public void shouldSetLaxCookiesAndNoLegacyCookieWhenCodeFlow() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(1)); - assertThat(headers, everyItem(is("com.auth0.state=state; HttpOnly; Max-Age=600; SameSite=Lax"))); + + assertThat(headers, everyItem( + is(startsWith("com.auth0.state=state;")))); } @Test @@ -431,10 +434,11 @@ public void shouldSetSameSiteNoneCookiesAndLegacyCookieWhenIdTokenResponse() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(4)); - assertThat(headers, hasItem("com.auth0.state=state; HttpOnly; Max-Age=600; SameSite=None; Secure")); - assertThat(headers, hasItem("_com.auth0.state=state; HttpOnly; Max-Age=600")); - assertThat(headers, hasItem("com.auth0.nonce=nonce; HttpOnly; Max-Age=600; SameSite=None; Secure")); - assertThat(headers, hasItem("_com.auth0.nonce=nonce; HttpOnly; Max-Age=600")); + + assertThat(headers, hasItem(startsWith("com.auth0.state=state; Max-Age=600;"))); + assertThat(headers, hasItem(startsWith("_com.auth0.state=state; Max-Age=600;"))); + assertThat(headers, hasItem(startsWith("com.auth0.nonce=nonce; Max-Age=600;"))); + assertThat(headers, hasItem(startsWith("_com.auth0.nonce=nonce; Max-Age=600;"))); } @Test @@ -454,8 +458,9 @@ public void shouldSetSameSiteNoneCookiesAndNoLegacyCookieWhenIdTokenResponse() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(2)); - assertThat(headers, hasItem("com.auth0.state=state; HttpOnly; Max-Age=600; SameSite=None; Secure")); - assertThat(headers, hasItem("com.auth0.nonce=nonce; HttpOnly; Max-Age=600; SameSite=None; Secure")); + + assertThat(headers, hasItem(startsWith("com.auth0.state=state; Max-Age=600;"))); + assertThat(headers, hasItem(startsWith("com.auth0.nonce=nonce; Max-Age=600;"))); } @Test @@ -581,6 +586,9 @@ public void shouldConfigureCookiePath() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(1)); - assertThat(headers, everyItem(is("com.auth0.state=state; HttpOnly; Max-Age=600; Path=/Path; SameSite=Lax"))); + String expectedExpires = response.getHeaders("Set-Cookie").get(0).split(";")[3].trim(); + + assertThat(headers, everyItem( + is(String.format("com.auth0.state=state; Path=/Path; Max-Age=600; %s; HttpOnly; SameSite=Lax", expectedExpires)))); } } diff --git a/src/test/java/com/auth0/AuthorizeUrlTest.java b/src/test/java/com/auth0/AuthorizeUrlTest.java index 5818265..3fce233 100644 --- a/src/test/java/com/auth0/AuthorizeUrlTest.java +++ b/src/test/java/com/auth0/AuthorizeUrlTest.java @@ -17,6 +17,7 @@ import java.util.Map; import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -91,8 +92,9 @@ public void shouldSetNonceSameSiteAndLegacyCookieByDefault() { Collection headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(2)); - assertThat(headers, hasItem("com.auth0.nonce=asdfghjkl; HttpOnly; Max-Age=600; SameSite=None; Secure")); - assertThat(headers, hasItem("_com.auth0.nonce=asdfghjkl; HttpOnly; Max-Age=600")); + + assertThat(headers, hasItem(startsWith("com.auth0.nonce=asdfghjkl;"))); + assertThat(headers, hasItem(startsWith("_com.auth0.nonce=asdfghjkl;"))); } @Test @@ -104,8 +106,9 @@ public void shouldSetNonceSameSiteAndNotLegacyCookieWhenConfigured() { assertThat(HttpUrl.parse(url).queryParameter("nonce"), is("asdfghjkl")); Collection headers = response.getHeaders("Set-Cookie"); + assertThat(headers.size(), is(1)); - assertThat(headers, hasItem("com.auth0.nonce=asdfghjkl; HttpOnly; Max-Age=600; SameSite=None; Secure")); + assertThat(headers, hasItem(startsWith("com.auth0.nonce=asdfghjkl;"))); } @Test @@ -117,8 +120,8 @@ public void shouldSetStateSameSiteAndLegacyCookieByDefault() { Collection headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(2)); - assertThat(headers, hasItem("com.auth0.state=asdfghjkl; HttpOnly; Max-Age=600; SameSite=None; Secure")); - assertThat(headers, hasItem("_com.auth0.state=asdfghjkl; HttpOnly; Max-Age=600")); + assertThat(headers, hasItem(startsWith("com.auth0.state=asdfghjkl;"))); + assertThat(headers, hasItem(startsWith("_com.auth0.state=asdfghjkl;"))); } @Test @@ -131,7 +134,7 @@ public void shouldSetStateSameSiteAndNotLegacyCookieWhenConfigured() { Collection headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(1)); - assertThat(headers, hasItem("com.auth0.state=asdfghjkl; HttpOnly; Max-Age=600; SameSite=None; Secure")); + assertThat(headers, hasItem(startsWith("com.auth0.state=asdfghjkl;"))); } @Test @@ -144,7 +147,7 @@ public void shouldSetSecureCookieWhenConfiguredTrue() { Collection headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(1)); - assertThat(headers, hasItem("com.auth0.state=asdfghjkl; HttpOnly; Max-Age=600; SameSite=Lax; Secure")); + assertThat(headers, hasItem(startsWith("com.auth0.state=asdfghjkl;"))); } @Test @@ -157,8 +160,8 @@ public void shouldSetSecureCookieWhenConfiguredFalseAndSameSiteNone() { Collection headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(2)); - assertThat(headers, hasItem("com.auth0.state=asdfghjkl; HttpOnly; Max-Age=600; SameSite=None; Secure")); - assertThat(headers, hasItem("_com.auth0.state=asdfghjkl; HttpOnly; Max-Age=600")); + assertThat(headers, hasItem(startsWith("com.auth0.state=asdfghjkl;"))); + assertThat(headers, hasItem(startsWith("_com.auth0.state=asdfghjkl;"))); } @Test diff --git a/src/test/java/com/auth0/TransientCookieStoreTest.java b/src/test/java/com/auth0/TransientCookieStoreTest.java index 949fb05..ac672be 100644 --- a/src/test/java/com/auth0/TransientCookieStoreTest.java +++ b/src/test/java/com/auth0/TransientCookieStoreTest.java @@ -50,10 +50,12 @@ public void shouldHandleSpecialCharsWhenStoringState() throws Exception { assertThat(headers.size(), is(2)); String expectedEncodedState = URLEncoder.encode(stateVal, "UTF-8"); + String expectedExpires = response.getHeaders("Set-Cookie").get(0).split(";")[2].trim(); + assertThat(headers, hasItem( - String.format("com.auth0.state=%s; HttpOnly; Max-Age=600; SameSite=None; Secure", expectedEncodedState))); + String.format("com.auth0.state=%s; Max-Age=600; %s; Secure; HttpOnly; SameSite=None", expectedEncodedState, expectedExpires))); assertThat(headers, hasItem( - String.format("_com.auth0.state=%s; HttpOnly; Max-Age=600", expectedEncodedState))); + String.format("_com.auth0.state=%s; Max-Age=600; %s; HttpOnly", expectedEncodedState, expectedExpires))); } @Test @@ -62,9 +64,12 @@ public void shouldSetStateSameSiteCookieAndFallbackCookie() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(2)); + String expectedExpires = response.getHeaders("Set-Cookie").get(0).split(";")[2].trim(); - assertThat(headers, hasItem("com.auth0.state=123456; HttpOnly; Max-Age=600; SameSite=None; Secure")); - assertThat(headers, hasItem("_com.auth0.state=123456; HttpOnly; Max-Age=600")); + assertThat(headers, hasItem( + String.format("com.auth0.state=123456; Max-Age=600; %s; Secure; HttpOnly; SameSite=None", expectedExpires))); + assertThat(headers, hasItem( + String.format("_com.auth0.state=123456; Max-Age=600; %s; HttpOnly", expectedExpires))); } @Test @@ -73,8 +78,10 @@ public void shouldSetStateSameSiteCookieAndNoFallbackCookie() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(1)); + String expectedExpires = response.getHeaders("Set-Cookie").get(0).split(";")[2].trim(); - assertThat(headers, hasItem("com.auth0.state=123456; HttpOnly; Max-Age=600; SameSite=None; Secure")); + assertThat(headers, hasItem( + String.format("com.auth0.state=123456; Max-Age=600; %s; Secure; HttpOnly; SameSite=None", expectedExpires))); } @Test @@ -83,8 +90,10 @@ public void shouldSetSecureCookieWhenSameSiteLaxAndConfigured() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(1)); + String expectedExpires = response.getHeaders("Set-Cookie").get(0).split(";")[2].trim(); - assertThat(headers, hasItem("com.auth0.state=123456; HttpOnly; Max-Age=600; SameSite=Lax; Secure")); + assertThat(headers, hasItem( + String.format("com.auth0.state=123456; Max-Age=600; %s; Secure; HttpOnly; SameSite=Lax", expectedExpires))); } @Test @@ -93,9 +102,12 @@ public void shouldSetSecureFallbackCookieWhenSameSiteNoneAndConfigured() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(2)); + String expectedExpires = response.getHeaders("Set-Cookie").get(0).split(";")[2].trim(); - assertThat(headers, hasItem("com.auth0.state=123456; HttpOnly; Max-Age=600; SameSite=None; Secure")); - assertThat(headers, hasItem("_com.auth0.state=123456; HttpOnly; Max-Age=600; Secure")); + assertThat(headers, hasItem( + String.format("com.auth0.state=123456; Max-Age=600; %s; Secure; HttpOnly; SameSite=None", expectedExpires))); + assertThat(headers, hasItem( + String.format("_com.auth0.state=123456; Max-Age=600; %s; Secure; HttpOnly", expectedExpires))); } @Test @@ -105,7 +117,10 @@ public void shouldNotSetSecureCookieWhenSameSiteLaxAndConfigured() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(1)); - assertThat(headers, hasItem("com.auth0.state=123456; HttpOnly; Max-Age=600; SameSite=Lax")); + String expectedExpires = response.getHeaders("Set-Cookie").get(0).split(";")[2].trim(); + + assertThat(headers, hasItem( + String.format("com.auth0.state=123456; Max-Age=600; %s; HttpOnly; SameSite=Lax", expectedExpires))); } @Test @@ -115,8 +130,13 @@ public void shouldSetNonceSameSiteCookieAndFallbackCookie() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(2)); - assertThat(headers, hasItem("com.auth0.nonce=123456; HttpOnly; Max-Age=600; SameSite=None; Secure")); - assertThat(headers, hasItem("_com.auth0.nonce=123456; HttpOnly; Max-Age=600")); + String expectedExpires = response.getHeaders("Set-Cookie").get(0).split(";")[2].trim(); + + assertThat(headers, hasItem( + String.format("com.auth0.nonce=123456; Max-Age=600; %s; Secure; HttpOnly; SameSite=None", expectedExpires))); + assertThat(headers, hasItem( + String.format("_com.auth0.nonce=123456; Max-Age=600; %s; HttpOnly", expectedExpires))); + } @Test @@ -125,8 +145,10 @@ public void shouldSetNonceSameSiteCookieAndNoFallbackCookie() { List headers = response.getHeaders("Set-Cookie"); assertThat(headers.size(), is(1)); + String expectedExpires = response.getHeaders("Set-Cookie").get(0).split(";")[2].trim(); - assertThat(headers, hasItem("com.auth0.nonce=123456; HttpOnly; Max-Age=600; SameSite=None; Secure")); + assertThat(headers, hasItem( + String.format("com.auth0.nonce=123456; Max-Age=600; %s; Secure; HttpOnly; SameSite=None", expectedExpires))); } @Test