Keycloak: Locale from browser is not set for/after the login - locale

We use Keycloak in a Docker container (image: jboss/keycloak:10.0.1) and a custom theme, which contains a locale selector (analogous to the keycloak theme). So the "Internationalization Enabled" flag is set to true. Additionally we store that locale in the user profile of Keycloak, using a mapper (Client Scopes > profile > Mappers > locale (Token mapper; User Attribute))
When an user connects to that Keycloak instance - without cookies - the language of the browser is used for the login screen, so it is for example displayed with Spanish translations. Also the locale is selected in the combobox, which looks like this:
<#if realm.internationalizationEnabled>
<div id="kc-locale" class="${properties.kcLocaleClass!}">
<div id="kc-locale-wrapper" class="${properties.kcLocaleWrapperClass!}">
<div class="kc-dropdown" id="kc-locale-dropdown">
${locale.current?no_esc}
<ul>
<#list locale.supported as l>
<li class="kc-dropdown-item">
${l.label?no_esc}</li>
</#list>
</ul>
</div>
</div>
</div>
</#if>
Now the problem is that the Cookie KEYCLOAK_LOCALE is not set automatically for this first access. The login page is displayed in the correct language, but in the request (Java servlet) the locale of the user profile is used. This can lead to the case, that a Spanish user has the login screen in the correct language, but when he access the application it is displayed in the default language (e.g. English), respectively which is defined in the user profile.
The locale value itself is not updated in the user profile.
This is not the case when the user sets the locale in the selector again. Then the cookie KEYCLOAK_LOCALE is for example set to "es" and when accessing our application, the locale is correctly set in the request.
Is there any possibility to have the correct locale for the first access, so without existing cookies (which would set the last chosen value)?
One possibility would to handle this by selecting the locale value in the selector again if the cookie is not set (using JavaScript), but this would lead to a reload of the page and in my opinion this would be a bad workaround.

Related

Is it possible to load a Liferay portlet dynamically on a page from a .jsp file?

I have a portlet that is deployed on a page and I need to produce a link that will load a different portlet (which is in a different module) in full-screen mode. I can load the built in Login portlet this way without a problem, but when I try to load any of my custom portlets I get two red error boxes with the message "You do not have the roles required to access this portlet." And I have the permissions - I can access the portlet fine when added to a page - and I'm even testing with an omni-admin account.
The portlet ID that has the .jsp file is 'subscriptionmanagement_WAR_subscriptionmanagementportlet' and the portlet ID I'm trying to load is 'GRPSignupForm_WAR_NY511RMportlet'. The tag is:
<liferay-portlet:renderURL portletName="GRPSignupForm_WAR_NY511RMportlet" var="grpPortlet" windowState="<%= WindowState.MAXIMIZED.toString() %>">
</liferay-portlet:renderURL>
Which produces the URL: http://localhost:8080/group/test/unsubscribe?p_p_id=tripitinerary_WAR_NY511RMportlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
However, as I've mentioned, I have been able to load other portlets in this way. The login portlet for example using the same tag works fine:
<liferay-portlet:renderURL portletName="<%= PortletKeys.LOGIN %>" var="loginURL" windowState="<%= WindowState.MAXIMIZED.toString() %>">
<portlet:param name="mvcRenderCommandName" value="/login/login" />
</liferay-portlet:renderURL>
The obvious difference is that it is passing a specific render command parameter, but otherwise it is the same. It produces the URL:
http://localhost:8080/group/test-1/unsubscribe?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_com_liferay_login_web_portlet_LoginPortlet_mvcRenderCommandName=%2Flogin%2Flogin
For completeness, here is the code for the portlet I'm trying to load. But as I mentioned above, I have tried to load various portlets in this project and all of them produce the permissions error.
#Component(
immediate = true,
property = {
"com.liferay.portlet.display-category=root//NYSDOT//GRP",
"com.liferay.portlet.instanceable=false",
"com.liferay.portlet.header-portlet-css=/css/main.css",
"com.liferay.portlet.footer-portlet-javascript=/js/main.js",
"com.liferay.portlet.css-class-wrapper=grh-signup-form-portlet",
"javax.portlet.display-name=GRP Signup Form",
"javax.portlet.init-param.template-path=/html/",
"javax.portlet.init-param.add-process-action-success-action=false",
"javax.portlet.init-param.config-template=/html/configuration.jsp",
"javax.portlet.init-param.view-template=/html/view.jsp",
"javax.portlet.init-param.edit-template=/html/edit.jsp",
"javax.portlet.name=" + GRPSignupPortletKeys.GRPSIGNUP,
"javax.portlet.resource-bundle=content.Language",
"javax.portlet.security-role-ref=administrator,guest,power-user,user"
},
service = Portlet.class
)
public class GRPSignupPortlet extends GenericPortlet {
...
...
}
So it's obviously possible, as the Login portlet works. I'm sure there is just some small bit of config I'm missing. I've tried to see what is different in the Liferay Login portlet that allows it to work, but haven't found the secret.
Liferay CE 7.3
You need to add the property 'add-default-resource'. In the component add:
"com.liferay.portlet.add-default-resource=true"
From portal.properties: "add-default-resource" set to true will allow those portlets to be dynamically added to any page by any user. This is useful (and necessary) for some portlets that need to be dynamically added to a page, but it can also pose a security risk because it also allows any user to do it.
It's prudent to also add
"com.liferay.portlet.add-default-resource-check-enabled=true",
From portal.properties: Set this property to true to add a security check around this behavior. If set to true, then portlets can only be dynamically added to a page if it contains a proper security token. This security token is automatically passed when using a portlet URL from one portlet to another portlet.

How do you set a custom redirect url when using {% requireLogin %} in Craft 3?

I'm creating a "members only" site using Craft CMS (3) where users must login before they can see the front-end of the site. I'm wondering how you can set a default redirect after a user logs in.
I've got the member only part working using the {% requireLogin %} tag at the top of the main layout template, which redirects to /login, or in my case admin/login since I changed the value of loginPath in config/general.php to be /admin/login (Craft defaults to /login). So on every front-end page view, if the user is not logged in, it redirects to the Control Panel (CP) login.
layout.twig:
{% requireLogin %}
<!DOCTYPE html>
<html lang="en-US">
<head>
...
config/general.php:
...
'loginPath' => 'admin/login',
...
Documentation: https://docs.craftcms.com/v3/dev/tags/requirelogin.html
The default functionality, it seems, is that Craft then redirects you to whatever route you came from. So if you hit the site at /resources/ and it redirects you to the loginPath - after you successfully login it would kick you back to /resources/.
I'm wondering if there is a way to set a "default" redirect, so that no matter what page you come from, after a user logs in, they get redirected to the same place every time.
I know I am a year late, but here it goes:
You can use the postLoginRedirect general config setting (defined in /config/general.php). The docs state that this is
The path that users should be redirected to after logging in from the
front-end site. This setting will also come into effect if the user
visits the Login page (as specified by the loginPath config setting)
when they are already logged in.
The {% requireLogin %} tag doesn’t take any parameters. In fact you should be getting a Twig parsing error if you tried to do
{% requireLogin 'some/path' %}.
The path is specified by the loginPath config setting, which should support query strings.

Azure AD B2C strips html tags from Custom UI template

While trying to customise the unified (Sign In & Sign Up page), I have this simple HTML in my unified.html template (fragment):
<div class="col-4 login-box gradient-background">
<div>
<h1>WELCOME TO<br/>SuperFancyProductName<sup>®</sup></h1>
</div>
<div id="api" data-name="Unified"></div>
</div>
However, when Azure AD B2C renders the Sign In page, the element is stripped of from inside the h1 element, with this result (fragment):
<div>
<h1>WELCOME TO<br>SuperFancyProductName®</h1>
</div>
In our case, this does not allow us to properly align the ® symbol.
Is there any documentation on what tags are allowed in the template html and how this template transformation actually works?
There is a subset of HTML that is allowed but is not documented.
It looks like the superscript tag is not allowed here. For reference, see this Github issue.
The docs team is still working on an update to show what's allowed.
You can upvote some of the requests in User Voice or create your own request: https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/31173091-improve-the-tag-filtering-on-the-b2c-custom-ui-tem

Generate portlet instance id liferay

I'm building some pages in liferay 6.1 GA3, so recently I was in need of embedding liferay web content portlets in an other web content portlet for this I use something like :
<div class="somecontent_stuff">
<runtime-portlet name="56" instance="hj33" queryString=""/>
</div>
<div class="some other content">
<runtime-portlet name="56" instance="ze33" queryString=""/>
</div>
<div id="part_right">
<runtime-portlet name="56" instance="nj33" queryString=""/>
</div>
And this is working perfectly fine, but when I use my web content in multiple page I have the change instance id manually and for every page, which is exhausting and risky (because I have lot of pages like this ).
Is there any way to generate this code automatically ?
Capture the instance id of your embedded portlet using a web form. See this for more info

CSRF protection in login form

I'm using Symfony 2.1 to build a website with a little login form. I'm following the tutorial at this link but I don't see any part talking about the CSRF protection. However, here there are all the options for the login security and at the end I can clearly see that that type of protection should be supported. I don't understand how to use it
Here you can read in details about CSRF protection in version 2.1
In case if you don't use form classes for your forms, you can simply use csrf_token function (don't forget to pass your intention string there, which is empty by default):
<input type="hidden" name="token" value="{{ csrf_token('') }}">
It is defined here and in default cases will execute this method.
May be these answers might be useful for you also:
https://stackoverflow.com/a/12054712/970721
https://stackoverflow.com/a/11632713/970721
Nothing is preventing you from creating a form class for login. All you need to do is to tell the login controller the names of the generated fields:
form_login:
username_parameter: login[username]
password_parameter: login[password]
csrf_parameter: login[_token]
and set the form's CSRF intention to authenticate:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults([
'intention' => 'authenticate',
]);
}

Resources