-
Notifications
You must be signed in to change notification settings - Fork 0
/
CasLogin.pm
206 lines (150 loc) · 6.46 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
206
# Module of Foswiki - The Free and Open Source Wiki, http://foswiki.org/
#
# Copyright (C) 2005-2006 TWiki Contributors. All Rights Reserved.
# TWiki Contributors
# are listed in the AUTHORS file in the root of this distribution.
# NOTE: Please extend that file, not this notice.
#
# Additional copyrights apply to some or all of the code in this
# file as follows:
# Copyright (C) 2005 Greg Abbas, twiki@abbas.org
# Copyright (C) 2008 Charlie Reitsma, reitsma@denison.edu
# Copyright (C) 2008 Olivier Berger, olivier.berger@it-sudparis.eu
#
# 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 2
# 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 TWiki::Client::CasLogin
This is a login manager that you can specify in the security setup section of
[[%SCRIPTURL{"configure"}%][configure]]. It provides users with a trip to
the CAS server to enter usernames and passwords.
Subclass of TWiki::Client; see that class for documentation of the
methods of this class.
=cut
package TWiki::Client::CasLogin;
use strict;
use Assert;
use TWiki::Client;
use AuthCAS;
@TWiki::Client::CasLogin::ISA = ('TWiki::Client');
sub new {
my ( $class, $session ) = @_;
my $this = bless( $class->SUPER::new($session), $class );
$session->enterContext('can_login');
return $this;
}
# Triggered on auth fail : redirects to the login script which in turn will go to CAS
sub forceAuthentication {
my $this = shift;
my $twiki = $this->{twiki};
# TWiki::Client::_trace($this, "CasLogin::forceAuthentication()");
unless ( $twiki->inContext('authenticated') ) {
my $query = $twiki->{cgiQuery};
# Redirect with passthrough so we don't lose the original query params
my $twiki = $this->{twiki};
my $topic = $twiki->{topicName};
my $web = $twiki->{webName};
# simple URL of the login script (not using loginUrl() to not provide additional args not necessary when calling redirect and not real redirect)
my $url = $twiki->getScriptUrl( 0, 'login', $web, $topic );
$query->param( -name => 'origurl', -value => $ENV{REQUEST_URI} );
# redirect to the login script by asking it to transfer to origurl one authenticated successfully
$twiki->redirect( $url, 1 );
return 1;
}
return undef;
}
# Content of a login link displayed in the page
sub loginUrl {
my $this = shift;
# TWiki::Client::_trace($this, "CasLogin::loginUrl()");
my $twiki = $this->{twiki};
my $topic = $twiki->{topicName};
my $web = $twiki->{webName};
# generate a link to the login script with origurl param to return to the same place (view normally)
return $twiki->getScriptUrl( 0, 'login', $web, $topic,
origurl => $ENV{REQUEST_URI} );
}
=pod
---++ ObjectMethod login( $query, $twiki )
If invoked from the CAS server with a valid ticket, redirects to the original
script. If the ticket is invalid, fails.
If invoked without a ticket parameter (maybe after direct access to
login script or redirect because of previous forceAuthentication, then
redirect to CAS server to login.
After successful login on CAS server, we will be invoked back, with
the ability to retrieve a username by verifying the ticket.
When invoked since foreceAuthentication is needed, we should return
afterwards to the orig_url parameter. This needs to be saved during
the trip to the CAS server, by using the 'my_orig' session variable.
=cut
sub login {
my ( $this, $query, $twikiSession ) = @_;
# TWiki::Client::_trace($this, "CasLogin::login()");
my $twiki = $this->{twiki};
my $casUrl = $TWiki::cfg{CAS}{casUrl};
my $CAFile = $TWiki::cfg{CAS}{CAFile};
my $cas = new AuthCAS(
casUrl => $casUrl,
CAFile => $CAFile
);
my $url = $query->url();
my $origurl = $query->param('origurl');
my $app_url = $TWiki::cfg{DefaultUrlHost};
my $remember = $query->param('remember');
# this is a param provided by CAS server to the app it redirects to upon succesfull login
my $ticket = $query->param('ticket');
# Eat these so there's no risk of accidental passthrough
$query->delete( 'origurl', 'ticket' );
my $cgisession = $this->{_cgisession};
$cgisession->param( 'REMEMBER', $remember ) if $cgisession;
my $error = '';
if ($ticket) {
# now we've been redirected here by the CAS server
#TWiki::Client::_trace($this, "CasLogin::login : we have a ticket : $ticket");
# retrieve the original orig_url that had been passed to the login script
$origurl = $cgisession->param('my_orig');
$cgisession->clear( ['my_orig'] );
# validate the ticket with our login URL
my $loginName = $cas->validateST( $url, $ticket );
# if validation is successfull, we have the login name
if ($loginName) {
# TWiki::Client::_trace($this, "CasLogin::login : we have a login : $loginName");
# notifiy parent class that user is logged-in
$this->userLoggedIn($loginName);
#SUCCESS our user is authenticated..
# Redirect with passthrough
# get back to where authentication was requested
$twikiSession->redirect( $origurl, 1 );
return;
}
else {
# autherwise, authentication was refused
printf STDERR "Error: %s\n", &AuthCAS::get_errors();
# would need some kind of banner in case of unsuccesfull auth (reuse templatelogin)
exit 0;
}
}
else {
# initially called by explicit login script or forceauthentication() pseudo redirect
# save previous origurl into my_orig in the session to b able to retrieve it when coming back from CAS server's login screen
$cgisession->param( 'my_orig', $origurl ) if $cgisession;
###
### Redirect the User for login at CAS server
###
# Redirect the server so that we get back to login afterwards and be able to consume the ticket parameter
my $login_url = $cas->getServerLoginURL($url);
# real redirect
print "Location: $login_url\n\n";
exit 0;
}
}
1;