-
Notifications
You must be signed in to change notification settings - Fork 614
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1909 from madhukarbharti/issue-1840
Issue-1840: Improve password encoding support for LDAP
- Loading branch information
Showing
25 changed files
with
754 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 12 additions & 1 deletion
13
strongbox-security/strongbox-authentication-providers/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,12 @@ | ||
Strongbox authentication providers enumerates all supported builin authentication providers. | ||
# strongbox-authentication-providers | ||
|
||
Strongbox authentication providers enumerates all supported built-in authentication providers. | ||
|
||
NOTE: | ||
|
||
There is currently some conflicting terminology due to Spring's conventions: | ||
|
||
* `Authentication Provider` in Spring is a mechanism which provides some sort of authentication credentials | ||
(i.e. Basic Authentication). | ||
* `Authentication Provider` in Strongbox is a `database` of some sort, which provides the users to authenticate against. | ||
|
32 changes: 31 additions & 1 deletion
32
...ngbox-authentication-providers/strongbox-ldap-authentication-provider/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,31 @@ | ||
Strongbox LDAP authentication provider. | ||
# strongbox-ldap-authentication-provider | ||
|
||
This module provides the functionality to authenticate users using an LDAP server as the data source. | ||
|
||
## Manual testing with OpenLDAP | ||
|
||
Sometimes you might need to do manual testing with an OpenLDAP server. In the `project root` path we already have | ||
`docker-compose.yml` which has everything you need to proceed. The only thing you need is an installed Docker | ||
([guide here](https://docs.docker.com/get-docker/)). | ||
|
||
Terminal 1: | ||
|
||
1. `cd project root` | ||
2. `docker-compose up openldap` (if you've made changes to the ldif files you might need to | ||
`docker-compose up --force-recreate openldap` instead) | ||
|
||
Terminal 2: | ||
|
||
1. `cd project root` | ||
2. `mvn clean install -DskipTests` | ||
3. `mvn -pl strongbox-web-core spring-boot:run` | ||
|
||
Browser: | ||
|
||
1. Open `http://localhost:48080/` | ||
2. Go over the security settings | ||
3. Testing using curl should return `Status 200` | ||
``` | ||
curl -I -u an-existing-ldap-user http://localhost:48080/api/account | ||
``` | ||
|
142 changes: 142 additions & 0 deletions
142
...in/java/org/carlspring/strongbox/authentication/api/ldap/CustomLdapUserDetailsMapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package org.carlspring.strongbox.authentication.api.ldap; | ||
|
||
import java.util.Base64; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.security.crypto.codec.Hex; | ||
import org.springframework.security.crypto.codec.Utf8; | ||
import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper; | ||
import org.springframework.util.StringUtils; | ||
|
||
/** | ||
* This class handles password base64 decoding based on the property strongbox.authentication.ldap.userPasswordEncoded. | ||
* | ||
* <p> | ||
* When set to true will handle these possible cases: | ||
* {ALG}base64.encode(md5/sha1/bcrypt(mypassword)) | ||
* base64.encode({ALG}md5/sha1/bcrypt(mypassword)) | ||
* <p> | ||
* | ||
* <p> | ||
* When set to false will handle the ordinary case: | ||
* {ALG}md5/sha1/bcrypt(mypassword) | ||
* </p> | ||
* | ||
* @author mbharti | ||
* @date 19/10/20 | ||
*/ | ||
public class CustomLdapUserDetailsMapper | ||
extends LdapUserDetailsMapper | ||
{ | ||
|
||
private static final String PREFIX = "{"; | ||
|
||
private static final String SUFFIX = "}"; | ||
|
||
private static final String EMPTY_STRING = ""; | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(CustomLdapUserDetailsMapper.class); | ||
|
||
private boolean isUserPasswordEncoded; | ||
|
||
protected String mapPassword(Object passwordValue) | ||
{ | ||
String passwordValueString = super.mapPassword(passwordValue); | ||
|
||
if (!isUserPasswordEncoded()) | ||
{ | ||
return passwordValueString; | ||
} | ||
|
||
return decodeBase64EncodedPassword(passwordValueString); | ||
} | ||
|
||
private String decodeBase64EncodedPassword(String prefixEncodedPasswordString) | ||
{ | ||
try | ||
{ | ||
String algorithmUsed = extractId(prefixEncodedPasswordString); | ||
String extractBase64EncodedHash = prefixEncodedPasswordString; | ||
|
||
if (!StringUtils.isEmpty(algorithmUsed)) | ||
{ | ||
extractBase64EncodedHash = extractEncodedPassword(prefixEncodedPasswordString); | ||
|
||
return PREFIX + algorithmUsed + SUFFIX + decodeBase64EncodedHashWithHex(extractBase64EncodedHash); | ||
} | ||
else | ||
{ | ||
return new String(Base64.getDecoder().decode(Utf8.encode(extractBase64EncodedHash))); | ||
} | ||
} | ||
catch (Exception e) | ||
{ | ||
logger.warn("Failed to match password after decoding base64encoded hash after algorithm", e); | ||
|
||
return prefixEncodedPasswordString; | ||
} | ||
} | ||
|
||
private String decodeBase64EncodedHashWithHex(String base64EncodedHash) | ||
{ | ||
try | ||
{ | ||
return new String(Hex.encode(Base64.getDecoder().decode(Utf8.encode(base64EncodedHash)))); | ||
} | ||
catch (Exception ex) | ||
{ | ||
logger.warn("decode hash using base64! " + ex.getMessage(), ex); | ||
} | ||
|
||
return base64EncodedHash; | ||
} | ||
|
||
private String extractEncodedPassword(String prefixEncodedPassword) | ||
{ | ||
int start = prefixEncodedPassword.indexOf(SUFFIX); | ||
|
||
return prefixEncodedPassword.substring(start + 1); | ||
} | ||
|
||
private String extractId(String prefixEncodedPassword) | ||
{ | ||
int start = prefixEncodedPassword.indexOf(PREFIX); | ||
|
||
if (start != 0) | ||
{ | ||
return EMPTY_STRING; | ||
} | ||
|
||
int end = prefixEncodedPassword.indexOf(SUFFIX, start); | ||
|
||
if (end < 0) | ||
{ | ||
return EMPTY_STRING; | ||
} | ||
|
||
return prefixEncodedPassword.substring(start + 1, end); | ||
} | ||
|
||
|
||
/** | ||
* Getting value whether Base64EncodedPassword is enabled or not | ||
* | ||
* @return boolean | ||
*/ | ||
public boolean isUserPasswordEncoded() | ||
{ | ||
return isUserPasswordEncoded; | ||
} | ||
|
||
|
||
/** | ||
* Setting value whether Base64EncodedPassword is enabled or not | ||
* | ||
* @param userPasswordEncoded | ||
*/ | ||
public void setUserPasswordEncoded(boolean userPasswordEncoded) | ||
{ | ||
isUserPasswordEncoded = userPasswordEncoded; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.