* Make auth methods pluggable.
* Move httpauth support to a plugin. * Add an openid plugin to support logging in using OpenID.master
parent
ad01bcd8b4
commit
54cf5a62ca
|
@ -120,7 +120,7 @@ sub cgi_signin ($$) { #{{{
|
|||
error($@) if $@;
|
||||
my $form = CGI::FormBuilder->new(
|
||||
title => "signin",
|
||||
fields => [qw(do title page subpage from name password)],
|
||||
fields => [qw(do title page subpage from name password openid_url)],
|
||||
header => 1,
|
||||
charset => "utf-8",
|
||||
method => 'POST',
|
||||
|
@ -149,32 +149,56 @@ sub cgi_signin ($$) { #{{{
|
|||
$form->field(name => "from", type => "hidden");
|
||||
$form->field(name => "subpage", type => "hidden");
|
||||
$form->field(name => "password", type => "password", required => 0);
|
||||
if ($config{openid}) {
|
||||
$form->field(name => "openid_url", label => "OpenID", comment => "to log in via OpenID");
|
||||
}
|
||||
else {
|
||||
$form->field(name => "openid_url", type => "hidden");
|
||||
}
|
||||
if ($form->submitted eq "Register" || $form->submitted eq "Create Account") {
|
||||
$form->title("register");
|
||||
$form->text("");
|
||||
$form->fields(qw(do title page subpage from name password confirm_password email));
|
||||
$form->field(name => "confirm_password", type => "password");
|
||||
$form->field(name => "email", type => "text");
|
||||
$form->field(name => "openid_url", type => "hidden");
|
||||
}
|
||||
if ($q->param("do") ne "signin" && !$form->submitted) {
|
||||
$form->text("You need to log in first.");
|
||||
}
|
||||
|
||||
if ($form->submitted) {
|
||||
my $submittype=$form->submitted;
|
||||
# OpenID login uses the Login button, but validates
|
||||
# differently.
|
||||
if ($submittype eq "Login" && $config{openid} &&
|
||||
length $form->field("openid_url")) {
|
||||
$submittype="OpenID";
|
||||
|
||||
$form->field(
|
||||
name => "openid_url",
|
||||
validate => sub {
|
||||
# FIXME: ugh
|
||||
IkiWiki::Plugin::openid::validate($q, $session, $form, shift);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
# Set required fields based on how form was submitted.
|
||||
my %required=(
|
||||
"Login" => [qw(name password)],
|
||||
"Register" => [],
|
||||
"Create Account" => [qw(name password confirm_password email)],
|
||||
"Mail Password" => [qw(name)],
|
||||
"OpenID" => [qw(openid_url)],
|
||||
);
|
||||
foreach my $opt (@{$required{$form->submitted}}) {
|
||||
foreach my $opt (@{$required{$submittype}}) {
|
||||
$form->field(name => $opt, required => 1);
|
||||
}
|
||||
|
||||
# Validate password differently depending on how
|
||||
# form was submitted.
|
||||
if ($form->submitted eq 'Login') {
|
||||
if ($submittype eq 'Login') {
|
||||
$form->field(
|
||||
name => "password",
|
||||
validate => sub {
|
||||
|
@ -184,13 +208,13 @@ sub cgi_signin ($$) { #{{{
|
|||
);
|
||||
$form->field(name => "name", validate => '/^\w+$/');
|
||||
}
|
||||
else {
|
||||
elsif ($submittype ne 'OpenID') {
|
||||
$form->field(name => "password", validate => 'VALUE');
|
||||
}
|
||||
# And make sure the entered name exists when logging
|
||||
# in or sending email, and does not when registering.
|
||||
if ($form->submitted eq 'Create Account' ||
|
||||
$form->submitted eq 'Register') {
|
||||
if ($submittype eq 'Create Account' ||
|
||||
$submittype eq 'Register') {
|
||||
$form->field(
|
||||
name => "name",
|
||||
validate => sub {
|
||||
|
@ -201,7 +225,7 @@ sub cgi_signin ($$) { #{{{
|
|||
},
|
||||
);
|
||||
}
|
||||
else {
|
||||
elsif ($submittype ne 'OpenID') {
|
||||
$form->field(
|
||||
name => "name",
|
||||
validate => sub {
|
||||
|
@ -229,8 +253,8 @@ sub cgi_signin ($$) { #{{{
|
|||
do => $form->field("do"),
|
||||
page => $form->field("page"),
|
||||
title => $form->field("title"),
|
||||
subpage => $form->field("subpage"),
|
||||
from => $form->field("from"),
|
||||
subpage => $form->field("subpage"),
|
||||
));
|
||||
}
|
||||
else {
|
||||
|
@ -680,11 +704,30 @@ sub cgi () { #{{{
|
|||
{ FileName => "$config{wikistatedir}/sessions.db" });
|
||||
umask($oldmask);
|
||||
|
||||
# Auth hooks can sign a user in.
|
||||
if ($do ne 'signin' && ! defined $session->param("name")) {
|
||||
run_hooks(auth => sub {
|
||||
shift->($q, $session)
|
||||
});
|
||||
if (defined $session->param("name")) {
|
||||
# Make sure whatever user was authed is in the
|
||||
# userinfo db.
|
||||
if (! userinfo_get($session->param("name"), "regdate")) {
|
||||
userinfo_setall($session->param("name"), {
|
||||
email => "",
|
||||
password => "",
|
||||
regdate => time,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Everything below this point needs the user to be signed in.
|
||||
if (((! $config{anonok} || $do eq 'prefs') &&
|
||||
(! $config{httpauth}) &&
|
||||
(! defined $session->param("name") ||
|
||||
! userinfo_get($session->param("name"), "regdate"))) || $do eq 'signin') {
|
||||
! userinfo_get($session->param("name"), "regdate")))
|
||||
|| $do eq 'signin') {
|
||||
cgi_signin($q, $session);
|
||||
|
||||
# Force session flush with safe umask.
|
||||
|
@ -695,22 +738,6 @@ sub cgi () { #{{{
|
|||
return;
|
||||
}
|
||||
|
||||
if ($config{httpauth} && (! defined $session->param("name"))) {
|
||||
if (! defined $q->remote_user()) {
|
||||
error("Could not determine authenticated username.");
|
||||
}
|
||||
else {
|
||||
$session->param("name", $q->remote_user());
|
||||
if (! userinfo_get($session->param("name"), "regdate")) {
|
||||
userinfo_setall($session->param("name"), {
|
||||
email => "",
|
||||
password => "",
|
||||
regdate=>time,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defined $session->param("name") && userinfo_get($session->param("name"), "banned")) {
|
||||
print $q->header(-status => "403 Forbidden");
|
||||
$session->delete();
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/perl
|
||||
# HTTP basic auth plugin.
|
||||
package IkiWiki::Plugin::httpauth;
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use IkiWiki;
|
||||
|
||||
sub import { #{{{
|
||||
hook(type => "auth", id => "skeleton", call => \&auth);
|
||||
} # }}}
|
||||
|
||||
sub auth ($$) { #{{{
|
||||
my $cgi=shift;
|
||||
my $session=shift;
|
||||
|
||||
if (defined $cgi->remote_user()) {
|
||||
$session->param("name", $cgi->remote_user());
|
||||
}
|
||||
} #}}}
|
||||
|
||||
1
|
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/perl
|
||||
# OpenID support.
|
||||
package IkiWiki::Plugin::openid;
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use IkiWiki;
|
||||
|
||||
sub import { #{{{
|
||||
hook(type => "checkconfig", id => "smiley", call => \&checkconfig);
|
||||
hook(type => "auth", id => "skeleton", call => \&auth);
|
||||
} # }}}
|
||||
|
||||
sub checkconfig () { #{{{
|
||||
# Currently part of the OpenID code is in CGI.pm, and is enabled by
|
||||
# this setting.
|
||||
# TODO: modularise it all out into this plugin..
|
||||
$config{openid}=1;
|
||||
} #}}}
|
||||
|
||||
sub auth ($$) { #{{{
|
||||
my $q=shift;
|
||||
my $session=shift;
|
||||
|
||||
if (defined $q->param('openid.mode')) {
|
||||
my $csr=getobj($q, $session);
|
||||
|
||||
if (my $setup_url = $csr->user_setup_url) {
|
||||
IkiWiki::redirect($q, $setup_url);
|
||||
}
|
||||
elsif ($csr->user_cancel) {
|
||||
IkiWiki::redirect($q, $config{url});
|
||||
}
|
||||
elsif (my $vident = $csr->verified_identity) {
|
||||
$session->param(name => $vident->url);
|
||||
}
|
||||
}
|
||||
} #}}}
|
||||
|
||||
sub validate ($$$$) { #{{{
|
||||
my $q=shift;
|
||||
my $session=shift;
|
||||
my $form=shift;
|
||||
my $openid_url=shift;
|
||||
|
||||
my $csr=getobj($q, $session);
|
||||
|
||||
my $claimed_identity = $csr->claimed_identity($openid_url);
|
||||
if (! $claimed_identity) {
|
||||
# Put the error in the form and fail validation.
|
||||
$form->field(name => "openid_url", comment => $csr->err);
|
||||
return 0;
|
||||
}
|
||||
my $check_url = $claimed_identity->check_url(
|
||||
return_to => IkiWiki::cgiurl(
|
||||
do => $form->field("do"),
|
||||
page => $form->field("page"),
|
||||
title => $form->field("title"),
|
||||
from => $form->field("from"),
|
||||
subpage => $form->field("subpage")
|
||||
),
|
||||
trust_root => $config{cgiurl},
|
||||
delayed_return => 1,
|
||||
);
|
||||
# Redirect the user to the OpenID server, which will
|
||||
# eventually bounce them back to auth() above.
|
||||
IkiWiki::redirect($q, $check_url);
|
||||
exit 0;
|
||||
} #}}}
|
||||
|
||||
sub getobj ($$) { #{{{
|
||||
my $q=shift;
|
||||
my $session=shift;
|
||||
|
||||
eval q{use Net::OpenID::Consumer};
|
||||
error($@) if $@;
|
||||
|
||||
my $ua;
|
||||
eval q{use LWPx::ParanoidAgent};
|
||||
if (! $@) {
|
||||
$ua=LWPx::ParanoidAgent->new;
|
||||
}
|
||||
else {
|
||||
$ua=LWP::UserAgent->new;
|
||||
}
|
||||
|
||||
# Store the secret in the session.
|
||||
my $secret=$session->param("openid_secret");
|
||||
if (! defined $secret) {
|
||||
$secret=$session->param(openid_secret => time);
|
||||
}
|
||||
|
||||
return Net::OpenID::Consumer->new(
|
||||
ua => $ua,
|
||||
args => $q,
|
||||
consumer_secret => $secret,
|
||||
required_root => $config{cgiurl},
|
||||
);
|
||||
} #}}}
|
||||
|
||||
1
|
|
@ -20,6 +20,7 @@ sub import { #{{{
|
|||
hook(type => "delete", id => "skeleton", call => \&delete);
|
||||
hook(type => "change", id => "skeleton", call => \&change);
|
||||
hook(type => "cgi", id => "skeleton", call => \&cgi);
|
||||
hook(type => "auth", id => "skeleton", call => \&auth);
|
||||
hook(type => "savestate", id => "savestate", call => \&savestate);
|
||||
} # }}}
|
||||
|
||||
|
@ -95,6 +96,13 @@ sub cgi ($) { #{{{
|
|||
debug("skeleton plugin running in cgi");
|
||||
} #}}}
|
||||
|
||||
sub auth ($$) { #{{{
|
||||
my $cgi=shift;
|
||||
my $session=shift;
|
||||
|
||||
debug("skeleton plugin running in auth");
|
||||
} #}}}
|
||||
|
||||
sub savestate () { #{{{
|
||||
debug("skeleton plugin running in savestate");
|
||||
} #}}}
|
||||
|
|
|
@ -205,3 +205,11 @@ li.L7 {
|
|||
li.L8 {
|
||||
list-style: upper-alpha;
|
||||
}
|
||||
|
||||
input#openid_url {
|
||||
background: url(http://openid.net/login-bg.gif) no-repeat;
|
||||
background-color: #fff;
|
||||
background-position: 0 50%;
|
||||
color: #000;
|
||||
padding-left: 18px;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
ikiwiki (1.34) UNRELEASED; urgency=low
|
||||
|
||||
* Make auth methods pluggable.
|
||||
* Move httpauth support to a plugin.
|
||||
* Add an openid plugin to support logging in using OpenID.
|
||||
|
||||
-- Joey Hess <joeyh@debian.org> Sun, 19 Nov 2006 16:40:26 -0500
|
||||
|
||||
ikiwiki (1.33) unstable; urgency=low
|
||||
|
||||
* Fix issue with aggregate plugin updating expired pages.
|
||||
|
|
|
@ -11,7 +11,7 @@ Package: ikiwiki
|
|||
Architecture: all
|
||||
Depends: ${perl:Depends}, libxml-simple-perl, markdown, libtimedate-perl, libhtml-template-perl, libhtml-scrubber-perl, libcgi-formbuilder-perl (>= 3.02.02), libtime-duration-perl, libcgi-session-perl (>= 4.14-1), libmail-sendmail-perl, gcc | c-compiler, libc6-dev | libc-dev, libhtml-parser-perl, liburi-perl
|
||||
Recommends: subversion | git-core | tla | mercurial, hyperestraier
|
||||
Suggests: viewcvs, librpc-xml-perl, libtext-wikiformat-perl, python-docutils, polygen, tidy, libxml-feed-perl, libmailtools-perl, perlmagick, libfile-mimeinfo-perl
|
||||
Suggests: viewcvs, librpc-xml-perl, libtext-wikiformat-perl, python-docutils, polygen, tidy, libxml-feed-perl, libmailtools-perl, perlmagick, libfile-mimeinfo-perl, libnet-openid-consumer-perl, libcrypt-ssleay-perl
|
||||
Description: a wiki compiler
|
||||
ikiwiki converts a directory full of wiki pages into html pages suitable
|
||||
for publishing on a website. Unlike many wikis, ikiwiki does not have its
|
||||
|
|
|
@ -129,7 +129,11 @@ and can be enabled by enabling [[CGI]].
|
|||
### User registration
|
||||
|
||||
Can optionally be configured to allow only registered users to post
|
||||
pages; online user registration form, etc.
|
||||
pages.
|
||||
|
||||
User registration can be done using a web form, or ikiwiki can be
|
||||
configured to accept users authenticated with OpenID, or HTTP basic
|
||||
authentication, or other methods implemented via plugins.
|
||||
|
||||
### Discussion pages
|
||||
|
||||
|
|
|
@ -88,8 +88,6 @@ use IkiWiki::Setup::Standard {
|
|||
#locale => 'en_US.UTF-8',
|
||||
# Only send cookies over SSL connections.
|
||||
#sslcookie => 1,
|
||||
# Use HTTP Authentication instead of Ikiwiki's.
|
||||
#httpauth => 1,
|
||||
# Logging settings:
|
||||
verbose => 0,
|
||||
syslog => 0,
|
||||
|
@ -97,7 +95,7 @@ use IkiWiki::Setup::Standard {
|
|||
# To add plugins, list them here.
|
||||
#add_plugins => [qw{meta tag pagecount brokenlinks search smiley
|
||||
# wikitext camelcase pagestats htmltidy fortune
|
||||
# sidebar map rst toc linkmap}],
|
||||
# sidebar map rst toc linkmap openid}],
|
||||
# If you want to disable any of the default plugins, list them here.
|
||||
#disable_plugins => [qw{inline htmlscrubber}],
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
Most of ikiwiki's [[features]] are implemented as plugins. Beyond the
|
||||
[[type/core]] features, there are plugins to [[type/format]] text,
|
||||
use [[type/tags]], show [[type/meta]] information, do other [[type/useful]]
|
||||
stuff, add [[type/chrome]] to the wiki, or just have [[type/fun]].
|
||||
use [[type/tags]], show [[type/meta]] information, add [[type/auth]]
|
||||
methods, do other [[type/useful]] stuff, add [[type/chrome]] to the
|
||||
wiki, or just have [[type/fun]].
|
||||
|
||||
There's documentation if you want to [[write]] your own plugins, or you can
|
||||
install and use plugins contributed by others.
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
[[template id=plugin name=httpauth included=1 author="Alec Berryman"]]
|
||||
[[tag type/auth]]
|
||||
|
||||
This plugin allows HTTP basic authentication to be used to log into the
|
||||
wiki. To use the plugin, your web server should be set up to perform HTTP
|
||||
basic authentiation. The authenticated user will be automatically signed
|
||||
into the wiki.
|
||||
|
||||
This plugin is included in ikiwiki, but is not enabled by default.
|
|
@ -12,7 +12,6 @@ Hint: To limit the map to displaying pages less than a certian level deep,
|
|||
use a [[PageSpec]] like this: `pages="* and !*/*/*"`
|
||||
|
||||
This plugin is included in ikiwiki, but is not enabled by default.
|
||||
It was contributed by Alessandro Dotti Contra.
|
||||
|
||||
If this plugin is enabled, here is a page map for the plugins section
|
||||
of this wiki:
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
[[template id=plugin name=openid included=1 author="[[Joey]]"]]
|
||||
[[tag type/auth]]
|
||||
|
||||
This plugin allows users to use their [OpenID](http://openid.net/) to log
|
||||
into the wiki.
|
||||
|
||||
The plugin needs the `Net::OpenID::Consumer` perl module. The
|
||||
`LWPx::ParanoidAgent` perl module is used if available, for added
|
||||
security. Finally, the `Crypt::SSLeay` perl module is needed to support
|
||||
users entering "https" OpenID urls.
|
||||
|
||||
This plugin is included in ikiwiki, but is not enabled by default.
|
|
@ -0,0 +1,2 @@
|
|||
These plugins add different authentication methods for logging in to the
|
||||
wiki.
|
|
@ -175,6 +175,19 @@ called in turn, and passed a CGI object. The hook should examine the
|
|||
parameters, and if it will handle this CGI request, output a page and
|
||||
terminate the program.
|
||||
|
||||
### cgi
|
||||
|
||||
hook(type => "cgi", id => "foo", call => \&auth);
|
||||
|
||||
This hook can be used to implement a different authentication method than
|
||||
the standard web form. When a user needs to be authenticated, each registered
|
||||
auth hook is called in turn, and passed a CGI object and a session object.
|
||||
|
||||
If the hook is able to authenticate the user, it should set the session
|
||||
object's "name" parameter to the authenticated user's name. Note that
|
||||
if the name is set to the name of a user who is not registered,
|
||||
a basic registration of the user will be automatically performed.
|
||||
|
||||
### savestate
|
||||
|
||||
hook(type => "savestate", id => "foo", call => \&savestate);
|
||||
|
|
Loading…
Reference in New Issue