Skip to content

Commit ec0e42e

Browse files
committed
OIDC: Store redirect URL in state parameter
Multiple IdPs disallow usage of custom query parameters in the authorization request's `redirect_uri`. By storing the target URL in `state`, `redirect_uri` can remain static without query params. Fixes #64 Signed-off-by: nscuro <[email protected]>
1 parent 7b0a348 commit ec0e42e

File tree

2 files changed

+28
-45
lines changed

2 files changed

+28
-45
lines changed

public/static/oidc-callback.html

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,24 @@
1313
'/project', '/component', '/vulnerability', '/license', '/login', '/change-password'
1414
];
1515
function getContextPath() {
16-
if (window.location.pathname === '/static/oidc-callback.html') {
17-
// App is deployed in the root context. Return an empty string.
18-
return "";
19-
} else {
20-
// App is deployed in a non-root context. Return the context.
21-
return window.location.pathname.substring(0, window.location.pathname.indexOf("/",2));
22-
}
16+
if (window.location.pathname === '/static/oidc-callback.html') {
17+
// App is deployed in the root context. Return an empty string.
18+
return "";
19+
} else {
20+
// App is deployed in a non-root context. Return the context.
21+
return window.location.pathname.substring(0, window.location.pathname.indexOf("/",2));
22+
}
2323
}
2424
function isUrlSaveForRedirect(redirectUrl) {
25-
const contextRoot = getContextPath();
26-
try {
27-
const resultingUrl = new URL(redirectUrl, window.location.origin);
28-
return resultingUrl.origin === window.location.origin
25+
const contextRoot = getContextPath();
26+
try {
27+
const resultingUrl = new URL(redirectUrl, window.location.origin);
28+
return resultingUrl.origin === window.location.origin
2929
&& /^https?:$/.test(resultingUrl.protocol)
3030
&& acceptableRootContextPaths.map(r => contextRoot + r).some(p => redirectUrl.startsWith(p));
31-
} catch(invalidUrl) {
32-
return false;
33-
}
31+
} catch(invalidUrl) {
32+
return false;
33+
}
3434
}
3535

3636
axios.get("/static/config.json")
@@ -44,25 +44,11 @@
4444
});
4545
})
4646
.then((oidcUserManager) => {
47-
const redirectTo = (new URLSearchParams(window.location.search)).get("redirect");
48-
49-
oidcUserManager.getUser()
50-
.then((user) => {
51-
if (user !== null) {
52-
// Implicit flow: Token is already present in URL
53-
window.location.href = redirectTo && isUrlSaveForRedirect(redirectTo) ? redirectTo : "../";
54-
return Promise.resolve()
55-
} else {
56-
// Code flow: Token must be acquired in exchange for auth code
57-
return oidcUserManager.signinRedirectCallback();
58-
}
59-
})
60-
.then((user) => {
61-
window.location.href = redirectTo && isUrlSaveForRedirect(redirectTo) ? redirectTo : "../";
62-
})
63-
.catch((err) => {
64-
console.log(err);
65-
})
47+
return oidcUserManager.signinRedirectCallback();
48+
})
49+
.then((user) => {
50+
const redirectTo = user.state;
51+
window.location.href = redirectTo && isUrlSaveForRedirect(redirectTo) ? redirectTo : "../";
6652
})
6753
.catch((err) => {
6854
console.log(err);

src/views/pages/Login.vue

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,6 @@ export default {
8787
ValidationObserver
8888
},
8989
data() {
90-
let redirectUri = `${ window.location.origin }/static/oidc-callback.html`;
91-
// redirect to url from query param but only if it is save for redirection
92-
const redirectTo = getRedirectUrl(this.$router);
93-
if (redirectTo) {
94-
redirectUri += `?redirect=${ encodeURIComponent(redirectTo) }`;
95-
}
96-
9790
return {
9891
loginError: "",
9992
input: {
@@ -105,7 +98,7 @@ export default {
10598
userStore: new Oidc.WebStorageStateStore(),
10699
authority: this.$oidc.ISSUER,
107100
client_id: this.$oidc.CLIENT_ID,
108-
redirect_uri: redirectUri,
101+
redirect_uri: `${ window.location.origin }/static/oidc-callback.html`,
109102
response_type: this.$oidc.FLOW === "implicit" ? "token id_token" : "code",
110103
scope: this.$oidc.SCOPE,
111104
loadUserInfo: false
@@ -174,10 +167,14 @@ export default {
174167
});
175168
},
176169
oidcLogin() {
177-
this.oidcUserManager.signinRedirect().catch(err => {
178-
console.log(err);
179-
this.$toastr.e(this.$t("message.oidc_redirect_failed"));
180-
});
170+
this.oidcUserManager
171+
.signinRedirect({
172+
state: getRedirectUrl(this.$router)}
173+
)
174+
.catch(err => {
175+
console.log(err);
176+
this.$toastr.e(this.$t("message.oidc_redirect_failed"));
177+
});
181178
},
182179
oidcCheckLoginButtonTextSetted() {
183180
return this.$oidc.LOGIN_BUTTON_TEXT.length > 0;

0 commit comments

Comments
 (0)