Re: [keycloak-dev] passing SAML extensions and context to custom authenticators
by Caranzo Gideon
Hi Hynek,
Thank you for your response. Yes, I agree with you. It would be good to have this mechanism in those areas as well.
I already have a PR ready for just the SAML login portion. Is it fine with you if I submit this first so that we can use it as early as possible? We can create a separate ticket to implement similar mechanism for other SAML messages and broker endpoint which can be done in near future.
Thanks,
Gideon
-----Original Message-----
From: keycloak-dev-bounces(a)lists.jboss.org [mailto:keycloak-dev-bounces@lists.jboss.org] On Behalf Of Hynek Mlnarik
Sent: Thursday, January 24, 2019 1:58 AM
To: Gideon Caranzo <gideonray(a)gmail.com>
Cc: keycloak-dev <keycloak-dev(a)lists.jboss.org>
Subject: Re: [keycloak-dev] passing SAML extensions and context to custom authenticators
Hi Gideon,
thanks for the idea. Something like that would be a useful enhancement. The implementation would need to cover also the broker endpoint, other SAML message types (extensions are part of message types other than AuthnRequest as well), and count on several implementations of the hypothetical SamlAuthenticationPreprocessor. Could you please file an "Enhancement" JIRA?
--Hynek
On Wed, Jan 16, 2019 at 5:49 PM Gideon Caranzo <gideonray(a)gmail.com> wrote:
> Hi All,
>
> I'd like to propose a feature that allows custom authenticators to
> handle SAML extensions, authentication context and other request attributes.
>
> Right now in OIDC, all request claims are passed to custom
> authenticators which allows for customized behavior depending on the claims.
> However, this is not the case for SAML. Only attributes that are
> explicitly set (e.g. NameID) in the auth session are passed to custom authenticators.
>
> Information like SAML extension and authentication context are not
> available which limits the ability to define custom behaviors. In the
> past, we ran into similar limitation and we had to update keycloak
> core to add support for NameID attribute.
>
> To solve this, we can have an optional hook that pre-process SAML
> login request right before authentication. The hook can then extract
> the needed attributes and set it accordingly for custom authenticators to process.
>
> The pre-processing will be done in
> *SamlService.BindingProtocol.loginRequest()*:
>
> *public* *class* SamlService *extends* AuthorizationEndpointBase {
>
> *. . .*
>
> *public* *abstract* *class* BindingProtocol {
>
> . . .
>
> *protected* Response loginRequest(String relayState,
> AuthnRequestType requestAbstractType, ClientModel client) {
>
> . . .
>
> SamlAuthenticationPreprocessor preProcessor = session
> .getProvider(SamlAuthenticationPreprocessor.*class*);
>
> *if* (preProcessor != *null*) {
>
> preProcessor.process(requestAbstractType, authSession);
>
> }
>
>
>
> *return* newBrowserAuthentication(authSession,
> requestAbstractType.isIsPassive(), redirectToAuthentication);
>
> }
>
>
> Let me know what you think. Thanks.
>
> Best regards,
> Gideon
> _______________________________________________
> keycloak-dev mailing list
> keycloak-dev(a)lists.jboss.org
> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flis
> ts.jboss.org%2Fmailman%2Flistinfo%2Fkeycloak-dev&data=02%7C01%7Cgi
> deon.caranzo%40gemalto.com%7C6f947d88676b4f788b2108d681d1d529%7C37d0a9
> db7c464096bfe31add5b495d6d%7C0%7C0%7C636839135555784466&sdata=Yhpx
> 28KFJWJGa1kv1ROWWqJd3nt60YvAb0YmeKUU5Mg%3D&reserved=0
>
_______________________________________________
keycloak-dev mailing list
keycloak-dev(a)lists.jboss.org
https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists....
________________________________
This message and any attachments are intended solely for the addressees and may contain confidential information. Any unauthorized use or disclosure, either whole or partial, is prohibited.
E-mails are susceptible to alteration. Our company shall not be liable for the message if altered, changed or falsified. If you are not the intended recipient of this message, please delete it and notify the sender.
Although all reasonable efforts have been made to keep this transmission free from viruses, the sender will not be liable for damages caused by a transmitted virus.
5 years, 3 months
User TLS client certificate authentication - inconsistent DN string representation with LDAP
by Peck, Michael A
Hello,
I’ve configured Keycloak to authenticate users using TLS client certificate authentication.
I’ve also configured Keycloak to synchronize users with my LDAP server.
I’d like to match the TLS client certificate’s Subject DN to the Subject DNs synchronized from my LDAP server (which are stored by Keycloak in each user’s LDAP_ENTRY_DN attribute).
I’ve set that up, but am running into an issue that Keycloak appears to have inconsistent string representations of DNs between those two methods - so the Subject DNs from the TLS client certificate and the LDAP server aren’t matching as I was expecting.
The TLS client certificate DNs look like this:
CN=Peck Michael, OU=People, DC=test, DC=net
While the LDAP_ENTRY_DN attribute is formatted like this:
cn=Peck Michael,ou=People,dc=test,dc=net
It looks to me that the TLS client certificate DN string representation is coming from the standard Java X500Principal class used by calls to X509Certificate.getSubjectDN().getName() in keycloak/services/src/main/java/org/keycloak/authentication/authenticators/x509/X509ClientCertificateAuthenticator.java and the LDAP_ENTRY_DN string representation is coming from the toString method in keycloak/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/model/LDAPDn.java.
I modified the LDAPDn class’s toString method to follow the same format as used in the TLS client certificate DNs, and authentication works for me now.
Would the Keycloak project consider accepting a pull request to change the way LDAPDn formats DNs as strings?
(However I have not checked if this would impact other uses of the LDAPDn class within Keycloak or cause problems with upgrading existing deployments?)
The suggested change follows:
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/model/LDAPDn.java b/federation/ldap/src/main/
index 39e7d97..2f8c805 100644
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/model/LDAPDn.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/model/LDAPDn.java
@@ -87,9 +87,9 @@ public class LDAPDn {
if (first) {
first = false;
} else {
- builder.append(",");
+ builder.append(", ");
}
- builder.append(rdn.attrName).append("=").append(rdn.attrValue);
+ builder.append(rdn.attrName.toUpperCase()).append("=").append(rdn.attrValue);
}
return builder.toString();
Thank you,
Michael Peck
The MITRE Corporation
5 years, 10 months
Authentication SPI - Pinning the IDP
by gambol
Hiya
Hopefully someone know's a way around this ..
We have a requirement to pin a keycloak client to a specific group of login
options i.e. they can only login via a social provider and not a local
username/password, BUT we also wish to allow certain users the ability to
override the behavior. I mocked up authenticator which used the
IdentityProviderSpi.IDENTITY_PROVIDER_SPI_NAME checked it against the a
configurable list for the authenticator and also looked for a user override
attribute. Now on first login that works fine, but as the access token
comes up for refresh the IdentityProviderSpi.IDENTITY_PROVIDER_SPI_NAME is
not retained (i guess because it's now a sso session refresh and not a
login) and so the authenticator throws the error message.
Is it possible to hook into login only? .. Anyone think of another way
around it? :-) .. I tried using SetClientNotes / SetAuthNote to retain the
logged in provider, but that doesn't appear to work either.
Disclaimer: I know the official stance would be the IDP provides
authentication only with authorization handled by the application end, but
in many case's third party applications can't support this .. so was hoping
we could control it at source.
Rohith
5 years, 10 months
Better support for "scope" in adapters
by Marek Posolda
During my work on Client Scopes last year, I did not any work on the
adapters side. I think there is a space for improvement here. I will try
to summary current issues and some initial proposals for improve things.
Suggestions welcomed! And sorry for longer email :)
Both javascript adapter and servlet adapter has some way for requesting
the additional "scope" and ensure that that initial OIDC authentication
request sent to Keycloak will contain some custom "scope" parameter. The
javascript adapter has support for "scope" as an option of the "login"
method [1]. The servlet adapter has a possibility to inject custom
"scope" with parameters forwarding [2]. I am not sure about node.js and
other adapters TBH. But even for javascript and servlet adapter, the
current support is quite limited for few reasons. For example:
- The approach of parameters forwarding used in servlet adapters
requires to logout before requesting the additional scope. Because when
I am already authenticated in the application and I open secured URL
like http://localhost/app/secured?scope=some-custom-scope, the adapter
will just ignore it in case that user is already logged-in and it will
automatically forward to the application.
- Both servlet and javascript adapters support to have just single
"triplet" of tokens per browser session. In this context "triplet" means
the single set of 3 tokens (ID token , Access Token , Refresh token). So
for example when I want to request the custom scope for being able to
invoke "service1", I can use "scope=service1". However after Keycloak
redirects me back to the application, the existing triplet of tokens is
just replaced with the new one for "service1" . Then when I want to
later invoke another service like "service2", I need to request the
additional scope "scope=service2", which will replace my tokens on the
adapter's side with the "service2" tokens . But then later when I want
to switch again to "service1", I need to redirect to Keycloak again as
the current triplet of tokens for "service1" etc.
To improve this limitation, I think that it will be good if adapters
easily support the following:
- Instead of having single triplet of tokens, it will be good if
adapters can contain Map of tokens. Key of the map can be "scope"
parameter. So for example, the adapter will have "default" tokens
(those, which were used for initial login), the tokens for "service1"
and the tokens for "service2" .
- It will be nice if there is easy way to ask adapter for "service1"
scope. In case that I don't have yet this scope, adapter will redirect
me to Keycloak with "scope=service1". If I already have it, adapter will
return me an existing token. If existing access token is expired,
adapter will refresh the access token for requested scope in the
background and return me the "updated" token.
- When I want to invoke service1 and I need to use "scope=service1", I
usually need just access token and refresh token. I don't need ID Token
anymore. I also don't need the "profile" and "email" claims to be
returned in the new access token. This is related to the JIRA of having
the server-side support for client scopes like (always, default,
optional) instead of current (default, optional) [3]. In other words,
the client scopes "profile" and "email" will be default client scopes,
which means that if I don't use "scope=openid" in the OIDC initial
request, the "profile" and "email" will be ommited from the response as
well as the ID Token will be ommited from the response.
So how to support this on adapters? For Keycloak.js, I can think about
some variation of existing "update" method like this:
keycloak.updateTokenWithScope('service1',
5).success(function(accessToken, refreshed) {
if (refreshed) {
alert("I had existing accessToken for scope 'service1', but
it needed to be refreshed as it was expired or about to expire in less
than 5 seconds");
} else {
alert('I have accessToken for 'service1', which didn't
need to be refreshed');
}
// I can invoke REST service now with the accessToken
...
}).error(function() {
alert("Failed to refresh the token OR I don't have yet scope
for 'service1' .");
// User usually need to call keycloak.login with the requested
scope now...
});
For servlet adapter something like:
KeycloakSecurityContext ctx = ... // Retrieved from HttpServletRequest
or Principal as currently
if (ctx.hasScope("service1")) {
try {
String accessToken = ctx.getScope("service1");
// Invoke service1 with accessToken now
} catch (TokenRefreshException ex) {
log.error("I already had scope for service1, but failed to
refresh the token. Need to re-login for the scope service1");
// See method below
redirectToKeycloakWithService1Scope();
}
} else {
// See method below
redirectToKeycloakWithService1Scope();
}
private void redirectToKeycloakWithService1Scope() {
KeycloakRedirectUriBuilder builder = ctx.createLoginUrl();
URL url = builder.scope("service1").build();
httpServletResponse.sendRedirect(url);
}
Regarding the class KeycloakRedirectUriBuilder, I was thinking about
this class so that servlet adapter are able to easily create login URL
with custom values for things like scope, prompt, max_age etc. This
capability is currently missing in servlet adapters and the current
approach based on parameters forwarding is a bit clunky for few reasons.
One reason is usability and the other is, that you need to logout first.
[1]
https://www.keycloak.org/docs/latest/securing_apps/index.html#javascript-...
[2]
https://www.keycloak.org/docs/latest/securing_apps/index.html#_params_for...
[3] https://issues.jboss.org/browse/KEYCLOAK-8323
Marek
5 years, 10 months
More robust datasource configuration in Keycloak docker images
by Thomas Darimont
Hello Keycloak developers,
The current Keycloak server docker image comes with some default
configuration (listed below) for the supported databases (mysql, postgres,
mariadb), which work quite well so far.
However, in HA database production environments, we encountered some issues
with the default configuration. We were able to mitigate those issues with
the following general, and in our case PostgreSQL specific, settings.
I'd like to propose adding those settings to the "change-database.cli"
scripts of the default Keycloak docker images.
We faced the following problems:
1. Connections are not always validated before use.
If a database node is not available or has any issues, the connections in
the connection-pool don't reflect this immediately, although the
`check-valid-connection-sql` is set.
2. No timeout configured for database queries.
Some database queries in Keycloak could run quite slowly (due to
performance bugs, inefficient queries etc.). Sometimes this freezes the
admin-console and if the operation is retried in different tabs, could use
up all connections from the pool.
Eventually, the query runs into a timeout, but only after a driver specific
amount of time.
3. Creation of new connections could introduce an unnecessary long delay
(1-5s.
We managed to mitigate those issues by using the following additional
settings in production - and haven't seen any problems with database
connections since.
This mitigates problem 1: This ensures that a connection is "really" tested
before use.
# Configure datasource to connection before use
/subsystem=datasources/data-source=KeycloakDS/:write-attribute(name=validate-on-match,value=${env.DB_VALIDATE_ON_MATCH:true})
This mitigates problem 2: since we can now explicitly control how long a
query can run at max. --> better transparency.
# Configure datasource to use explicit query timeout in seconds
/subsystem=datasources/data-source=KeycloakDS/:write-attribute(name=query-timeout,value=${env.DB_QUERY_TIMEOUT:60})
This mitigates problem 3:
To reduce the time for connection reuse we also use the following setting
to use the next valid connection first, instead of immediately trying to
create a new one.
# Configure datasource to try all other connections before failing
/subsystem=datasources/data-source=KeycloakDS/:write-attribute(name=use-fast-fail,value=${env.DB_USE_CAST_FAIL:false})
In combination with PostgreSQL we also configured the following, which
helped to make the database error handling more robust:
/subsystem=datasources/data-source=KeycloakDS/:write-attribute(name=valid-connection-checker-class-name,value=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker)
/subsystem=datasources/data-source=KeycloakDS/:write-attribute(name=exception-sorter-class-name,value=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter)
This improves the PostgreSQL database error handling in Keycloak.
See:
https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_ap...
Note that this document contains useful configurations for other database
vendors as well.
For reference, this is the current postgres change-database.cli script:
https://github.com/jboss-dockerfiles/keycloak/blob/master/server/tools/cl...
```
/subsystem=datasources/data-source=KeycloakDS: remove()
/subsystem=datasources/data-source=KeycloakDS:
add(jndi-name=java:jboss/datasources/KeycloakDS,enabled=true,use-java-context=true,use-ccm=true,
connection-url=jdbc:postgresql://${env.DB_ADDR:postgres}:${env.DB_PORT:5432}/${env.DB_DATABASE:keycloak}${env.JDBC_PARAMS:},
driver-name=postgresql)
/subsystem=datasources/data-source=KeycloakDS:
write-attribute(name=user-name, value=${env.DB_USER:keycloak})
/subsystem=datasources/data-source=KeycloakDS:
write-attribute(name=password, value=${env.DB_PASSWORD:password})
/subsystem=datasources/data-source=KeycloakDS:
write-attribute(name=check-valid-connection-sql, value="SELECT 1")
/subsystem=datasources/data-source=KeycloakDS:
write-attribute(name=background-validation, value=true)
/subsystem=datasources/data-source=KeycloakDS:
write-attribute(name=background-validation-millis, value=60000)
/subsystem=datasources/data-source=KeycloakDS:
write-attribute(name=flush-strategy, value=IdleConnections)
/subsystem=datasources/jdbc-driver=postgresql:add(driver-name=postgresql,
driver-module-name=org.postgresql.jdbc,
driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource)
```
What do you think about adding the proposed settings?
Cheers,
Thomas
5 years, 10 months
Defining several Password Policies within a Realm
by AMIEL Patrice
Hi all,
We are currently working on adding the capability to define several Password Policies for a given realm.
The rationale is that in our systems, within a given realm, we have different "types" of accounts that have different constraints on password management. For instance:
- Administrators shall have long and complex passwords, with a very short password expiration time
- Regular users have a "normal" :P password strength, and medium expiration time
- Accounts for technical/automated access to the system shall never expire and have very long passwords
All these Users shall be part of the same Realm.
Obviously, these 3 types are only an example and there might be a need of more types or less types of accounts for other deployments => the number of Password Policies is not fixed in advance.
We would definitely like to push the work as a PR, but before doing that, we'd like to be sure that we are going on the good tracks so that this PR could be accepted.
The idea is consequently, from Web UI perspectives:
- To update the Password Policy pane so that we have first a list of what we could call "Password Policy Groups". Within this pane, an initial list would allow to list, create and edit the Password Policy Groups.
- When creating or editing one of the available Password Policy Groups, a sub pane would allow to select the individual Password Policies to be added to the Group.
- Then, on Users management section, a new drop-down field of the User edition page would enable to select the Password Policy Group to be applied to this specific User
- The Password Policy Group page might remain under the Authentication menu area... but it might also be eligible to be moved to a dedicated area similar to the current "Group" area (indeed, we would then have a "Roles Groups" area (this is indeed what the current "Group" area is) and a "Password Policy Groups" area...)
Note that it would maybe be more convenient to attach a Password Policy Group to a "Group" rather than to an individual User, but as Users may belong to several Groups, then it would generate conflicts when applying the individual Password Policies if they are conflicting (for example, one saying that the min password length is 10 characters while the other saying it is 15).
Impacts are:
- On the DB model and JPA classes to support a list of Password Policies (i.e. Password Policy Groups),
- On the User classes to support attachment of a User to a Password Policy Group
- On the GUI, as described above
- On the authentication process, to select the right Password Policy
- On the change password process, to select the right Password Policy
- On the REST API
Does this proposal make sense to you (any concern or recommendation) ?
Thanks for your feedbacks
Best regards,
Patrice
________________________________
This message and any attachments are intended solely for the addressees and may contain confidential information. Any unauthorized use or disclosure, either whole or partial, is prohibited.
E-mails are susceptible to alteration. Our company shall not be liable for the message if altered, changed or falsified. If you are not the intended recipient of this message, please delete it and notify the sender.
Although all reasonable efforts have been made to keep this transmission free from viruses, the sender will not be liable for damages caused by a transmitted virus.
5 years, 10 months
Switching to Native JavaScript promise by default
by Stian Thorgersen
I would like to switch the JavaScript adapter to use Native promises by
default and deprecate the legacy promise with the aim to remove it in the
future.
This would result in users that want to continue to use the legacy promise
having to explicitly enable this in the config.
I see this as the best path to eventually remove the legacy promises.
5 years, 10 months
Improve search by a specific user in the admin console
by Alexis Almeida
Considering an instalation of Keycloak where there are 2mi (or more) of
users on user_entity table, search for a specific user on the console is a
stressing task if you do it several times a day. I think it should be
possible to do "direct" search by username.
Today it is possible to search for a specific user by ID, by typing
id:xxxxxx in the search field in the console. IMO this feature could be
expanded, so someone could search for a specific user by username or by
email, like this: username:xxxxx or email:xxxxxx.
I made this change on my local machine and the result was ok.
private static final String SEARCH_USERNAME_PARAMETER = "username:";
private static final String SEARCH_EMAIL_PARAMETER = "email:";
.
.
.
} else if (search.startsWith(SEARCH_USERNAME_PARAMETER)) {
UserModel userModel =
session.users().getUserByUsername(search.substring(SEARCH_USERNAME_PARAMETER.length()).trim(),
realm);
if (userModel != null) {
userModels = Arrays.asList(userModel);
}
} else if (search.startsWith(SEARCH_EMAIL_PARAMETER)) {
UserModel userModel =
session.users().getUserByEmail(search.substring(SEARCH_EMAIL_PARAMETER.length()).trim(),
realm);
if (userModel != null) {
userModels = Arrays.asList(userModel);
}
} else {
5 years, 10 months
Authz services feedback
by Marek Posolda
I recently have a chance to play a bit more with authz services when
preparing for the devconf demo. Great stuff and cudos to Pedro and all
the others who contributed to authorization services!
I just have few questions and possible suggestions to improve in the
future :) Also based on some questions and discussion I had after the talk:
- My REST service was SpringBoot based and protected by policy enforced
configured in the applications.properties like this
https://github.com/mposolda/devconf2019-authz/blob/master/devconf2019-ser...
. However I was stuck when I wanted to enable UserManagedAccess for my
service. The PolicyEnforcerConfig.UserManagedAccessConfig is an empty
class and I couldn't figure how to properly add it in the
application.properties file. I've tried to add various things in
application.properties like this, but none of them helped:
keycloak.policy-enforcer-config.user-managed-access
keycloak.policy-enforcer-config.user-managed-access=
keycloak.policy-enforcer-config.user-managed-access= (Just left single
space here after equals character)
As a workaround, I ended with having separate bean to do it
programatically -
https://github.com/mposolda/devconf2019-authz/blob/master/devconf2019-ser...
. Is it a bug or is it just me doing something stupid?
- I wonder about possible improvements of keycloak-authz.js and if
usability can be a bit improved? More specifically I mean this:
-- Handling of the 401 response with UMA ticket from resource-server -
Can this be done "automatically"? I meant the flow described here:
https://www.keycloak.org/docs/latest/authorization_services/index.html#ha...
. Maybe the keycloak-authz itself can just handle the response from
resource server, then send the AuthorizationRequest to KC with the UMA
ticket and then possibly re-send the request to resource-server with new
RPT and do this "automatically" without a need to manually handle it by
the application like this:
https://github.com/keycloak/keycloak-quickstarts/blob/latest/app-authz-um...
. WDYT?
-- Another thing is refreshing of RPT. It looks that RPT response
contains the refresh token, so refreshing of RPTs is possible. However
the keycloak-authz.js client doesn't have any support for automatically
refreshing RPT token. I mean something similar, which is provided by
keycloak.js itself (method "keycloak.updateToken" which automatically
refreshes the token if needed). Due this limitation, it seems there is a
bug in our quickstart. When you try the quickstart
"app-authz-uma-photoz" and you go through the flow like this:
- Open http://localhost:8080/photoz-html5-client and login as jdoe
- Create some album
- Wait 10 minutes (RPT expiration is same like AccessTokenLifespan, so 5
minutes by default)
- Try to create some album again - now fails with 403 due the RPT
expired and no support for refreshing it in the keycloak-authz.js or the
application itself.
Should I create JIRA for this?
- It seems we don't have any Java based adapter for the frontend clients
written in Java? We have Java based authorization client, but that
provides just sending REST requests. It doesn't provide things like I
mentioned above though (Storing RPT, automatically refreshing RPT,
Automatically handling 401 response with the UMA ticket from
resource-server and sending the request to KC etc). Any plan to have this?
Marek
5 years, 11 months
IDP initiated flow redirect not working
by Priyadarshini Chandra
I am trying to implement below workflow for SAML auth using Keycloak:
1. User is logged-in to external website.
2. User clicks on the link for Service Provider which redirects the user to
Keycloak for SAML authentication. It is a HTTP POST Request with
SAMLResponse and RelayState.
3. Keycloak should validate the SAML token ,create session etc and redirect
the user to the Service provider application.
I have tried the IDP initiated Login flow and Client creation steps.
1.Created one IDP - idp1
2.Created a client - client1, master SAML points to idp1 endpoint.
3.Sending the HTTP Request with
SAMLResponse:"../broker/idp1/endpoint/clients/client1"
RelayState: Service provider application page.
We are stuck at the point where getting error "You are already
authenticated as different user 'testuser' in this session. Please logout
first."
It looks like session and user is getting created.
What should be the correct flow.
5 years, 11 months