Redmine is a project management web application. It’s written in Ruby using the Rails framework.
There is a CAS client available written in Ruby: RubyCAS-Client.
So, I’ve made some modifications on Redmine code in order to use the CAS service to authenticate Redmine users. Moreover, user information is updated from a LDAP every time the user login in the Redmine website (using Net::LDAP). And the fields to modify this data will be disabled on My account page.
Summarizing, I’ve uploaded a patch which provides this specific behaviour (this patch is done against the revision 2824 of Redmine). I know that it’s hardcoded, but it could be a base for further steps and I hope that it could be useful for someone else (or even for me in the future ;-) ). In the next paragraphs I’ll go into more technical details.
Once you’ve installed the last version of Redmine (I’m using trunk revision 2824), you’ll need to install RubyCAS-Client (again from trunk because of some functions are not available at last stable 2.0.1):
./script/plugin install http://rubycas-client.googlecode.com/svn/trunk/rubycas-client
First of all, you should add the basic configuration for CAS at
CASClient::Frameworks::Rails::Filter.configure( :cas_base_url => 'https://localhost/cas/' )
Moreover, it’s needed to add the next line to the class
Then, in order to change the login behaviour you should modify the
login action of the
account controller. Change the method
require 'casclient' require 'casclient/frameworks/rails/filter' def login if session[:cas_user].empty? # Logout user self.logged_user = nil CASClient::Frameworks::Rails::Filter::redirect_to_cas_for_authentication(self) else cas_authentication(session[:cas_user]) end end
Now, it’s necessary to add the new method
cas_authentication, which register an user if it’s the first time that makes login on the Redmine website:
def cas_authentication(cas_user) user = User.find_or_initialize_by_login(cas_user) if user.new_record? # Create on the fly user.login = cas_user user = update_user_data_from_ldap(user) user.status = User::STATUS_REGISTERED register_automatically(user) do onthefly_creation_failed(user) end else if user.active? user = update_user_data_from_ldap(user, true) successful_authentication(user) else account_pending end end end
update_user_data_from_ldap gets the user data from LDAP, and update user data on database if needed:
def update_user_data_from_ldap (user, save = false) ldap = Net::LDAP::new ldap.host = 'localhost' ldap.port = '389' treebase = 'dc=example,dc=com' filter = Net::LDAP::Filter.eq('uid', user.login) entry = ldap.search( :base => treebase, :filter => filter, :attributes => ['cn', 'sn', 'mail'] ).first user.firstname = entry.cn.first user.lastname = entry.sn.first user.mail = entry.mail.first user.save if save return user end
Following, you should modify the logout behaviour, changing the method
logout of the same controller:
def logout cookies.delete :autologin Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) if User.current.logged? self.logged_user = nil CASClient::Frameworks::Rails::Filter::logout(self) end
The last step is to disable the fields gotten from LDAP at My account page. Modify the
app/views/my/account.rhtml file adding
:disabled => true option:
<p><%= f.text_field :firstname, :required => true, :disabled => true %></p> <p><%= f.text_field :lastname, :required => true, :disabled => true %></p> <p><%= f.text_field :mail, :required => true, :disabled => true %></p>
Finally, you can get all this stuff from a single patch. Any comment or suggestion are, as usual, welcomed.
On 09/08/14 10:54, Neoh59 wrote:
I use Redmine 0.8.4 (latest stable release)
CASifying Redmine will be great. But why do you write a function to connect to LDAP although LDAP configuration can be made in the Redmine interface ?
I’m dreaming of a SSO plugin for Redmine. But I’m not be able to do it. :-(
Do you ? ;-)
PS: Sorry for my poor english, I’m french.
On 09/08/14 07:22, Manuel Rego Casasnovas wrote:
I’m just using LDAP for a specific requirement. I need that the first time the user login Redmine, the information from LDAP about this use was stored on the database (morover every time the user login again I should update the data if that has changed on LDAP). Anyway, I could have a look at LDAP plugin, maybe it fulfils my requirements ;-)
About the SSO plugin, maybe this patch could be useful as example for that plugin. But for the moment it’s enough for my needs.
On 09/11/25 12:15, rubiojr wrote:
Awesome mate. Your patch saved us hours of work!!!
On 10/04/15 16:44, lnomine wrote:
Do you plan to use the 0.9.x version of Redmine? I’d love to see your patch working for the current version.
On 10/04/15 16:52, Manuel Rego Casasnovas wrote:
Maybe in the future we could update to this version, but not in the short term. Sorry.
I’ll keep you informed if we update the patch.