Merge branch 'master' into tova
[ikiwiki.git] / doc / todo / cas_authentication.mdwn
1 [[!tag patch wishlist]]
2
3 ikiwiki should support [Central Authentication
4 Service](http://www.ja-sig.org/products/cas/) authentication in order to use
5 this <acronym title='Single Sign On'>SSO</acronym> mechanism very popular in
6 universities web services.
7
8 I have already written a first draft plugin supporting that authentication
9 mechanism. It works for me with my university CAS service. I did not try it
10 with other CAS server but it do not see any reason why it should not work.
11
12 What is the best way to submit it to you (just in case it can help my patch
13 follows) ?
14
15 --[[/users/bbb]]
16
17 ------------------------------------------------------------------------------
18     diff --git a/IkiWiki/Plugin/cas.pm b/IkiWiki/Plugin/cas.pm
19     new file mode 100644
20     index 0000000..ea189df
21     --- /dev/null
22     +++ b/IkiWiki/Plugin/cas.pm
23     @@ -0,0 +1,94 @@
24     +#!/usr/bin/perl
25     +# JaSIG CAS support by Bruno Beaufils <bruno@boulgour.com>
26     +package IkiWiki::Plugin::cas;
27     +
28     +use warnings;
29     +use strict;
30     +use IkiWiki 2.00;
31     +use AuthCAS;                  # http://search.cpan.org/~osalaun/AuthCAS-1.3.1/
32     +
33     +sub import { #{{{
34     +    hook(type => "getopt", id => "cas", call => \&getopt);
35     +    hook(type => "auth", id => "cas", call => \&auth);
36     +    hook(type => "formbuilder_setup", id => "cas", call => \&formbuilder_setup);
37     +} # }}}
38     +
39     +# FIXME: We should check_config to ensure that :
40     +# * cas_url and ca_file are present
41     +# * no other auth plugin are present (at least passwordauth and openid)
42     +
43     +sub getopt () { #{{{
44     +    eval q{use Getopt::Long};
45     +    error($@) if $@;
46     +    Getopt::Long::Configure('pass_through');
47     +    GetOptions("cas_url=s" => \$config{cas_url});
48     +    GetOptions("ca_file=s" => \$config{ca_file});
49     +} #}}}
50     +
51     +sub auth ($$) { #{{{
52     +    my $q=shift;
53     +    my $session=shift;
54     +
55     +    my $cas = new AuthCAS(casUrl => $config{'cas'}{'cas_url'},
56     +                          CAFile => $config{'cas'}{'ca_file'});
57     +
58     +    my $service = $config{'cgiurl'};
59     +    my $ticket = $q->param('ticket');
60     +
61     +    unless (defined($ticket)) {
62     +        $service .= "?$ENV{QUERY_STRING}";
63     +        my $login_url = $cas->getServerLoginURL($service);
64     +        debug("CAS: asking a Service Ticket for service $service");
65     +        IkiWiki::redirect($q, $login_url);
66     +        exit 0;
67     +    } else {
68     +        $service = $service . "?$ENV{QUERY_STRING}";
69     +        $service =~ s/\&ticket=$ticket//;
70     +        my $user = $cas->validateST($service, $ticket);
71     +        if (defined $user) {
72     +            debug("CAS: validating a Service Ticket ($ticket) for service $service");
73     +            $session->param(name=>$user);
74     +            $session->param(CASservice=>$service);
75     +            IkiWiki::cgi_savesession($session);
76     +        } else {
77     +            error("CAS failure: ".&AuthCAS::get_errors());
78     +        }
79     +    }
80     +} #}}}
81     +
82     +# I use formbuilder_setup and not formbuilder type in order to bypass the
83     +# Logout processing done in IkiWiki::CGI::cgi_prefs()
84     +sub formbuilder_setup (@) { #{{{
85     +    my %params=@_;
86     +    
87     +    my $form=$params{form};
88     +    my $session=$params{session};
89     +    my $cgi=$params{cgi};
90     +    my $buttons=$params{buttons};
91     +
92     +    my $cas = new AuthCAS(casUrl => $config{'cas'}{'cas_url'},
93     +                          CAFile => $config{'cas'}{'ca_file'});
94     +
95     +    if ($form->title eq "preferences") {
96     +        # Show the login
97     +        if (! defined $form->field(name => "name")) {
98     +            $form->field(name => "CAS ID",
99     +                         disabled => 1,
100     +                         value => $session->param("name"), 
101     +                         size => 50,
102     +                         force => 1,
103     +                         fieldset => "login");
104     +        }
105     +        
106     +        # Force a logout if asked
107     +        if ($form->submitted && $form->submitted eq 'Logout')
108     +        {
109     +            debug("CAS: asking to remove the Ticket Grant Cookie");
110     +            IkiWiki::redirect($cgi, $cas->getServerLogoutURL($config{'url'}));
111     +            $session->delete();
112     +            exit 0;
113     +        }
114     +    }
115     +}
116     +
117     +1
118     diff --git a/doc/plugins/cas.mdwn b/doc/plugins/cas.mdwn
119     new file mode 100644
120     index 0000000..2f2f53e
121     --- /dev/null
122     +++ b/doc/plugins/cas.mdwn
123     @@ -0,0 +1,18 @@
124     +[[ template id=plugin name=cas core=0 author="[[bbb]]"]]
125     +[[ tag type/auth]]
126     +
127     +This plugin allows users to use authentication offered by a
128     +[JaSIG](http://www.ja-sig.org) [<acronym title='Central Authentication
129     +Service'>CAS</acronym>](http://www.ja-sig.org/products/cas/) server to log
130     +into the wiki.
131     +
132     +The plugin needs the [[!cpan AuthCAS-1.3.1]] perl module.
133     +
134     +This plugin has two mandatory configuration option. You **must** set `--cas_url`
135     +to the url of a server offering CAS 2.0 authentication. You must also set the
136     +`--ca_file` to an absolute path to the file containing CA certificates used by
137     +the server (generally, aka under Debian, fixing that value to
138     +`/etc/ssl/certs/ca-certificates.crt` is sufficient).
139     +
140     +This plugin is not enabled by default. It can not be used with other
141     +authentication plugin, such as [[passwordauth]] or [[openid]].
142
143 ------------------------------------------------------------------------------