Compare commits

..
Author SHA1 Message Date
Dima May 58f6265836 upgraded to spring boot 4.1.0 2026-08-12 19:35:43 +00:00
Ryan Mayo e3f299376c Merge pull request #285 from arpitjain099/fix/encode-oauth-redirect-uri
Encode the redirect target before interpolating it into the authenticator URL
2026-07-31 10:09:11 -04:00
Arpit Jain 2b66377a30 Encode the redirect target before interpolating it into the authenticator URL
getAuthenticationToken built the OAuth redirect by interpolating
window.location straight into the query string, so any reserved
character already present in the current URL was carried through as
structure rather than data. A page reached with an ampersand in its
query string could therefore append parameters to the authenticator
URL, including a second skillsRedirectUri.

Use encodeURIComponent(window.location.href) so the value is passed as
a single opaque parameter. Closes #284.

Signed-off-by: Arpit Jain <[email protected]>
2026-07-31 00:06:02 +09:00
Dima May b88c19d0c7 Merge pull request #283 from NationalSecurityAgency/dependabot/npm_and_yarn/skills-client-integration/skills-int-client-js/axios-1.18.0
Bump axios from 1.17.0 to 1.18.0 in /skills-client-integration/skills-int-client-js
2026-07-21 07:21:08 -04:00
dependabot[bot] 558cecacdd Bump axios in /skills-client-integration/skills-int-client-js
Bumps [axios](https://github.com/axios/axios) from 1.17.0 to 1.18.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.17.0...v1.18.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.18.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-07-21 10:55:51 +00:00
Dima May dbcc95f951 Merge pull request #282 from NationalSecurityAgency/dependabot/npm_and_yarn/skills-client-js/axios-1.18.0
Bump axios from 1.17.0 to 1.18.0 in /skills-client-js
2026-07-21 06:54:48 -04:00
dependabot[bot] 50ac5c413f Bump axios from 1.17.0 to 1.18.0 in /skills-client-js
Bumps [axios](https://github.com/axios/axios) from 1.17.0 to 1.18.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.17.0...v1.18.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.18.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-07-20 20:13:33 +00:00
Don Walizer cf0961c435 Merge pull request #280 from NationalSecurityAgency/upgrades_gh-actions_node_java
upgrade gh actions, node and java
2026-07-06 09:38:03 -04:00
Dima May 56cb884fdb Merge pull request #279 from NationalSecurityAgency/dependabot/npm_and_yarn/skills-client-js/babel/core-7.29.6
Bump @babel/core from 7.29.0 to 7.29.6 in /skills-client-js
2026-07-06 08:02:34 -04:00
dependabot[bot] a301650700 Bump @babel/core from 7.29.0 to 7.29.6 in /skills-client-js
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.29.0 to 7.29.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.29.6/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-version: 7.29.6
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-06-25 14:51:08 +00:00
9 changed files with 35 additions and 18 deletions

No files matched your search

+1 -5
View File
@@ -7,7 +7,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.16</version>
<version>4.1.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>skills</groupId>
@@ -31,10 +31,6 @@
<properties>
<!--suppress UnresolvedMavenProperty -->
<nexusServer>${nexus.url}</nexusServer>
<frontend-maven-plugin.version>1.10.3</frontend-maven-plugin.version>
<!-- TODO: Temporary override spring boot versions, remove once spring boot upgrades these versions -->
<commons-lang3.version>3.19.0</commons-lang3.version>
</properties>
</project>
@@ -17,7 +17,7 @@
"author": "SkillTree Team",
"dependencies": {
"@skilltree/skills-client-js": "3.6.3",
"axios": "1.17.0",
"axios": "1.18.0",
"bootstrap": "5.3.8",
"jquery": "4.0.0"
},
@@ -23,6 +23,10 @@
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-restclient</artifactId>
</dependency>
</dependencies>
<build>
@@ -15,10 +15,8 @@
*/
package skills.example;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.http.*;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.util.LinkedMultiValueMap;
@@ -27,6 +25,8 @@ import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import skills.example.SkillsExampleApplication.SkillsConfig;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.Arrays;
@@ -23,11 +23,9 @@ import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.ssl.TrustStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.boot.restclient.RestTemplateCustomizer;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@@ -18,15 +18,18 @@ package skills.example.filters;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@Order(SecurityProperties.DEFAULT_FILTER_ORDER-1)
@Order(VueEntryPointFilter.BEFORE_SECURITY_FILTER_ORDER)
public class VueEntryPointFilter implements Filter {
// -100 (Default Security Order) - 1
public static final int BEFORE_SECURITY_FILTER_ORDER = -101;
@Autowired
private VueEntryPointFilterUtils vueEntryPointFilterUtils;
+2 -2
View File
@@ -30,7 +30,7 @@
"author": "SkillTree Team",
"devDependencies": {
"@babel/cli": "7.28.6",
"@babel/core": "7.29.0",
"@babel/core": "7.29.6",
"@babel/plugin-transform-runtime": "7.29.0",
"@babel/polyfill": "7.12.1",
"@babel/preset-env": "7.29.5",
@@ -56,7 +56,7 @@
},
"dependencies": {
"@stomp/stompjs": "7.3.0",
"axios": "1.17.0",
"axios": "1.18.0",
"js-logger": "1.6.1",
"postmate": "1.5.2",
"sockjs-client": "1.6.1"
+1 -1
View File
@@ -119,7 +119,7 @@ export default {
if (xhr.status !== 200) {
if (isOAuthMode && oauthRedirect && xhr.status === 401) {
// if we get 401 and we are using OAuth, then redirect to the OAuth Provider
const oauthAuthenticator = `${authenticator}?skillsRedirectUri=${window.location}`;
const oauthAuthenticator = `${authenticator}?skillsRedirectUri=${encodeURIComponent(window.location.href)}`;
log.info(`SkillsClient::SkillService::unable to get oAuth token, navigating to [${oauthAuthenticator}]`);
this.assignWindowLocation(oauthAuthenticator);
resolve();
+17 -1
View File
@@ -45,7 +45,23 @@ describe('OAuth auto redirect tests', () => {
await SkillsService.getAuthenticationToken(authEndpoint, mockServiceUrl, mockProjectId, true);
expect(SkillsService.assignWindowLocation).toHaveBeenCalledTimes(1)
expect(SkillsService.assignWindowLocation).toHaveBeenCalledWith(`${authEndpoint}?skillsRedirectUri=http://localhost/`)
expect(SkillsService.assignWindowLocation).toHaveBeenCalledWith(`${authEndpoint}?skillsRedirectUri=${encodeURIComponent('http://localhost/')}`)
});
it('oauth redirect encodes the current location so it cannot add query parameters', async () => {
const oauthTokenEndpoint = `${mockServiceUrl}/api/projects/${mockProjectId}/token`;
mock.get(oauthTokenEndpoint, (req, res) => res.status(401));
window.history.pushState({}, '', '/page?a=1&skillsRedirectUri=http://evil.example.com/');
const injected = window.location.href;
await SkillsService.getAuthenticationToken(authEndpoint, mockServiceUrl, mockProjectId, true);
const [redirectedTo] = SkillsService.assignWindowLocation.mock.calls[0];
expect(redirectedTo).toBe(`${authEndpoint}?skillsRedirectUri=${encodeURIComponent(injected)}`);
// the injected separators must not survive as separators
expect(redirectedTo.split('?')).toHaveLength(2);
expect(redirectedTo).not.toContain('&skillsRedirectUri=');
});
it('oauth does not auto redirect when oauthRedirect=false', async () => {