Forums

Home » Liferay Portal » English » 3. Development

Combination View Flat View Tree View
Threads [ Previous | Next ]
toggle
John Brown
Using Liferay 6.2 user credentials with CAS
April 21, 2014 9:38 AM
Answer

John Brown

Rank: New Member

Posts: 13

Join Date: April 21, 2014

Recent Posts

Hi All:

I have read how to integrate Liferay 6.0.5 with CAS using SHA1 here: http://stackoverflow.com/questions/9292979/how-do-i-alter-cas-configuration-to-use-email-password-authentication

However it feels like too many dependencies are being imported when I think from reading here: https://crackstation.net/hashing-security.htm#javasourcecode it shouldn't be this complicated nor should I need to rely on so many dependencies ... unless I do: please advise.

What essentially I am trying to understand is that does Liferay encryption store the salt with the password? i.e. password = salt + password hash? If so, what is the structure? I also see a digest column in the User_ table, what is that for and does it play a role in decryption?

I see this code in PBKDF2PasswordEncryptor :
 1               ByteBuffer byteBuffer = ByteBuffer.allocate(
 2                2 * 4 + saltBytes.length + secretKeyBytes.length);
 3
 4            byteBuffer.putInt(pbkdf2EncryptionConfiguration.getKeySize());
 5            byteBuffer.putInt(pbkdf2EncryptionConfiguration.getRounds());
 6            byteBuffer.put(saltBytes);
 7            byteBuffer.put(secretKeyBytes);
 8
 9            return Base64.encode(byteBuffer.array());


for example sake i am using 160 hash size with 128000 rounds. Encoding algorithm is PBKDF2 and AES encryption key size is 128.

Based on this once I coud do Base64.decode(encryptedString.), I should be able to pull these things out of the byteBuffer by the indexes, correct? i.e. byteBuffer.get(0) for key size, byteBuffer.get(1) for rounds, byteBuffer.get(2) for saltBytes, and byteBuffer.get(3) for secret key bytes, correct?

If this thought process is not correct, please advise. I have built a PasswordEncoder passed on the logic in PBKDF2PasswordEncryptor and would like to basically compare the hashed password with a new hash generated for the same password for authentication via CAS. To generate same hash for same password I need to get the salt value used and that is where I am stuck.

Thanks for all help.

Regards,
John
Tomas Polesovsky
RE: Using Liferay 6.2 user credentials with CAS
April 22, 2014 2:54 AM
Answer

Tomas Polesovsky

LIFERAY STAFF

Rank: Liferay Master

Posts: 653

Join Date: February 13, 2009

Recent Posts

Hi,

you are right, you don't need the example from stackoverflow and it's possible for you to implement it yourself.

The PBKDF2 Liferay password has this structure:
1In bytes:
2   | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
3 0 |   Key Size    |  # of rounds  |
4 8 |             Salt              |
516 |             Hash              |
6...| length based on the key size  |

You need to have the existing password from DB to extract salt the same way as in PBKDF2EncryptionConfiguration

With the clear-text password, salt, key size and rounds you can create the same PBKDF2 hash as is stored in the DB.

HTH.
John Brown
RE: Using Liferay 6.2 user credentials with CAS
April 24, 2014 9:58 AM
Answer

John Brown

Rank: New Member

Posts: 13

Join Date: April 21, 2014

Recent Posts

Tomáš Polešovský:
Hi,

you are right, you don't need the example from stackoverflow and it's possible for you to implement it yourself.

The PBKDF2 Liferay password has this structure:
1In bytes:
2   | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
3 0 |   Key Size    |  # of rounds  |
4 8 |             Salt              |
516 |             Hash              |
6...| length based on the key size  |

You need to have the existing password from DB to extract salt the same way as in PBKDF2EncryptionConfiguration

With the clear-text password, salt, key size and rounds you can create the same PBKDF2 hash as is stored in the DB.

HTH.


Hi Tomas:

Thanks for the reply. Based on the information you provided I was able to write a custom module to do clear text password encryption and authenticate user using the Liferay 6.2 User_ table.

I have another problem. Once I click the "Sign-in" link from Liferay, I end up on the CAS login form. After I am authenticated from CAS it redirects me back to the login page with the sign-in form and link on top "sign-in". If i click the "sign-in" link i keep getting redirected to the same page as CAS has already authenticated the user/pass combination.

What am I missing? I went over the instructions in documentation and have done exactly as stated. Do I need to do something to "inform" Liferay that a user has been authenticated by CAS? I have checked the CAS checkbox under control panel configurations.

Any and all help is appreciated. Thanks.
Tomas Polesovsky
RE: Using Liferay 6.2 user credentials with CAS
April 24, 2014 12:38 PM
Answer

Tomas Polesovsky

LIFERAY STAFF

Rank: Liferay Master

Posts: 653

Join Date: February 13, 2009

Recent Posts

John Brown:

Hi Tomas:

Thanks for the reply. Based on the information you provided I was able to write a custom module to do clear text password encryption and authenticate user using the Liferay 6.2 User_ table.

Great!

]I have another problem. Once I click the "Sign-in" link from Liferay, I end up on the CAS login form. After I am authenticated from CAS it redirects me back to the login page with the sign-in form and link on top "sign-in". If i click the "sign-in" link i keep getting redirected to the same page as CAS has already authenticated the user/pass combination.

What am I missing? I went over the instructions in documentation and have done exactly as stated. Do I need to do something to "inform" Liferay that a user has been authenticated by CAS? I have checked the CAS checkbox under control panel configurations.


CAS should redirect the request to http://portal-site/c/portal/login?ticket=... with the CAS ticket. There should be CASFilter listening for the ticket.

I haven't created any CAS module, but I guess you should setup the principal name in CAS to be user's email address (email is the default) or screen name (in case you turned on authentication by screen name):
 1// CASFilter: https://github.com/liferay/liferay-portal/blob/master/portal-impl/src/com/liferay/portal/servlet/filters/sso/cas/CASFilter.java#L194,L202
 2    Assertion assertion = ticketValidator.validate(ticket, serviceUrl);
 3    if (assertion != null) {
 4            AttributePrincipal attributePrincipal =
 5                assertion.getPrincipal();
 6        login = attributePrincipal.getName();
 7        session.setAttribute(WebKeys.CAS_LOGIN, login);
 8    }
 9
10// CASAutoLogin: https://github.com/liferay/liferay-portal/blob/master/portal-impl/src/com/liferay/portal/security/auth/CASAutoLogin.java
11...
12    String login = (String)session.getAttribute(WebKeys.CAS_LOGIN);
13...
14    if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
15        user = UserLocalServiceUtil.getUserByScreenName(
16            companyId, login);
17    }
18    else {
19        user = UserLocalServiceUtil.getUserByEmailAddress(
20            companyId, login);
21    }
22...
John Brown
RE: Using Liferay 6.2 user credentials with CAS
April 25, 2014 7:51 AM
Answer

John Brown

Rank: New Member

Posts: 13

Join Date: April 21, 2014

Recent Posts

Tomáš Polešovský:

CAS should redirect the request to http://portal-site/c/portal/login?ticket=... with the CAS ticket. There should be CASFilter listening for the ticket.



The thing is CAS isn't return the ticket appended to the URL. This is how I have configured the service URL:
[https://mymachine:8443//portal/*]

Let me know if I need to change the above. My portal-ext.properties file:
auto.login.hooks=com.liferay.portal.security.auth.BasicAutoLogin,com.liferay.portal.security.auth.CASAutoLogin

I haven't configured anything in web.xml or liferay-web.xml and I am assuming I don't need to as the property above will invoke the filter?

Thanks for the help so far.
Tomas Polesovsky
RE: Using Liferay 6.2 user credentials with CAS
April 28, 2014 6:42 AM
Answer

Tomas Polesovsky

LIFERAY STAFF

Rank: Liferay Master

Posts: 653

Join Date: February 13, 2009

Recent Posts

John Brown:
Tomáš Polešovský:

CAS should redirect the request to http://portal-site/c/portal/login?ticket=... with the CAS ticket. There should be CASFilter listening for the ticket.



The thing is CAS isn't return the ticket appended to the URL. This is how I have configured the service URL:
[https://mymachine:8443//portal/*]


When I try your configuration, CAS redirects me to this URL: https://mymachine:8443//portal/*?ticket=ST-8-uof1Fkp3NJtFNPRUthFD-cas

You can see it's invalid URL so portal redirects the request to a default page, without the ticket param.

So I think that's it.

The difference between specifying serviceURL and serverURL:
- with serviceURL the users will be always redirected to this fixed URL, and it should end with /c/portal/login. CASFilter sits on /c/portal/login so the serviceURL should point back to that URL
- with serverURL portal specifies serviceURL dynamically so that users can be redirected back to the original page

HTH.
John Brown
RE: Using Liferay 6.2 user credentials with CAS
April 28, 2014 8:07 AM
Answer

John Brown

Rank: New Member

Posts: 13

Join Date: April 21, 2014

Recent Posts

John Brown:

The thing is CAS isn't return the ticket appended to the URL. This is how I have configured the service URL:
[https://mymachine:8443//portal/*]


I did some debugging and actually CAS *IS* returning the URL with the ticket appended to it. However on the Liferay side the filter isn't getting invoked, or at least I can't tell.

Please help as I am dead in the water at the moment. Thanks.
Tomas Polesovsky
RE: Using Liferay 6.2 user credentials with CAS
April 28, 2014 8:22 AM
Answer

Tomas Polesovsky

LIFERAY STAFF

Rank: Liferay Master

Posts: 653

Join Date: February 13, 2009

Recent Posts

Please can you share the chain of URLs?

Or at least, how does the URL with the ticket look like?

Thanks.
John Brown
RE: Using Liferay 6.2 user credentials with CAS
April 28, 2014 8:49 AM
Answer

John Brown

Rank: New Member

Posts: 13

Join Date: April 21, 2014

Recent Posts

Tomáš Polešovský:
Please can you share the chain of URLs?

Or at least, how does the URL with the ticket look like?

Thanks.


Sure the URL that CAS redirects to looks like this:

1https://mymachine:8443/portal/c/portal/login?p_l_id=10184&ticket=ST-1-lLaRvua39IvDEwMMOYvI-www.mymachine.org


However when the browser lands on the portal, URL looks like this:

1https://mymachine:8443/portal/web/guest/home?p_p_id=58&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&saveLastPath=false&_58_struts_action=%2Flogin%2Flogin


This drops me again on the page with login form and sign-in link. Clicking on sign-in link keeps dropping me on this page as CAS already has an authenticated ticket.

As an FYI, reading in documentation it says to reference the CASFilter in web.xml:

the filter com.liferay.portal.servlet.filters.sso.cas.CASFilter must be referenced in web.xml.


Where do I reference this or how should the referencing be done? Do i modify the entries for InvokeFilter? or the mappings /*?

The filter is defined in liferay-web.xml.

Thanks.
John Brown
RE: Using Liferay 6.2 user credentials with CAS
April 28, 2014 9:35 AM
Answer

John Brown

Rank: New Member

Posts: 13

Join Date: April 21, 2014

Recent Posts

Tomáš Polešovský:

When I try your configuration, CAS redirects me to this URL: https://mymachine:8443//portal/*?ticket=ST-8-uof1Fkp3NJtFNPRUthFD-cas]https://mymachine:8443//portal/*?ticket=ST-8-uof1Fkp3NJtFNPRUthFD-cas

You can see it's invalid URL so portal redirects the request to a default page, without the ticket param.

So I think that's it.

The difference between specifying serviceURL and serverURL:
- with serviceURL the users will be always redirected to this fixed URL, and it should end with /c/portal/login. CASFilter sits on /c/portal/login so the serviceURL should point back to that URL
- with serverURL portal specifies serviceURL dynamically so that users can be redirected back to the original page

HTH.


Hi Tomas:

Sorry I missed this reply of yours. There are 2 places service URL is defined. In CAS and in Liferay.

In Liferay I don't define serviceURL just server URL for CAS.

In CAS server, under managing services, I defined serviceURL to be: https://mymachine:8443//portal/* for Liferay. The reason for wildcard after the portal/ is because Liferay appends to the end of the URL some query string parameters when the user lands on the page. Clicking sign-in link redirects to CAS, but with those query string parameters. If I specify serviceURL in CAS to be:

https://mymachine:8443/portal/c/portal/login

It complains about service not recognized/defined due to presence of the query string parameters at the end of the URL from which the user comes to CAS. That is why I did the portal/* to enable matching the URL dynamically on the CAS server.

HTH and clears things a bit from my setup perspective.

Below is my portal_ext.properties for CAS:

 1
 2cas.login.url=https://mymachine:8443/cas/login
 3cas.logout.url=https://mymachine:8443/cas/logout
 4cas.server.name=https://mymachine:8443
 5cas.server.url=https://mymachine:8443/cas
 6cas.service.url=
 7#cas.service.url=http://localhost:8080/c/portal/login
 8#cas.service.url=http://localhost:8080/c/portal/login
 9cas.validate.url=https://mymachine:8443/cas/validate
10cas.logout.on.session.expiration=false


As you see in Liferay I am not defining the service URL. Also in my logs I see the following from the AutoLoginFilter:

1ERROR [http--0.0.0.0-8443-2][AutoLoginFilter:257] Current URL /portal/web/guest/home?p_p_id=58&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&saveLastPath=false&_58_struts_action=%2Flogin%2Flogin generates exception: null


this is interesting, because I thought CASFilter should get invoked when returning to Liferay from CAS authentication.
Tomas Polesovsky
RE: Using Liferay 6.2 user credentials with CAS
April 28, 2014 9:43 AM
Answer

Tomas Polesovsky

LIFERAY STAFF

Rank: Liferay Master

Posts: 653

Join Date: February 13, 2009

Recent Posts

OK, this looks good.

One thing though, please can you remove BasicAutoLogin from the auto.login.hooks and have only:
1auto.login.hooks=com.liferay.portal.security.auth.CASAutoLogin

Just to isolate the root cause now. Thanks!

And also please verify CAS settings through Control Panel. Once you save the configuration from UI, the settings are saved into DB and they are never picked up from the properties file again.

----

The CAS implementation in Liferay is not complex, but we need to be sure both CASFilter and then CASAutoLogin are involved.

CASFilter is inside liferay-web.xml, which is processed by InvokerFilter.

It's possible to disable it through portal-ext.properties though - see portal.properties

Now, please can you try to add breakpoints into CASFilter:
* here, so that we know the filter is in the chain & processed
* and here to catch and debug the processing?

You can also verify it by stopping at InvokerFilter and verify that the CASFilter is in the chain for /c/portal/login.

Then hit https://mymachine:8443/portal/c/portal/login?p_l_id=10184&ticket=ST-1-lLaRvua39IvDEwMMOYvI-www.mymachine.org manually, just to be sure the CASFilter is invoked.

We need to know why CASFilter is not invoked => not processing the ticket.
John Brown
RE: Using Liferay 6.2 user credentials with CAS
April 28, 2014 9:46 AM
Answer

John Brown

Rank: New Member

Posts: 13

Join Date: April 21, 2014

Recent Posts

Thanks Tomas for the reply.

I will go ahead and start work on these items now. It will take me a bit to post back the results.

Thanks again.
John Brown
RE: Using Liferay 6.2 user credentials with CAS
April 28, 2014 2:16 PM
Answer

John Brown

Rank: New Member

Posts: 13

Join Date: April 21, 2014

Recent Posts

Tomáš Polešovský:

One thing though, please can you remove BasicAutoLogin from the auto.login.hooks and have only:
1auto.login.hooks=com.liferay.portal.security.auth.CASAutoLogin

And also please verify CAS settings through Control Panel. Once you save the configuration from UI, the settings are saved into DB and they are never picked up from the properties file again.


Verified and saved. Done.

Tomáš Polešovský:


Doing this way works and the ticket is successfully validated.

I will do the other debugging and update accordingly.
John Brown
RE: Using Liferay 6.2 user credentials with CAS
April 29, 2014 6:06 PM
Answer

John Brown

Rank: New Member

Posts: 13

Join Date: April 21, 2014

Recent Posts

Tomáš Polešovský:

Now, please can you try to add breakpoints into CASFilter:
* https://github.com/liferay/liferay-portal/blob/6.2.0-ga1/portal-impl/src/com/liferay/portal/servlet/filters/sso/cas/CASFilter.java#L62, so that we know the filter is in the chain & processed
* and https://github.com/liferay/liferay-portal/blob/6.2.0-ga1/portal-impl/src/com/liferay/portal/servlet/filters/sso/cas/CASFilter.java#L122 to catch and debug the processing?
....
We need to know why CASFilter is not invoked => not processing the ticket.


Hi Tomas:

I did debugging using the source code against the war deployed to the server. The CASFilter is getting invoked when the "Sign-in" link is clicked from the portal sign-in page. I was able to detect this by encountering the breakpoints that I put in the CASFilter.java class at the places you recommended. It successfully determined that CAS Auth was enabled for my portal i.e. return true.

I also checked the HTTPSession value after clicking the sign-in link and it was a valid session object i.e. not null.

However on the redirect back from CAS, after authentication, the filter wasn't getting invoked and i kept getting dropped back to the login page. I finally realized the mistake after running debug a few times:

The issue was:
CASFiler -> line 177, serviceURL = https://mymachine:8443//portal/c/portal/login?p_l_id=10184

here there are two // after the port number which causes the CASFilter to not get invoked. The reason the extra / was getting appended was because in my configuration I had a trailing / after the serverName i.e. https://mymachine:8443/

After I removed that forward slash from the serverName, the CASFilter did get invoked on being redirected to Liferay after authentication and I was successfully logged in emoticon

Good thing is that this exercise forced me to setup development environment for Liferay and configure remote debugging.

Thanks for your help ... didn't realize such a silly mistake caused me so much trouble. Hopefully this is the last of this emoticon

Now I am off to customizing the UI templates ... Thanks.
Tomas Polesovsky
RE: Using Liferay 6.2 user credentials with CAS
April 30, 2014 2:35 AM
Answer

Tomas Polesovsky

LIFERAY STAFF

Rank: Liferay Master

Posts: 653

Join Date: February 13, 2009

Recent Posts

Great!!!!
Klaus Bachmaier
RE: Using Liferay 6.2 user credentials with CAS
March 5, 2015 7:49 AM
Answer

Klaus Bachmaier

Rank: Regular Member

Posts: 224

Join Date: September 30, 2013

Recent Posts

John Brown:


Thanks for the reply. Based on the information you provided I was able to write a custom module to do clear text password encryption and authenticate user using the Liferay 6.2 User_ table.


Would you possibly share your Code with us? I'm having the exact same requirements, and have no idea on how to use source code of PBKDF2PasswordEncryptor.java to build an PasswordEncoder for CAS on top of that.
Shaun Nesbitt
RE: Using Liferay 6.2 user credentials with CAS
January 25, 2018 8:35 PM
Answer

Shaun Nesbitt

Rank: New Member

Posts: 1

Join Date: January 24, 2018

Recent Posts

Hi,

So I found this post and am replying to it as it's the most relevenat thing I've found on these forums.

I'm in the process of transferring users passwords from liferay to another database and backend.

I need to implement the same logic in the new backend code and have run into some difficulties.

Namely

a) The base64 encode and decode in Liferay is using it's own utility library com.liferay.portal.kernel.util.Base64 (so i have to copy this logic across instead of using whatever backend language I'm using has by default. I've tested node.js and c#)

b) When I get the equivalent getInt() as found in the link below, I'm getting back really huge numbers for the number of rounds and key size.

c) Although I can get the items needed to hash the password again, it won't give me the same hash.

Essentially I've put the basic logic into a java emulator online (using Liferays logic and base64 code). I've also written the equivalent code in node.js and I can get the same keysize, rounds, salt, and hash's from the original base64 encoded string. But when I run pbkdf2 on the password using these values, it gives me back a different hash.

Base64 password
f+MvFHDfiqoYWKQFjb83atEcmjAqLd8KFCcVfw==

Byte array
. . .
7fe32f14 70df8aaa 1858a4058dafbf6a d11c9a302a2dcfca1427157f

16 Byte array of the above
7fe32f14 70df8aaa 1858a4058dafbf6

Keysize
2145595156

Number of rounds
1893698218

Salt
1858a4058dafbf6a

Hash
d11c9a302a2dcfca1427157f


Now as far in our liferay instance we are using the default password encryption scheme PBKDF2WithHmacSHA1/160/128000

So from my understanding, when I extract the keysize and number of rounds, this should come up as 160 and 128000 respectively (based on https://github.com/liferay/liferay-portal/blob/6.2.1-ga2/portal-impl/src/com/liferay/portal/security/pwd/PBKDF2PasswordEncryptor.java#L6)

Theoretically if I have the original password, salt, number of rounds, I should be able to match the "hash's" and authenticate the password.

Any help much apprecated,

Code examples here
http://s000.tinyupload.com/index.php?file_id=82316303083721294763

Kind regards,

Shaun
Attachments: code.zip (390.2k)

Participate in the State of Liferay Community 2017. Help the community and even win some prizes!