What's the best way to change the "OpenId Connect" link in the Liferay login page? - liferay

We have added several Social Logins to our Liferay 7.3 portal. These include the built-in Facebook and OpenId Connect capabilities as well as custom filters for Twitter, LinkedIn, and so on. OpenId Connect is configured for Google login.
This all works fine, but I need to change the link in the login page from "OpenId Connect" to "Google".
I have discovered that the value is set in the key open-id-connect-configuration-name in the language files in the portal-security-sso-openid-connect-api module. It is then accessed by the getName() method of the com.liferay.portal.settings.authentication.openid.connect.web.internal.portal.settings.configuration.admin.display.OpenIdConnectPortalSettingsConfigurationScreenContributor class. I believe this contributor supplies the value to the navigator for use as the label.
My question is what is the easiest and most maintainable way to go about changing this value? My thought was to supply alternate Language_*.properties files, but I'm not sure how to override the existing ones. Would a JSP hook of the portal-security-sso-openid-connect-api module allow me to do this?

I don't know a clean way - hopefully someone will chime in with one - but I had the same issue and had to solve it with a small piece of JavaScript in navigation.jspf:
<script>
$( document ).ready(function() {
$(".taglib-text").filter(function () {
return ($(this).text() === 'OpenId Connect')
}).text("Google");
});
</script>
While this works it's still a bit weird since clicking the link will go to the OpenId Connect portlet that has a drop down with a single item - Google - that is selected, and then the user has to click another Login button. I know this is to allow multiple OpenID Connect clients, but I'd sure like a direct method for Google.

Related

Is it possible to setup Single sign-on for a Single Page Application that will initiate the SSO from an arbitrary (not pre-approved) domain?

Our scenario is the following:
We have an SPA that we package and send to multiple customers.
The customers hosts the SPA on an arbitrary domain like www.unknown.com/spa/anything-goes, or www.also-unknown.com/spa/really-anything-goes, etc.
The customer also opens the SPA in a popup window and injects a service to communicate back and fourth from the popup (the SPA) and the main window.
The SPA uses our own API service, lets call it www.backend.com, as a backend.
The SPA also uses the service that is injected into the popup window by the opener (the customer website), meaning the main popup (where the SPA is loaded) window can't directly redirect to a common login page, because that will interrupt the connection to the injected service, and we can't modify the customer code to make it more robust).
We want to let the user of the SPA authenticate against our backend (www.backend.com) using SSO (their Microsoft credentials)
For any given (fixed) domain, we can make this work by approving the exact domain as an allowed Redirect URI in AzureAd, and just using the MSAL in the SPA.
But how would you go about using SSO when you don't know ahead of time which Redirect URIs to add in AzureAd?
We can't re-direct the SPA to a common login page (cleared in AzureAd), because that would break the connection to the injected service.
The msal-browser library has an option to use a popup window instead of a redirect directly in the SPA window, but this option also needs a pre-approved Redirect URI.
I'm thinking we may need to implement custom logic to let our SPA open a popup window that navigates to a page we can pre-approve as a Redirect URI, that itself has the MSAL library and does the SSO login and communicates the result back to our SPA. But before I attempt a custom solution like that, I wonder if maybe I'm missing something.
Is there a more standard, less "hacky", solution that I have missed?
We would appreciate any input, thanks!
We eventually went with the solution I hinted at in the question:
Publish a simple page including the MSAL library on a "central" location that we can pre-approve in AzureAD. Let's call that the Central SSO-page (CSSO).
Let each SPA, running on what ever domain they want, open a popup with the CSSO. This runs the MSAL and completes the login.
CSSO has logic that, on login-completion, communicates back to the SPA, using window.postMessage("Some message", "https://somerandomdomain.com")
The SPA sets up a listener window.addEventListener("message", handleMessage(){..logic here}).
The drawbacks are, as far as I can tell, mostly that you need to make sure you are posting the message so that only the correct window can receive it.
Another drawback is that popups are often blocked, but in our case that is unlikely since our SPAs are running from domains where the main way of loading our SPAs is through a popup, so for the user to even see our SPA, popups must already be allowed. Still, some fallback logic is needed to open the popup manually with a click (which seems to circumvent the default block of popups).

B2C Popup on iOS: "My App" Wants to Use "b2clogin.com" to Sign In

After upgrading Microsoft.Identity.Client within Xamarin.Forms from 1.x to 4.x, most things work much the same. However, login to iOS results in a popup that says:
"My App" Wants to Use "b2clogin.com" to Sign In
This allows the app and website to share information about you.
It's OK if user hits continue, but it's hardly seamless.
Supposedly it's associated with iOS 12, but that doesn't seem to be the trigger for me. There's a Microsoft article that says this is actually normal, stating:
On iOS, though, the user might have to give consent for the browser to call back the application, which can be annoying.
I found that it's possible to set .WithUseEmbeddedWebView(true) and this hides the URL as well as removing the popup, and this works with Facebook sign in, but Google sign in is a hard no.
There's the potential path of Universal Links instead of URL Schemes and Associated Domains.
Investigating that path, it appears that I simply need to set the URL https://myapp.b2clogin.com/.well-known/apple-app-site-association with the following JSON:
{
"webcredentials": {
"apps": [
"MYTEAMID.com.mycompany.myapp"
]
}
}
Unfortunately, I don't have control of that URL.
Any other ideas?
The short answer is -- it can't be done today as this alert pop-up is built into the iOS framework. Any authentication provider, library, etc. will trigger this alert if they use the ASWebAuthentication API in iOS
You can choose to use different embedded-browser pop-up APIs which do not cause this alert, however they will have sandboxed cookies and the user may not experience SSO. There is an MSAL docs page which discusses this in a bit more detail:
https://learn.microsoft.com/en-us/azure/active-directory/develop/customize-webviews
The best user experience:
I use ROPC for signIn only (native username/password fields or could be with biometry).
So I don't have any popup at simple Sign In.
For the rest I use commons Flows (Reset password, Google provider etc..)
that open the WebView with unfortunately the warning popup.

How to Logout user from Spotify after authorization and Web API call is over

Im using Spotify Web API to get list of playlist and track of user. Authorization is working fine. Also i do get track details. But after that I want to logout user from spotify and allow new login .
There is a session time till the user auto logout from spotify account. But user might not have patience to wait so long and re try with different spotify account.
Is there any API to logout user from spotify.
What can be done. Please help.
While an application using the Spotify Web API can't log a user out, it can force the permissions dialog to be shown during the login process. For that, use the show_dialog query parameter and set it to true when calling the https://accounts.spotify.com/authorize endpoint.
If there is a user already logged in, there will be a (Not you?) link to change the user.
This applies to the 'Authorization Code' and 'Implicit Grant' flows. You can read the documentation about the show_dialog parameter on the Spotify Web API Authorization Guide.
As addition to José M. Pérez his answer, if you really want to log out, it seems the only way you could achieve this is by opening the Spotify log out URL in the user's browser: https://www.spotify.com/logout/
To prevent CORB protection this could for example be achieved by opening a pop up window with JavaScript and close it after 2 seconds:
const url = 'https://www.spotify.com/logout/'
const spotifyLogoutWindow = window.open(url, 'Spotify Logout', 'width=700,height=500,top=40,left=40')
setTimeout(() => spotifyLogoutWindow.close(), 2000)
UPDATE:
https://accounts.spotify.com/en/logout could also be used, this will redirect to a login page instead of the Spotify main page which is nicer IMHO.
You want to simply logout from "spotify web api" then you should terminate your spotify session through clear authentication token like:
AuthenticationClient.clearCookies(getApplication());
I solved this using the asnwer #jpoppe provided. I didn't like the idea of having a popup window so I used an iframe instead.
<iframe style={{display: 'none'}} src="https://spotify.com/logout"></iframe>
One problem I found with this was if the user had signed in with facebook, when logging in on another account using facebook, they would automatically be signed in when they clicked the 'sign in with facebook' button. I couldn't find a simple way to solve this.

WebEngine "keep me logged in" functionality

Is there any way to store state, basically to have a "keep me logged in" functionality like browsers do?
I've been looking into the CookieManager, and search a lot but haven't been able to find anything on this.
I have a social feeds reader, in which if a user clicks on a link it is opened on a WebView. The thing is, that on every run of my app, when they click on a link pointing to a private facebook post, they need to log in to their accounts in order to view it, which is quite uncomfortable.
Appreciate your help.
I found this How do I persist cookies when using HTTPUrlConnection?
and this http://docs.oracle.com/javase/tutorial/networking/cookies/custom.html
which allowed me to create a persistent cookie handler.

Liferay changing the default redirect page when a does not have the specific role

This is basically two question? First i was wonder how to change the page liferay redirects when a user tries to access a page that has Power User view permissions. Liferay by default points to localhost:web/guest/home where they have their login page. On my application i have a different login in page and i want to redirect to the following page. I was browsing the web and found out that by setting auth.login.site.url=/whereiwontittopoint should actualy redirect me there. However it does not. I'm using Liferay 6.0.6 Community Editions. Has anyone done this? Is this the right way or this need to be done with a hook?
My other question is the following. I want to have a custom role on some pages. And i want when a user does not have that specfic role to be redirect to a totaly different page not the default login. I'm fairly sure this can be done by using the hook on some service but for some reason i can not identify this service.
EDIT
Ok for the first question i solved the issues. For the second question the answers i got here were not what i was looking for probably because i didn't post the question correctly. This is a full scenario of what i have done and what i need to do:
First of all i changed the /web/guest path that's on every liferay page to web/somthing/ this might not play a crucial role but the problems(some of the problems) started when that happend. THe over all idea is the following. I'm using spring mvc to create the application. I have created a backend to my application from where the admin can create pages for other users to see(This is not done by going to the control panel of liferay and adding a page but through the logic of the application). Once a page is created depending on some logic i create a role for that certain page(customer role also through code not the liferay admin). Some of the users are given this role if the satisfy some criteria and some are not. Here my problem arises, once a user that is loged in to my application tries to access a page (by inputting a direct URL in the browser to the page) that requres the view permision of the role i create for that page and the user does not have the appropriate role he gets redirect to lets say localhost/web/(username)/home a personal page and for some reason on that page by default from liferay he is able to view personal data(user name) of all other users of the application. My question is how through code to handle the redirection that happens of the above scenario.
I have tried on one attempt to actualy hook the servlet.service.events.pre action and before the user access that page to check if he has the appropriate permisions and actualy change his request. So far i have some issues but i can resolve them but this approach is not what i not rly what i am looking for because this action is executed before every single request on the application( and the page handling is just small part of that application) which means i will have a lot of code executing for no reason. I was wondering if there are any ways to add where the exception will redirect when i create the role? If not what action should i hook that will help me solve this scenario but with out the unneeded extrea trafic that i am creating with hooking servlet.service.events.pre action?
For the second stuff a bit hacky way could be as follows
1) Define set of roles against which you want to check in portal-ext.properties. You can add some property like my.super.secret.roles=rolename1,rolename2
2) Add a property for a redirect page url in portal-ext.properties so that you can redirect user there.
3)Add a custom attribute for Layout named checkForSecretRoles which has to be boolean and visible on Page. This will show you a checkbox in Manage page for each page, so that an admin can easily check or uncheck the value
4)Add a condition in your theme (portal_normal.vm) to check if the page has a check for secret role and then check the users role falls in any of the roles defined in portal-ext.properties. If yes then issue a redirect to the page specified by your custom redirect page url property
For your first question, it should work -
auth.forward.last.paths=/sign-in
sign-in would be your page name
The answer for your second question is, you have to create a Hook extending Action and made the below entry in your portal-ext.properties.
login.events.post=com.liferay.portal.events.LoginPostAction,com.liferay.portal.events.CustomLandingPageAction
There is a lot of information you can found on forum about how to use this property.
for 1. set default.landing.page.path=/whereiwontittopoint in portal.properties, see Liferay Login page redirect
for 2. create a hook, set servlet.service.events.post=com.my.action.MyAction and impliment this action, at this point you can redirect user to another page.

Resources