/
CasLogin.pm
205 lines (155 loc) · 5.36 KB
/
CasLogin.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# Module of Foswiki Collaboration Platform, http://Foswiki.org/
#
# Copyright (C) 2012 Sven Dowideit, SvenDowideit@fosiki.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version. For
# more details read LICENSE in the root of this distribution.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# As per the GPL, removal of this notice is prohibited.
=pod
---+ package Foswiki::LoginManager::CasLogin
The CasLogin class uses the CAS SSO to auto-login into Foswiki
=cut
package Foswiki::LoginManager::CasLogin;
use strict;
use Assert;
use Foswiki::LoginManager::TemplateLogin;
use Foswiki::Func;
use AuthCAS;
@Foswiki::LoginManager::CasLogin::ISA =
('Foswiki::LoginManager::TemplateLogin');
sub new {
my ( $class, $session ) = @_;
my $this = bless( $class->SUPER::new($session), $class );
$session->enterContext('can_login');
$this->{CAS} = new AuthCAS(
casUrl => $Foswiki::cfg{CAS}{casUrl},
CAFile => $Foswiki::cfg{CAS}{CAFile},
SSL_version => $Foswiki::cfg{CAS}{SSL_version}
);
return $this;
}
sub finish {
my $this = shift;
undef $this->{CAS};
$this->SUPER::finish();
return;
}
=pod
---++ ObjectMethod loadSession()
=cut
sub loadSession {
my $this = shift;
my $foswiki = $this->{session};
my $query = $foswiki->{request};
my $ticket = $query->param('ticket');
ASSERT( $this->isa('Foswiki::LoginManager::CasLogin') ) if DEBUG;
if ( $query->param('logout') && $Foswiki::cfg{CAS}{LogoutFromCAS} ) {
#can't redirect browser to logout from CAS, as the CAS server does not return to service URL
#$foswiki->redirect($this->logoutUrl(), 0);
$this->{CAS}->callCAS( $this->logoutUrl() );
}
# LoginManager::loadSession does a redirect on logout, so we have to deal with (CAS) logout before it.
my $authUser = $this->SUPER::loadSession();
my $uri = Foswiki::Func::getUrlHost() . $query->uri();
#print STDERR "hello : $authUser\n";
#print STDERR "params: ".join(', ', $query->param())."\n";
#print STDERR "uri: $uri\n";
#print STDERR "relative ".$query->url(-relative=>1);
#print STDERR "full ".$query->url(-full=>1);
#print STDERR "query ".$query->url(-query=>1);
#check returned ticket
if ( defined($ticket) ) {
$uri =~ s/[?;&]ticket=.*$//;
my $casUser = $this->{CAS}->validateST( $uri, $ticket );
if ($casUser) {
if ( $Foswiki::cfg{CAS}{AllowLoginUsingEmailAddress}
&& $casUser =~ /@/ )
{
my $login = $foswiki->{users}->findUserByEmail($casUser);
$casUser = $login->[0] if ( defined( $login->[0] ) );
}
$authUser = $casUser;
$this->userLoggedIn($authUser);
}
else {
# a bad ticket - so ignore
# its a bit difficult if its a resubmit of an old ticket to the login script :/
}
}
else {
if ( defined( $query->param('sudo') )
|| defined( $query->param('logout') ) )
{
#sudo-ing, allow template auth
$authUser = $Foswiki::cfg{DefaultUserLogin};
$this->userLoggedIn($authUser);
}
else {
if ( $foswiki->inContext('login') || $foswiki->inContext('logon') )
{
if ( !$this->forceAuthentication() ) {
my $full = $query->url( -full => 1 );
$uri =~ s/^$full//;
$uri = Foswiki::Func::getScriptUrl( undef, undef, 'view' )
. $uri;
$foswiki->redirect( $uri, 0 );
}
}
}
}
return $authUser;
}
=begin TML
---++ ObjectMethod forceAuthentication () -> $boolean
method called when authentication is required - redirects to (...|view)auth
Triggered on auth fail
=cut
sub forceAuthentication {
my $this = shift;
my $session = $this->{session};
my $query = $session->{request};
if ( !$session->inContext('authenticated')
&& !defined( $query->param('ticket') ) )
{
$session->redirect( $this->loginUrl(), 0 );
return 1;
}
return 0;
}
=begin TML
---++ ObjectMethod loginUrl () -> $loginUrl
over-ride the login url
=cut
sub loginUrl {
my $this = shift;
my $foswiki = $this->{session};
my $query = $foswiki->{request};
my $uri = Foswiki::Func::getUrlHost() . $query->uri();
#remove any urlparams, as they will be in the cachedQuery
$uri =~ s/\?.*$//;
return $this->{CAS}->getServerLoginURL(
Foswiki::urlEncode( $uri . $foswiki->cacheQuery() ) );
}
=begin TML
---++ ObjectMethod logoutUrl () -> $loginUrl
can't over-ride the logout url yet, but will try to use it.
=cut
sub logoutUrl {
my $this = shift;
my $foswiki = $this->{session};
my $query = $foswiki->{request};
my $uri = Foswiki::Func::getUrlHost() . $query->uri();
#remove any urlparams, as they will be in the cachedQuery
$uri =~ s/\?.*$//;
return $this->{CAS}->getServerLogoutURL(
Foswiki::urlEncode( $uri . $foswiki->cacheQuery() ) );
}
1;