Skip to content

Commit e1f816f

Browse files
authored
Merge pull request #7099 from Countly/ar2rsawseen/master2
Persistently store hash in session storage to preserve it across oauth
2 parents 8b33f20 + 945fa1c commit e1f816f

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

frontend/express/views/dashboard.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,41 @@
1717
<script><%- javascript %></script>
1818
<link rel="icon" type="image/png" href="<%- cdn %><%- countlyFavicon %>">
1919
<script type="text/javascript">
20+
// Restore URL hash preserved during OAuth2 authentication flow
21+
// The hash was saved in sessionStorage on the login page before OAuth2 redirect.
22+
// After successful authentication and redirect back to the dashboard, we restore it here
23+
// so users land on the page they originally intended to visit (e.g., #/analytics/sessions).
24+
// NOTE: The key 'countly_oauth_return_hash' must match the key used in login.html
25+
(function() {
26+
var OAUTH_HASH_KEY = 'countly_oauth_return_hash';
27+
try {
28+
var savedHash = sessionStorage.getItem(OAUTH_HASH_KEY);
29+
if (savedHash && savedHash.length > 1) {
30+
// Clear the saved hash immediately to prevent reuse
31+
sessionStorage.removeItem(OAUTH_HASH_KEY);
32+
33+
// Validate hash format: must start with # and contain only safe URL characters
34+
// Allow: alphanumeric, forward slash, hyphen, underscore, dot, question mark, equals, ampersand, percent
35+
var hashPattern = /^#[a-zA-Z0-9\/_\-\.?=&%]+$/;
36+
37+
if (hashPattern.test(savedHash)) {
38+
// Additional check: ensure no javascript: or data: protocol
39+
var lowerHash = savedHash.toLowerCase();
40+
if (lowerHash.indexOf('javascript:') === -1 &&
41+
lowerHash.indexOf('data:') === -1 &&
42+
lowerHash.indexOf('<script') === -1) {
43+
// Restore the hash to the current URL
44+
if (window.location.hash !== savedHash) {
45+
window.location.hash = savedHash;
46+
}
47+
}
48+
}
49+
}
50+
} catch(e) {
51+
// Ignore if sessionStorage is not available
52+
}
53+
})();
54+
2055
//no one should really need this
2156
window.eval = function(){
2257
console.log("eval not available");

frontend/express/views/login.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,26 @@ <h1 style="font-weight: 500;" id="header" data-test-id="login-sign-in" data-loca
114114
<script>
115115
var countlyTitle = "<%- countlyTitle %>";
116116
var resetResultMessage = "<%= message %>";
117+
118+
// Preserve URL hash for OAuth2 redirect flow
119+
// During OAuth2 authentication, the user is redirected to an external provider and back,
120+
// which causes the URL hash (e.g., #/analytics/sessions) to be lost.
121+
// We store it here in sessionStorage so it can be restored on the dashboard page
122+
// after successful authentication, ensuring users land on their intended page.
123+
// NOTE: The key 'countly_oauth_return_hash' must match the key used in dashboard.html
124+
(function() {
125+
var OAUTH_HASH_KEY = 'countly_oauth_return_hash';
126+
var hash = window.location.hash;
127+
if (hash && hash.length > 1) {
128+
// Store hash in sessionStorage to preserve it through OAuth2 redirect
129+
try {
130+
sessionStorage.setItem(OAUTH_HASH_KEY, hash);
131+
} catch(e) {
132+
// Ignore if sessionStorage is not available
133+
}
134+
}
135+
})();
136+
117137
$(document).ready(function() {
118138
<% if (message && message.length >0){ %>
119139
$('.cly-vue-notification__alert-box').show();

0 commit comments

Comments
 (0)