Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
127618f
dev template
hardl Nov 7, 2025
eae0160
prettier
hardl Nov 7, 2025
4548015
no compile errors...
hardl Nov 7, 2025
8770c5a
prettier
hardl Nov 7, 2025
fadffc7
remove vite tmp file
hardl Nov 7, 2025
3f2c1a6
fix auth store compile issues
hardl Nov 11, 2025
869a7ca
prettier
hardl Nov 11, 2025
0b81889
activate auth layer
hardl Nov 12, 2025
fe1ea77
logout
hardl Nov 13, 2025
b1a8a4b
prettier
hardl Nov 13, 2025
6c29b34
userInfo in profile
hardl Nov 13, 2025
c92bc24
prettier
hardl Nov 13, 2025
7e7f1b3
Merge branch 'main' into headless/auth
hardl Nov 13, 2025
0ba5f87
custome store implementation
hardl Nov 13, 2025
2fe6f2e
prettier
hardl Nov 13, 2025
cb11d56
userInfo in profile updates
hardl Nov 14, 2025
65f18ac
prettier
hardl Nov 14, 2025
49931d8
Merge branch 'main' into headless/auth
hardl Nov 14, 2025
485613b
oidc config
hardl Nov 14, 2025
2b2f4fd
prettier
hardl Nov 14, 2025
af40038
handle auth errors, part1
hardl Nov 17, 2025
ce7a780
prettier
hardl Nov 17, 2025
d056096
auth events
hardl Nov 18, 2025
4679c9e
prettier
hardl Nov 18, 2025
5e03537
hideSideNav
hardl Nov 18, 2025
2086f5b
prettier
hardl Nov 18, 2025
bf0bcba
signed in metadata to topnav
hardl Nov 18, 2025
62facc6
prettier
hardl Nov 18, 2025
2e93386
earlier node permission check
hardl Nov 18, 2025
fc7b8c4
prettier
hardl Nov 18, 2025
f766e63
Merge branch 'main' into headless/auth
hardl Nov 18, 2025
d1ba129
Merge branch 'main' into headless/auth
hardl Nov 19, 2025
288c67d
Merge branch 'main' into headless/auth
hardl Nov 20, 2025
fa427df
fix test
hardl Nov 20, 2025
c9c6854
Merge branch 'main' into headless/auth
hardl Nov 21, 2025
53d5dd8
test for store
hardl Nov 21, 2025
6a9b197
prettier
hardl Nov 21, 2025
9911fe6
Merge branch 'main' into headless/auth
hardl Nov 24, 2025
022d421
config helpers test
hardl Nov 24, 2025
bf00fe9
prettier
hardl Nov 24, 2025
770a283
Merge branch 'main' into headless/auth
hardl Nov 24, 2025
e861d94
auth helpers test
hardl Nov 24, 2025
46e32d8
prettier
hardl Nov 24, 2025
3c87116
Merge remote-tracking branch 'refs/remotes/origin/headless/auth' into…
hardl Nov 24, 2025
0435379
auth-store service test
hardl Nov 25, 2025
fd50198
prettier
hardl Nov 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions core-modular/dev-tools/templates/simple/auth/callback.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script type="text/javascript">
const tokenLifetimeDays = 7;

const getParameterByName = (name) => {
return new URLSearchParams(location.search).get(name);
};

const setAuthData = (data) => {
const storageType = getParameterByName('storageType') || 'localStorage';
switch (storageType) {
case 'localStorage':
case 'sessionStorage':
window[storageType].setItem('luigi.auth', JSON.stringify(data));
window[storageType].setItem('luigi.newlyAuthorized', true);
break;
default:
console.error(
'Configuration Error: Invalid auth.storage setting. Must be either localStorage or sessionStorage to be used with OAuth2 Provider.',
);
}
};

const getHashParams = () => {
const hash = encodeURIComponent(window.location.hash.substring(1));
return decodeURIComponent(hash)
.split('&')
.reduce(function (result, item) {
var parts = item.split('=');
result[parts[0]] = parts[1];
return result;
}, {});
};

const processExpDate = (expiresInString) => {
let expirationDate;
const expiresIn = Number(expiresInString);
if (!isNaN(expiresIn) && expiresIn > 0) {
const nsToMsMultiplier = 1000;
expirationDate =
Number(new Date()) + nsToMsMultiplier * (expiresIn - tokenLifetimeDays);
}
return expirationDate;
};

const parseJwt = (token) => {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(
atob(base64)
.split('')
.map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
})
.join(''),
);

return JSON.parse(jsonPayload);
};
</script>
</head>

<body>
<script type="text/javascript">
const uri = encodeURIComponent(window.location.href);
const hashParams = getHashParams(uri);
const token = hashParams['access_token'] || hashParams['id_token'];
if (hashParams && (token || hashParams['error'])) {
const error = hashParams['error'];
const { exp } = parseJwt(hashParams['id_token']);
const expires_in = hashParams['expires_in'] || exp;
if (!error) {
const data = {
accessToken: token,
accessTokenExpirationDate: processExpDate(expires_in),
scope: hashParams['scope'],
idToken: hashParams['id_token'],
};

setAuthData(data);

const decodedState = atob(decodeURIComponent(hashParams['state'])).split(
'_luigiNonce=',
);
const appState = decodeURI(decodedState[0] || '');
const nonce = decodedState[1];

if (nonce !== sessionStorage.getItem('luigi.nonceValue')) {
document.getElementsByTagName('body')[0].innerHTML =
'Something went wrong. Try to log in again.';
throw new Error(
'State parameter returned from the authorization endpoint does not match locally stored state. Aborting login process.',
);
}

const appStateUrl = new URL(appState);
if (appStateUrl.origin === window.location.origin) {
const newUrl = new URL(window.location.href);
newUrl.pathname = appStateUrl.pathname;
newUrl.search = appStateUrl.search;
newUrl.hash = appStateUrl.hash;
window.location.href = newUrl.href;
} else {
window.location.href = '/';
console.log(
`Preventing redirect to ${appState} as it does not match the current origin.`,
);
}
} else {
// else tree only applies to idtoken auths, I guess
const errorDescription = hashParams['error_description'];
console.error('error', errorDescription);
const params = new URLSearchParams();
params.set('error', error);
params.set('errorDescription', errorDescription);
const url = new URL('/', window.location.href);
url.search = params;
window.location.href = url.href;
}
}
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Luigi Mock Identity Provider</title>
<link
href="/vendor/fundamental-styles/dist/fundamental-styles.css"
rel="stylesheet"
/>
<link rel="stylesheet" type="text/css" href="../../styles/styles.css" />
<style type="text/css">
body {
background-color: #f7f7f7;
}

h1 {
text-align: center;
font-weight: 400;
}

.fd-input {
display: block;
margin: auto;
width: 200px;
}

.fd-button {
display: block;
margin: auto;
}

.login-form {
background-color: #ffffff;
box-shadow: 0 5px 20px 0 rgba(50, 54, 58, 0.08);
border-radius: 4px;
border: none;
width: 50%;
margin: auto;
margin-top: 50px;
min-width: 270px;
padding: 15px;
}
</style>
</head>
<body>
<div class="login-form">
<h1>Login to Luigi sample app</h1>
<form>
<input
id="username"
type="text"
class="fd-input"
value="LuigiUsername"
placeholder="Username"
/><br />
<input
type="password"
class="fd-input"
value="LuigiPassword"
placeholder="Password"
/><br />
<button id="login-button" class="fd-button">Login</button>
</form>
</div>
<script src="implicit.js"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
window.onload = function () {
const loginButton = document.getElementById('login-button');
const expiresIn = 3600;
const state = encodeURIComponent(window.location.href.match(/state=(.*?)(&|$)/)[1]);
const goTo = (scope) => {
return `/auth/callback.html#
expires_in=${expiresIn}&
state=${state}&
scope=${scope}&
access_token=thisisanaccesstokenthatisnotreallyneeded&
id_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAiLCJzdWIiOiJtYXNrb3BhdG9sIiwiZXhwIjoxNjQzNzY0OTIwLCJhe
nAiOiJtYXNrb3BhdG9sIiwibm9uY2UiOiJidE5rWVZzc1FldVlWNmEyR1RVZm1wWVFFelBRN3c1ZENCbU54SG54IiwiZW
1haWwiOiJsdWlnaXVzZXJAa3ltYS5jeCJ9.80GanA3z-Rl67VQAb-lvMNpDZKcVI32CQZIoM9imF5w&
token_type=bearer`;
};

loginButton.addEventListener('click', function (ev) {
ev.preventDefault();
const username = document.getElementById('username').value;
const scope = username == 'admin' ? 'admin' : 'viewer';
window.location.replace(goTo(scope).replace(/\s\s+/g, ''));
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!doctype html>
<html>
<head>
<title>Luigi Mock Identity Provider</title>
</head>

<body>
Logging out...
<script>
window.onload = function () {
let href = encodeURI(window.location.href);
const decodeChars = (string) => string.replace(/[<>'*+?^${}()|[\]\\]/g, '\\$&');
let redirectTo = decodeChars(
decodeURIComponent(href.match(/post_logout_redirect_uri=(.*?)(&|$)/)[1]),
);
if (!redirectTo.startsWith(window.location.origin)) {
console.warn(
'post_logout_redirect_uri has wrong input. You are redirected to /auth/logout.html!',
);
redirectTo = '/auth/logout.html';
}
window.location.href = redirectTo;
};
</script>
</body>
</html>
48 changes: 48 additions & 0 deletions core-modular/dev-tools/templates/simple/auth/logout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="" />
<meta name="keywords" content="logout" />
<title>Logout successful</title>
<link
href="/vendor/fundamental-styles/dist/fundamental-styles.css"
rel="stylesheet"
/>
<link rel="stylesheet" type="text/css" href="../styles/styles.css" />

<style>
.sap-icon--log::before {
font-size: 50px;
color: #a0a0a0;
}

.fd-container--centered {
text-align: center;
}

.fd-container {
padding-top: 20px;
}
</style>
<script type="text/javascript">
function login() {
window.location.href = '/';
}
</script>
</head>

<body>
<div class="fd-container fd-container--centered">
<div class="fd-col--6 fd-col--shift-3">
<span class="sap-icon--log"></span>
<br />
Logout successful
<br />
<br />
<button class="fd-button" onclick="login()">Login again</button>
</div>
</div>
</body>
</html>
9 changes: 8 additions & 1 deletion core-modular/dev-tools/templates/simple/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<title>Luigi Headless</title>
Expand All @@ -19,12 +19,19 @@
{ "theme": "sap_horizon" }
</script>
<link rel="stylesheet" href="/luigi-ui/lui.css" />
<!-- <link rel="stylesheet" href="https://unpkg.com/@luigi-project/core/luigi_horizon.css" /> -->
</head>

<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script src="/public/luigi.js"></script>
<script src="/luigi-ui/lui-ui5wc.js"></script>

<!-- <script src="https://unpkg.com/@luigi-project/core/luigi.js" type="module"></script> -->

<script src="https://fiddle.luigi-project.io/vendor/plugin-auth-oauth2/plugin.js"></script>
<script src="https://fiddle.luigi-project.io/vendor/plugin-auth-oidc-pkce/plugin.js"></script>

<script src="/luigi-config.js"></script>
</body>
</html>
Loading