Skip to content

Commit

Permalink
Improvements for oidc auth (#251)
Browse files Browse the repository at this point in the history
* added possibility for root redirect_uris by disabling routing if access_token or id_token exist in the url, small contextswitcher bug, refactored backdrop since inline if-elses are breaking in svelte oncreate,
* iframe resiliency for logout
* added logout.html and changed logoutUrl, fixed small bugs causing errors
* added skipRoutingForUrlPatterns configuration setting for skipping route handling
* Update docs/navigation-configuration.md
  • Loading branch information
maxmarkus authored Nov 28, 2018
1 parent d84977a commit 0b761a8
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -533,11 +533,25 @@ Luigi.setConfig({
},
routing: {
/**
* useHashRouting
*
* Development:
* For hash routing, set to true and run `npm run start`
* For path routing, set to false and run `npm run startWebpack`
*/
useHashRouting: true
useHashRouting: true,
/**
* Prefix for reflecting params in the url, which is used when navigating .withParams() function.
*/
nodeParamPrefix: '~',
/**
* skipRoutingForUrlPatterns
* Define regex patterns that prevent the router from handling path changes.
* Used to exclude authentication or other callbacks.
*
* Default: /access_token=/, /id_token=/
*/
skipRoutingForUrlPatterns: [/access_token=/, /id_token=/]
},
settings: {
header: () => ({
Expand Down
3 changes: 1 addition & 2 deletions core/examples/luigi-sample-angular/src/logout.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
<title>Logout successful</title>
<meta name="description" content="">
<meta name="keywords" content="logout">

<link rel='stylesheet' href='/fiori-fundamentals/fiori-fundamentals.min.css'>
<link rel='stylesheet' href='/fundamental-ui/fiori-fundamentals.min.css'>

<style>
.sap-icon--log::before {
Expand Down
8 changes: 8 additions & 0 deletions core/src/App.html
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@
};

const sendContextToClient = (component, config, goBackContext = {}) => {
if (!config.iframe) {
console.info('iframe does not exist, not able to send context.');
return;
}
config.iframe.contentWindow.postMessage(
{
msg: 'luigi.init',
Expand All @@ -139,6 +143,10 @@
};

const sendAuthDataToClient = (iframe, authData) => {
if (!iframe || !iframe.contentWindow) {
console.info('iframe does not exist, not able to send authData to client.');
return;
}
iframe.contentWindow.postMessage(
{
msg: 'luigi.auth.tokenIssued',
Expand Down
30 changes: 22 additions & 8 deletions core/src/Backdrop.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="{backdropActive ? 'fd-ui__overlay fd-overlay fd-overlay--modal ' + heightCssClass : ''}" aria-hidden="false">
<div class="{backdropClass}" aria-hidden="false">
<slot></slot>
</div>

Expand All @@ -7,18 +7,14 @@
export default {
data() {
return {
backdropActive: false
backdropActive: false,
backdropClass: ''
}
},
oncreate() {
const backdropDisabled = LuigiConfig.getConfigValue('settings.backdropDisabled');
if (!backdropDisabled) {
if (this.options.data && this.options.data.heightCssClass) {
this.set({ heightCssClass: this.options.data.heightCssClass })
} else {
this.set({ heightCssClass: 'height-auto' })
}

this.setBackdropClass();
window.addEventListener("message", (e) => {
if ('luigi.add-backdrop' === e.data.msg) {
this.set({ backdropActive: true });
Expand All @@ -29,6 +25,24 @@
});
}
},
onstate({ changed, current, previous }) {
if (changed.backdropActive) {
this.setBackdropClass();
}
},
methods: {
setBackdropClass() {
const baseClasses = 'fd-ui__overlay fd-overlay fd-overlay--modal ';
if (!this.get().backdropActive) {
this.set({ backdropClass: '' });
} else if (this.options.data && this.options.data.heightCssClass) {
this.set({ backdropClass: baseClasses + this.options.data.heightCssClass });
} else {
console.log('backdropActive', this.get().backdropActive, this.get().backdropClass);
this.set({ backdropClass: baseClasses + 'height-auto' });
}
}
}
};
</script>

Expand Down
2 changes: 1 addition & 1 deletion core/src/navigation/ContextSwitcher.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
}
},
async setSelectedContext(currentPath) {
const config = this.get().config;
const config = this.get().config || {};
const options = this.get().options;
const parentNodePath = config.parentNodePath;
const fallbackLabelResolver = config.fallbackLabelResolver;
Expand Down
5 changes: 4 additions & 1 deletion core/src/navigation/LeftNav.html
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,12 @@
.fd-side-nav__icon{
padding-right: 4px;

&.sap-icon--lui-blank{
display: inline-block;
min-width: 20px;
vertical-align: middle;

&.sap-icon--lui-blank{

}
}
</style>
17 changes: 14 additions & 3 deletions core/src/navigation/TopNav.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@


<div class="fd-shellbar__actions">
<ContextSwitcher />
{#if !authorizationEnabled || isLoggedIn}
<ContextSwitcher />
{/if}
{#if children && pathData.length > 0}
{#each children as node}
{#if !node.hideFromNav}
Expand Down Expand Up @@ -39,7 +41,7 @@
</div>

<div class="fd-popover__body fd-popover__body--right" aria-hidden="{dropDownStatesNegated.OVERFLOW_POPOVER || true}" id="OVERFLOW_POPOVER">

<nav class="fd-menu">
<ul class="fd-menu__list">
{#each children as node}
Expand Down Expand Up @@ -85,6 +87,7 @@
import LogoTitle from './LogoTitle.html';
import Authorization from '../Authorization.html';
import { handleRouteClick } from '../services/routing.js';
import * as Navigation from './services/navigation.js';
import { LuigiConfig } from '../services/config.js';
import { getNegatedBoolString } from '../utilities/helpers.js';

Expand All @@ -107,6 +110,12 @@
}
};

const setLoggedInState = (current, component) => {
component.set({
isLoggedIn: Navigation.isLoggedIn()
});
}

export default {
oncreate() {
this.set({
Expand All @@ -118,10 +127,12 @@
if (!previous || previous.pathData != current.pathData) {
setTopNavData(current, this);
}
setLoggedInState(current, this);
},
data() {
return {
dropDownStates: {}
dropDownStates: {},
isLoggedIn: false
};
},
computed: {
Expand Down
1 change: 1 addition & 0 deletions core/src/navigation/services/context-switcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const ContextSwitcherHelpers = {

return Boolean(
parentNodePath &&
currentPathNormalized &&
currentPathNormalized.startsWith(parentNodePathNormalized) &&
!currentPathNormalized.endsWith(parentNodePathNormalized)
);
Expand Down
9 changes: 4 additions & 5 deletions core/src/navigation/services/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,11 @@ export const findMatchingNode = (urlPathElement, nodes) => {
return result;
};

const isLoggedIn = () => {
const getStoredAuthData = () =>
JSON.parse(localStorage.getItem('luigi.auth'));
export const isLoggedIn = () => {
const storedAuthData = JSON.parse(localStorage.getItem('luigi.auth'));
const isAuthValid = () =>
getStoredAuthData().accessTokenExpirationDate > Number(new Date());
return getStoredAuthData() && isAuthValid();
storedAuthData.accessTokenExpirationDate > Number(new Date());
return storedAuthData && isAuthValid();
};

export const getNodes = (children, pathData) => {
Expand Down
2 changes: 1 addition & 1 deletion core/src/providers/auth/openIdConnect.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class openIdConnect {
automaticSilentRenew: false,
accessTokenExpiringNotificationTime: 60,
thirdPartyCookiesScriptLocation: '',
logoutUrl: '',
logoutUrl: window.location.origin + '/logout.html',
silent_redirect_uri:
window.location.origin + '/luigi-core/auth/oidc/silent-callback.html'
};
Expand Down
9 changes: 9 additions & 0 deletions core/src/services/routing.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,15 @@ const buildRoute = (node, path, params) =>
: buildRoute(node.parent, `/${node.parent.pathSegment}${path}`, params);

export const handleRouteChange = async (path, component, node, config) => {
const defaultPattern = [/access_token=/, /id_token=/];
const patterns =
LuigiConfig.getConfigValue('routing.skipRoutingForUrlPatterns') ||
defaultPattern;
const hasSkipMatches =
patterns.filter(p => window.location.href.match(p)).length !== 0;
if (hasSkipMatches) {
return;
}
try {
const pathUrl = path && path.length ? getPathWithoutHash(path) : '';
const pathData = await getNavigationPath(
Expand Down
4 changes: 3 additions & 1 deletion docs/navigation-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ You can configure the way Luigi tackles routing in your application in the **Rou

- **useHashRouting** defines either hash-based (`url.com/#/yourpath`) or path-based (`url.com/yourpath`) routing.
- **nodeParamPrefix** sets the prefix character when using the `LuigiClient.linkManager().withParam()` function, which provides a way to simply attach query parameters to the view URL for activities such as sorting and filtering. The URL contains the parameters to allow deep linking. If you want to use a different character prefix, define yours here. The default character is `~`.
- **skipRoutingForUrlPatterns** defines regex patterns to be skipped by the router when listening for path changes. This parameter is used for excluding **redirect_uri** parameters. Default patterns are `[/access_token=/, '/id_token=/]`.

### Node navigation parameters

Expand Down Expand Up @@ -253,7 +254,8 @@ Luigi.setConfig({
routing: {
// uses hash-based navigation if set to true
useHashRouting: true,
nodeParamPrefix: '~'
nodeParamPrefix: '~',
skipRoutingForUrlPatterns: [/access_token=/, /id_token=/]
},
// navigation structure and settings
navigation: {
Expand Down

0 comments on commit 0b761a8

Please sign in to comment.