Pass locale from Spring web App to KeyCloak and back - locale

I have a multilingual spring boot web app which integrates with Keycloak (openId). For the Keycloak integration I´m using the keycloak-spring-security-adapter. The Locale state in my application is managed by the LocaleContextHolder. How can I pass my locale to Keycloak login page? I´ve found out there is a url parameter 'kc_locale', but I have no idea how to pass it, if I don´t want to override a lot of classes from Keycloak.
Is there an easy way to pass the locale to Keycloak login/Keycloak adapter?

While I know you're asking about Spring/Java, I wanted to give you something that may help
The OpenID Connect spec (https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) has a parameter ui_locales which may be helpful
ui_locales
OPTIONAL. End-User's preferred languages and scripts for the user interface, represented as a space-separated list of BCP47 [RFC5646]
language tag values, ordered by preference. For instance, the value
"fr-CA fr en" represents a preference for French as spoken in Canada,
then French (without a region designation), followed by English
(without a region designation). An error SHOULD NOT result if some or
all of the requested locales are not supported by the OpenID Provider.
You can pass this parameter to your OpenID Connect request, and Keycloak should honour it, according to this description: https://www.keycloak.org/docs/latest/server_development/#_locale_selector
With internationalization enabled, the locale is resolved in the
following priority:
kc_locale query parameter
KEYCLOAK_LOCALE cookie value
User’s preferred locale if a user instance is available
ui_locales query parameter
Accept-Language request header
Realm’s default language

Related

Custom Policies: Prevent unsupported locales even if language is passed directly to the user flow

We have started using some custom localized html files to show some localized headlines etc. to our users.
As per this article, we just uploaded a couple of html files for rendering.
https://contoso.blob.core.windows.net/{Culture:LanguageName}/myHTML/unified.html
However, when a user flow is started with an explicit locale set (e.g. &lang=es or UI-locales=es-ES) and we don't have a file for this locale, we get an error page.
AADB2C90002: The CORS resource 'https://anyhelpappreciated.blob.core.windows.net/es/myHTML/unified.html' returned a 404 not found.
We have set up SupportedLanguages, but this does not seem to do anything if the locale is passed explicitly. I don't want to have to rely on the applications not passing me this parameter.
<Localization Enabled="true">
<SupportedLanguages DefaultLanguage="en" MergeBehavior="ReplaceAll">
<SupportedLanguage>en</SupportedLanguage>
<SupportedLanguage>de</SupportedLanguage>
<SupportedLanguage>it</SupportedLanguage>
</SupportedLanguages>
...
Is there a way to prevent this?
This behavior is "by design" and cannot be changed.
https://github.com/MicrosoftDocs/azure-docs/issues/47654
For localization, you can provide the query string parameter, ui_locales, from your application. When you call into Azure AD B2C, your page is translated to the locale that you have indicated. This type of configuration gives you complete control over the languages in your user flow and ignores the language settings of the customer's browser.
You might not need that level of control over what languages your customer sees. If you don't provide a ui_locales parameter, the customer's experience is dictated by their browser's settings. You can still control which languages your user flow is translated to by adding it as a supported language. If a customer's browser is set to show a language that you don't want to support, then the language that you selected as a default in supported cultures is shown instead.
The {Culture:RFC5646} claim resolver works in the same way. Meaning If a customer's browser is set to show a language that you don't want to support, then the language that you selected as a default in supported cultures is sent to the HTML page instead.
The only case where an unsupported ui_locales will be sent to the HTML page, is when the app passes the missing ui_locales in the query string. In this case we consider that to be an application decision and allow it to override supported cultures configuration.
So, make sure your application sends only supported language in the ui_locales query string parameter.

What information is needed to write an abstract LDAP Integration Service

I've been tasked with researching/writing an LDAP integration module to support any/all clients that use local LDAP authentication for our new app. As I've never worked with LDAP before, I'm trying to figure out what settings are required/not required, and what settings I'd need to capture from each LDAP system to be able to support them all. So if I'm storing data in a database about each LDAP server, what is needed about that server to be able to successfully auth with a username/password?
I see lots of ou/cn/dc references, but sometimes people don't use them in their connection strings? And unless pre-registered, it seems like I'd have no way of knowing the names of the groups/categories to query against. I was thinking about the SAML spec and was curious if LDAP systems have an endpoint to retrieve some kind of XML describing their LDAP hierarchy? Or if I'd just need to know/ask for it from a sysadmin in advance?
FWIW I'm using Node/ldapjs
There is no standard way of describing the LDAP hierarchy in the manner you were considering. LDAP is in fact self-describing, you can search for a particular entry regardless of it's position in the LDAP tree by looking up one of its attribute's value.
So, to get started with completely unknown LDAP you only require it's network parameters: hostname, port (and even that can be avoided if you consult SRV DNS records (_ldap._tcp.domain.com)) and authentication details in the form of bind DN and password.
After that you can search for users, typically by looking up with filter like (objectClass=inetOrgPerson), or groups of users with filter like (objectClass=groupOfNames). Then you would use common attributes such as username, CN or displayName to reference or display the users in the user interface.
As you can see from this LDAP servers are very self defining and this ideally works for most LDAP servers, but as you perceived in your question it can differ from one LDAP server to another.
So here is my list of LDAP configuration settings that should be configurable:
hostname/port number (if not using DNS discovery)
username/password (if not using anonymous access)
does the server use SSL (port 636 by default) (or detect support for StartTLS)
user filter and user base DN (e.g. (objectClass=inetOrgPerson) and o=users)
group filter and group base DN (e.g. (objectClass=groupOfNames) and o=groups)
Depending on your use case you could define what attributes are used for displaying the user, mapping them to other parts of your application/system or you could determine those from the returned set of attributes. I've seen implementations that have that very configurable and implementations that default to some standard schema.

When trying to create a SSL connection with LWP::UserAgent, what do I use for realm?

I've started a project to scrape my work's employee website to scrape the user's (in this case, mine) schedule and munge the data onto a google calendar. I've decided to go with Perl with LWP.
The problem is this, when trying to set up SSL negotiations I don't know what do put for the 'realm'.
For example: (http://www.sciencemedianetwork.org/wiki/Form_submission_with_LWP,_https,_and_authentication)
# ...
my $ua = new LWP::UserAgent;
$ua->protocols_allowed( [ 'http','https'] );
$ua->credentials('some.server:443',**'realm'**,'username','password');
# ...
I've looked at everything my browser can tell me and at a wireshark packet capture trying to find anything but to no avail. I assume that second argument to credentials() isn't optional.
Where do I find the 'realm' I'm supposed to use?
The credentials are for the HTTP authentication protocol (RFC 2617) (Wikipedia).
The server can challenge the client to authenticate itself. This response contains a string called “realm” which tells the client for what authentication is required. This allows the same server under the same domain to request authentication for different things, e.g. in a content management system where there might be an “user password” and an “administrator password”, which would be two different realms.
In a browser, this realm would be displayed alongside the username and password box which allows the user to type in the correct password.
To discover the realm, navigate to a page which requires authentication and look for the WWW-Authenticate header.
Note that HTTP authentication has become quite uncommon, with session cookies being used more often. To deal with such an authentication scheme, make sure that your LWP::UserAgent has an attached cookie storage, and then navigate through the login form before visiting your actual target page. Using WWW::Mechanize tends to make this a lot easier.

OWASP Application Security Verification Standard - V3 and using with JSF

At the moment I'm dealing with implementing everything is to be safe against the security risks of the Top 10 Project
For #4 of the Top 10 - Insecure Direct Object References the OWASP refers to the OWASP Application Security Verification Standard
So I was reading all the suff in V3, but I have now some questions implementing it.
I'm using JBoss-AS 7.0.1 with Java EE6 and JSF 2.0
V3.4 Verify that the session id is never disclosed other than in cookie headers; particularly in URLs, error messages, or logs. This includes verifying that the application does not support URL rewriting of session cookies.
I read some articles here on stackoverflow how to avoid that the jesssion is in the URL for the first time a user is visiting the side...
But many answers are like: use the URL rewriting ... what does this means in contrast to the does not support URL rewriting of session cookies
What is the normal way to deal with jsessions on the first entry? What is a save way to handle it?
V3.10: Verify that only session ids generated by the application framework are recognized as valid by the application.
How you do this in JSF2.0 / JavaEE?
V3.12: Verify that cookies which contain authenticated session tokens/ids have their domain and path set to an appropriately restrictive value for that site.
What does this mean? When i look with my Firebug into the the cookie, I run the webapp from the URL http://localhost:8080/projectname/
and in the cookie i get: Path: /projectname
is this what the OWASP means with have their domain and path set to an appropriately restrictive value for that site. ?
Thank you!
V3.4 Verify that the session id is never disclosed other than in cookie headers; particularly in URLs, error messages, or logs. This includes verifying that the application does not support URL rewriting of session cookies.
The servlet container is by default configured to support session tracking by cookies and URLs. The session tracking by URL is also known as "URL rewriting" wherein you see the ;jsessionid=[session id] to appear in URLs. This will be triggered automatically when the client has cookies disabled. To disable tracking by URL, you need to explicitly specify a tracking mode by cookie only. Add this to the webapp's web.xml:
<session-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
Further you need to make sure that the JSF code is nowhere printing the session ID to the HTML output by among others <h:outputText value="#{session.id}" />.
V3.10: Verify that only session ids generated by the application framework are recognized as valid by the application.
The servlet container will by default already do that. Only Tomcat 6.x (and inherently thus also JBoss 5.x) had the security issue that when the server-wide session sharing is been enabled, then the server will use exactly the session ID as supplied by the client in the Cookie request header. Tomcat 7.x (and inherently thus also JBoss 6.x/7.x) will not do that anymore. See also among others the Tomcat 6.x <Connector> documentation for some more background information (check the emptySessionPath attribute description).
V3.12: Verify that cookies which contain authenticated session tokens/ids have their domain and path set to an appropriately restrictive value for that site.
The servlet container will by default already do that. Only when you configure the servlet container to use server-wide session sharing (thus, the same session is been shared between all deployed applications), then it violates the rule. See also the previous point.
Please note that most of those rules have very little to do with JSF. They have more to do with general server and webapp configuration. JSF is merely a component based MVC framework.

JSP login with declarative security - How does the actual authentication happen?

I've been a little puzzled with this as I have not seen many examples that gave me the complete picture. The best explanation I found so far is this.
By defining a security role in web.xml such as "admin" for example, and having my login form with all the necessary fields (i.e j_security_check as action, and fields j_username, j_password), how/where does the actual authentication occur?
I plan to use a custom authentication using username/passwords (hashes) stored in the database. When the user submits the form, how do I make the Java EE Web Container invoke my sevlet/bean method do perform the actual authentication? I didn't notice any place to add a hook to my code in web.xml which would do the actual authentication.
By defining a security role in web.xml such as "admin" for example, and having my login form with all the necessary fields (i.e j_security_check as action, and fields j_username, j_password), how/where does the actual authentication occur?
In the servlet implementation, the servletcontainer. In Tomcat for example, it's done by the AuthenticatorBase class (source code here).
I plan to use a custom authentication using username/passwords (hashes) stored in the database. When the user submits the form, how do I make the Java EE Web Container invoke my sevlet/bean method do perform the actual authentication? I didn't notice any place to add a hook to my code in web.xml which would do the actual authentication.
If you'd like to keep using container managed authentication, but instead want to check the login against a database, then you need to configure the so-called "realm" accordingly. It's unclear which servletcontainer you're using, but in for example Tomcat, the documentation is available here: Tomcat 6.0 Realm HOW-TO.
If you really want to have your own homegrown authentication system invoked instead, then you need to drop the container managed security and homegrow it further. Which is not recommended.
The actual authentication is doing via either two ways:
Via a Server Proprietary way, e.g. the *LoginModules in JBoss, or the Tomcat one BalusC mentioned. These are different for each Server.
Via JASPIC, which was introduced in Java EE 6.
JASPIC pretty much has standardized the proprietary methods, but it's a fairly low-level API and unfortunately only available for full profile Java EE 6 and 7 implementations.
See Implementing container authentication in Java EE with JASPIC for more details.

Resources