Skip to content

Commit

Permalink
CAS authentication module, associated conf file and changes to Login.…
Browse files Browse the repository at this point in the history
…pm and Logout.pm
  • Loading branch information
paulvojta authored and aubreyja committed Dec 9, 2012
1 parent d42b671 commit 0010fb8
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 0 deletions.
36 changes: 36 additions & 0 deletions conf/authen_CAS.conf.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!perl

########################################################################################
# authen_CAS.conf.dist
# Copy this file to authen_CAS.conf. Then configure it to match your server's CAS configuration.
# Then to activate add the following line to localOverrides.conf:
# include("conf/authen_CAS.conf")
########################################################################################

# Set CAS as the authentication module to use.
$authen{user_module} = {
"*" => "WeBWorK::Authen::CAS",
};

$authen{cas_options} = {
# Options to pass to the AuthCAS module.
# Note that this is (plain) AuthCAS, not Apache::AuthCAS
# or Apache2::AuthCAS.
# You need at least casUrl and CAFile; others can be set as well.
AuthCAS_opts => {
# URL of CAS server. Edit the host below.
casURL => '', #e.g. 'https://auth.berkeley.edu/cas',

# Path of certificate file for CAS server.
CAFile => '', #e.g. '/etc/pki/tls/certs/ca-bundle.crt',
},
# There are no options specific to CAS at this time. If there were,
# though, they would go here.

# For debugging:
#su_from => '8315',
su_to => '999999',
};


1; #final line of the file to reassure perl that it was read properly.
136 changes: 136 additions & 0 deletions lib/WeBWorK/Authen/CAS.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
################################################################################
# WeBWorK Online Homework Delivery System
# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
# $CVSHeader: $
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of either: (a) the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version, or (b) the "Artistic License" which comes with this package.
#
# 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. See either the GNU General Public License or the
# Artistic License for more details.
################################################################################

package WeBWorK::Authen::CAS;
use base qw/WeBWorK::Authen/;

use strict;
use warnings;
use AuthCAS;

use WeBWorK::Debug;
#$WeBWorK::Debug::Enabled = 1;
#$WeBWorK::Debug::Logfile = "/opt/webwork/webwork2/logs/cas-debug.log";
#$WeBWorK::Debug::AllowSubroutineOutput = "get_credentials";

sub get_credentials {
my ($self) = @_;
my $r = $self->{r};
my $ce = $r->ce;

# if we come in with a user_id, then we've already authenticated
# through the CAS. So just check the provided user and session key.
$self->{external_auth} = 1;
if (defined $r->param('key') && defined $r->param('user')) {
# These lines were copied from the superclass get_credentials.
$self->{session_key} = $r->param('key');
$self->{user_id} = $r->param('user');
$self->{login_type} = 'normal';
$self->{credential_source} = 'params';
debug("CAS params user '", $self->{user_id},
"' key '", $self->{session_key}, "'");
# Check session key and user here. Otherwise, a student can
# determine the enrollment status of any other student if
# they know the userid (which is public information at
# Berkeley). That would be a privacy violation.
my $Key = $r->db->getKey($self->{user_id});
unless (defined $Key && $Key->key eq $self->{session_key}) {
debug('undefined or invalid session key: $Key->key = ',
defined $Key ? $Key->key : undef, ', user value = ',
$self->{session_key});
$self->{error} = "Invalid session key";
return 0;
}
return 1;
#debug("falling back to superclass get_credentials");
#return $self->SUPER::get_credentials( @_ );
} else {
#my $cas_url = $ce->{authen}{cas_options}{url};
#my $cas_certs = $ce->{authen}{cas_options}{certs};
#my $cas = new AuthCAS(casUrl => $cas_url,
# CAFile => $cas_certs);
my $cas = new AuthCAS(
%{ $ce->{authen}{cas_options}{AuthCAS_opts} });

my $service = $ce->{apache_root_url} . $r->location . '/'
. $r->urlpath->arg('courseID') . '/';
debug("service = $service");
my $ticket = $r->param('ticket') || 0;
unless ($ticket) {
# there's no ticket, so redirect to get one
#
my $go_to = $cas->getServerLoginURL($service);
#$go_to = 'http://math.berkeley.edu/'; # for debugging
debug("no ticket. Redirecting to $go_to");
$self->{redirect} = $go_to;
return 0;
}
# We have a ticket. Validate it.
my $user_id = $cas->validateST($service, $ticket);
if (!defined $user_id) {
my $err = $cas->get_errors();
$err = '<undef>' unless defined $err;
$self->{error} = $err;
debug("ticket error $err");
#return $self->SUPER::get_credentials( @_ );
return 0;
} else {
debug("ticket is good, user is $user_id");
if (defined $ce->{authen}{cas_options}{su_from}
&& $user_id eq $ce->{authen}{cas_options}{su_from}
&& defined $ce->{authen}{cas_options}{su_to}) {
$user_id = $ce->{authen}{cas_options}{su_to};
debug("hackily changing user to $user_id");
}
$self->{'user_id'} = $user_id;
$self->{r}->param('user', $user_id);
$self->{session_key} = undef;
$self->{password} = "not\tvalid";
$self->{login_type} = 'normal';
$self->{credential_source} = 'cas';
return 1;
}
}
}

# There's no need to provide site_checkPassword, since it's only accessed
# from checkPassword, which we're replacing.

sub checkPassword {
my ( $self, $userID, $clearTextPassword ) = @_;
# if we got here, we know we've already successfully authenticated
# against the CAS
return 1;
}

# Handle logout by redirecting to the relevant CAS url.

sub logout_user {
my ($self) = @_;

my $ce = $self->{r}->ce;

# Using AuthCAS::getServerLogoutURL($service) would be overkill,
# and (more important) it would send us back here after logging out,
# so we'd end up back at the CAS login screen.

my $go_to = $ce->{authen}{cas_options}{AuthCAS_opts}{casUrl}
. '/logout';
debug("logging out. Redirecting to $go_to");
$self->{redirect} = $go_to;
}

1;
10 changes: 10 additions & 0 deletions lib/WeBWorK/ContentGenerator/Login.pm
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,16 @@ sub links {
return( @return);
}

sub pre_header_initialize {
my ($self) = @_;
my $authen = $self->r->authen;

if ( defined($authen->{redirect}) && $authen->{redirect} ) {
$self->reply_with_redirect($authen->{redirect});
}
}


sub body {
my ($self) = @_;
my $r = $self->r;
Expand Down
3 changes: 3 additions & 0 deletions lib/WeBWorK/ContentGenerator/Logout.pm
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ sub pre_header_initialize {
}
$self->{keyError} = $keyError;

# Do any special processing needed by external authentication
$authen->logout_user() if $authen->can('logout_user');

# if we have an authen redirect, all of those errors may be
# moot, but I think that's unavoidable (-glarose)
if ( defined($authen->{redirect}) && $authen->{redirect} ) {
Expand Down

0 comments on commit 0010fb8

Please sign in to comment.