cancel
Showing results for 
Search instead for 
Did you mean: 

Extra Authentication for Fiori Launchpad tile

Colt
Active Contributor

Hi Experts,

Situation: SSO for Fiori Frontend-Server is implemented, e.g. SPNEGO or SAML 2.0. User has a valid session at the Gateway. Is there a way to enforce separate user authentication for accessing a specific Fiori app (tile) within the Launchpad? Should work without establishing a second Frontend-Server 😉

Thinking about Secure Store and Forward (SSF) enforcing a re-authentication or something similar as possible in ABAP/GUI. Could also be 2FA etc.

Any ideas much appreciated, thank you!

Regards,

Carsten

Accepted Solutions (0)

Answers (2)

Answers (2)

thbuett
Explorer
0 Kudos

Hello Carsten and Noël,

did you find a solution or a first idea? I am confronted with the same requirement. My actually idea is, a Shell-Plugin with an event listener for navigation and trigger in the plugin the 2FA.

What SSO-Solution do you use. We are on SAML with a Shibboleth IdP.

Cheers, Thomas

mabujan
Explorer
0 Kudos

Hi there

Did you manage to get something working?

We have similar requirement.

When click on a particular tile, we would like to prompt the user for a second factor authentication of choice using a custom logic.

The idea of using the Shell Plugin seems like the way to go.

Thanks in advance

Manuel

thbuett
Explorer
0 Kudos

Hello Manuel,

yes, we had some ideas.

  1. Custom tile type, which triggers the 2FA
  2. A custom navigation resolver in the FLP@EP via Plugin-Extension, which checks, if the Tile fullfile special requirements an then trigger the 2FA. I think in the FLP@GW its possible to, via a bootstrap script.

The first I did not implement yet, cause I want the 2FA separate from the tile-definition. What I tried, was to check, if the called app or a called services requires a second factor. So I have the possibility to add a second factor to an app later, without change the tile catalog 😉

The Implementation Idea looks like this:

sap.ui.define([
	"jquery.sap.global",
	"sap/ui/core/Component",
	"sap/ui/core/HTML",
	"sap/m/Dialog"	
], function(jQuery, Component, HTML, Dialog) {
	
	return Component.extend("preauthentication.Component", {
	
		metadata: {
			manifest: "json",
			version: "1.0"
		},
				
		init : function() {
			sap.ushell.Container.getService("NavTargetResolution").registerCustomResolver({
				name : "Pre-Authentication Resolver",			
		        isApplicable : function (sHashFragment) {
		        	return sHashFragment.indexOf('#') == 0 && sHashFragment.length > 1 && sHashFragment != '#Shell-home'		        	
		        },
		        resolveHashFragment : function (sHashFragment, nextResolver) {
		        	var aIDPOrigins = [...],
		        		aTANApps = [],
		        		oDfd = new jQuery.Deferred().always(function(data) {
		        			jQuery.sap.log.info("App could be loaded");	
		        		});
		        	
		        	function _is2FAApp(url) {
		        		for (var i in aTANApps) {
		        			if (url.indexOf(aTANApps[i]) > -1)
		        				return true;
		        		}
		        		return false;
		        	}
		        	
		            jQuery.sap.log.info("Pre-Authentication-Request - Resolver : " + sHashFragment);
		            
		            nextResolver(sHashFragment).done(function(oDst) {            	
		            	if (oDst.applicationType == "SAPUI5" && (oDst.url.indexOf("/sap/saml/2fa") == 0 || _is2FAApp(oDst.url))) {           		
		            		function _handleAuthenticationMessage(event) {            			
		            			if (aIDPOrigins.indexOf(event.origin) > -1 && event.data == "Start Authentication") {
		            				
		            			}
		            			
		            			if (window.location.origin == event.origin && event.data == "End Authentication") {
		            				oPopover.close();
		            			}
		            		};
		            		            		
		            		window.addEventListener("message", _handleAuthenticationMessage, false);
		            		
		            		oHtml = new HTML("html2FA", {
		            			content :
				    				'<!DOCTYPE html>\
				        			<html>\
					            	<head>\
					            		<meta charset="UTF-8">\
					            	</head>\
					            	<body>\
					            		<div style="overflow: hidden;">\
					            			<iframe id="i2FA" src="/sap/saml/2fa/login" style="border: 0; height: 100%; left: 0; position: absolute; top: 0; width: 100%;"\
					            			/>\
					            		</div>\
					            	</body>\
					            </html>'
				    		}),
				    		oPopover = new Dialog("dialog", {
					    		stretch : true,
					    		content : [oHtml],
					    		showHeader : false,
					    		escapeHandler : function(oPrm) {
					    			oPrm.reject();
					    		},
					    		beforeOpen : function() {
					    			var onPopstate = window.onpopstate;
					    			window.onpopstate = function(event) {
				                    	oHtml.destroy();
				                    	oPopover.destroy();
				                    	oDfd.fail();
				                    	window.onpopstate = onPopstate;
				                    }
					    		},
					    		afterOpen : function() {
			            			jQuery.sap.log.info("Starting SAML Authentication");	            			
			            		},
					    		afterClose : function(event) {
			            			window.removeEventListener("message", _handleAuthenticationMessage);
			            			oDfd.resolve(oDst);
			            			oHtml.destroy();
			            			oPopover.destroy();	            			
			            		} 
				    		}).open();  
		            		
		            	} else {
							oDfd.resolve(oDst);
		            	}
		            });
		            
		            return oDfd.promise();
		        }
			});		
		},		
		
		exit : function() {
			
		}
		
	})
	
});

As short explanation, the custom resolver looks, if the app comes from /sap/saml/2fa an then opens a dialog where it calls the same service again, in the case the user is requested to enter the second factor. If the 2FA was successful, the IdP send a post message via browser, so the plugin could close the dialog and give the control back to the default Navigation Controller.

Behind /sap/saml/2fa/ I added all SICF-Services via Link. To the link I added the 2FA Context. Problem is, that most apps send in there manifest not the link address (/sap/saml/2fa/...), they send the root address (/sap/bc/ui5/....). The root has not the 2FA-Context, which leads to the problem, that the plugin did not trigger a 2FA request. Solution for this is not to work with a separate SICF-Path. Instead work with external alias. But I had to add for every service an external alias and the root Service has to get the 2FA-Context, which forces us to manipulate Default-Services, which could get changed back with an SP-Update.

For now the solution is only a proof of concept an a first try. It did not work for all solutions and we take in the first step the way, that the whole Launchpad is 2FA secured.

Not the best, but we have not enough manpower. Maybe I will find a time, to put this all clear with diagrams in a Blog but for now it could give you a first idea. If I forget something to explain, let it me know.

Greetings,

Thomas

nol_hendrikx
Active Contributor
0 Kudos

Hi Carsten,

We have the same requirement: some tiles (apps) need 2FA and all others not. I am curious how we can solve this. We're using launchpad on-premise.

Any help appreciated!

Noël

Colt
Active Contributor

Hey Noël, good to know. The customer project is currently running and this requirement may come up in the future again, but for now, I am out. In any case, should I stumble upon a solution, I will give an update here and would be glad if you do the same 😉

Cheers, Carsten