Picketlink thread safety issues
by Stuart Douglas
Hi,
I have just been looking over Picketlink and I think I have spotted a couple of thread safety issues:
- File Data Store is not thread safe
It looks like there are quite a few problems here, but the biggest is that FileDataStore does not seem to use any sync, so multiple threads can be attempting to write out the database at the same time. Also threads can be modifying the database in memory at the same time it is being written out, so it is possible to write the DB in an inconsistent state.
Also when the file is written out it is written out directly over the old file, which greatly increases the chance of file corruption (rather than writing a tmp file and then moving it over the existing one). The also means that any sort of error (such as a non-serializable attribute) will corrupt the store and make it unreadable.
- LDAPIdentityStore is using SimpleDateFormat in a non-threadsafe manner
LDAPIdentityStore uses a static SimpleDateFormat, which is not thread safe. Not only that but this date format is modified before it is used in LDAPIdentityStore#parseLDAPDate, so if multiple threads are parsing dates with different timezone formats at the same time anything could happen.
Stuart
10 years, 9 months
Reseting passwords
by Bruno Oliveira
Good morning, on AeroGear we have the following scenario with PicketLink
beta5:
- Default user "admin" which must change her password at first
deployment, otherwise she will not be able to login
During the startup we have the following piece of code:
@Singleton
@Startup
public class PicketLinkDefaultUsers {
@Inject
private IdentityManager identityManager;
@PostConstruct
public void create() {
User adminUser = identityManager.getUser("admin");
Developer admin = new Developer();
admin.setLoginName("admin");
this.identityManager.add(admin);
this.identityManager.updateCredential(admin, new
Password("123"), new Date(), expirationDate());
Role roleDeveloper = new SimpleRole("admin");
this.identityManager.add(roleDeveloper);
identityManager.grantRole(admin, roleDeveloper);
}
//Expiration date of the password
private Date expirationDate() {
Calendar expirationDate = Calendar.getInstance();
expirationDate.add(Calendar.HOUR, -1);
return expirationDate.getTime();
}
}
On login:
public boolean login(User user, String password) {
credentials.setUserId(user.getLoginName());
credentials.setCredential(new Password(password));
if (identity.login() != Identity.AuthenticationResult.SUCCESS) {
return false;
}
return true;
}
Now to reset the password:
this.identityManager.updateCredential(admin, new Password(newPassword));
And here comes my question. At least to me it looks like is possible to
change admin's password by just guessing the username, my concern is
about an attacker being able to escalate privileges (I can be wrong). On
PicketLink do we have something internally like password matching? Or
maybe some mechanism to force user to change their password upon first
login? For example (just a very stupid example):
this.identityManager.updateCredential(admin, oldPassword, newPassword);
The correct solution (I guess) would be to check if that user has
already logged in and force admin to supply the new password, but the
method isLoggedIn will return false for credentials with status EXPIRED.
An alternative with the current scenario (maybe is just the lack of
knowledge in API usability) would be to validate and check credential
status.
Credentials credential = new UsernamePasswordCredentials("username", new
Password(password));
identityManager.validateCredentials(credential);
But I think that might exist something on PicketLink to verify if the
session exists, before reset user's password.
Any ideas?
-- abstractj
10 years, 9 months
Unable to put a partition type within a relationship
by Bill Burke
I'm unable to put a partition type within a Relationship property and
query on it:
org.picketlink.idm.IdentityManagementException: PLIDM000038: Could not
query Relationship using query
[org.picketlink.idm.query.internal.DefaultRelationshipQuery@5d834c31].
at
org.picketlink.idm.query.internal.DefaultRelationshipQuery.getResultList(DefaultRelationshipQuery.java:99)
at
org.keycloak.services.models.picketlink.RealmAdapter.getRequiredCredentials(RealmAdapter.java:254)
at
org.keycloak.test.AdapterTest.test2RequiredCredential(AdapterTest.java:90)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at
org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at
com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76)
at
com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.ClassCastException:
org.keycloak.services.models.picketlink.mappings.RealmData cannot be
cast to org.picketlink.idm.model.IdentityType
--
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com
10 years, 9 months
Keycloak datamodel
by Bill Burke
Keycloak is a SaaS in which people can register to create their own realms.
Default Realm:
User
Roles: REALM_CREATOR
Custom RealmAdminRelationship: Attribute: realmId, Attribute: User.
RealmId points to a realm a User has created
SSO Realms:
* A bunch of attributes for the Realm like private/public key stored in
an Agent
* Users
* Roles
* User/RoleMapping
* Custom RequiredCredentialRelationship. Defines the credential types
required by the realm.
* Custom ScopeRelationship. Scope is the same as role mapping, but this
defines an OAuth grant thing. It is the roles a user is allowed to
request permissions for. It is an Attribute of an Agent and a Role.
* Custom ResourceRelationship. A resource is an application that is
managed by the realm. This has Attribute Agent pointing to the Agent of
the realm, various attributes of the resource, and also a String value
pointing to the Tier. I couldn't figure out how to have a hard
relationship to a Tier
Resource (maps to Tier)
* Roles
* User/RoleMapping
* ScopeRelationship
--
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com
10 years, 9 months
IDM and vault are the same thing
by David M. Lloyd
Consider:
IDM:
* associates identities with credentials
* provides ability to retrieve credentials or verify against credentials
Vault:
* associates identities with credentials
* provides ability to retrieve credentials or verify using credentials
So, they're basically the same thing, except vaults are kind of a crappy
hack. Instead of using a sys prop kludge for vaulted passwords, we
should have an explicit reference to an identity store plus an identity,
and simply not have a field for passwords in the config, period.
Discuss
--
- DML
10 years, 9 months