lemonldap-ng/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/OpenID/Server.pm

233 lines
7.4 KiB
Perl
Raw Normal View History

## @file
# Subclass of Net::OpenID::Server that manage OpenID extensions
## @class
# Subclass of Net::OpenID::Server that manage OpenID extensions
2017-01-05 09:59:05 +01:00
package Lemonldap::NG::Portal::Lib::OpenID::Server;
2010-09-25 14:55:29 +02:00
use strict;
use base qw(Net::OpenID::Server);
use fields qw(_extensions);
2010-09-25 14:55:29 +02:00
use Net::OpenID::Server;
2010-09-26 10:16:56 +02:00
use Lemonldap::NG::Common::Regexp;
2010-09-25 14:55:29 +02:00
2010-09-28 18:26:35 +02:00
use constant DEBUG => 0;
our $VERSION = '2.0.0';
2010-09-25 14:55:29 +02:00
2017-01-05 09:59:05 +01:00
use constant OPENID2_NS => 'http://specs.openid.net/auth/2.0';
2017-02-15 07:41:50 +01:00
use constant OPENID2_ID_SELECT =>
'http://specs.openid.net/auth/2.0/identifier_select';
2010-09-28 18:26:35 +02:00
*_push_url_arg =
( $Net::OpenID::Server::VERSION >= 1.09 )
? *OpenID::util::push_url_arg
: *Net::OpenID::Server::_push_url_arg;
2010-09-28 18:26:35 +02:00
2017-01-05 12:55:46 +01:00
## @cmethod Lemonldap::NG::Portal::Lib::OpenID::Server new(hash opts)
# Call Net::OpenID::Server::new() and store extensions
# @param %opts Net::OpenID::Server options
2017-01-05 12:55:46 +01:00
# @return Lemonldap::NG::Portal::Lib::OpenID::Server new object
2010-09-25 14:55:29 +02:00
sub new {
my $class = shift;
my $self = fields::new($class);
my %opts = @_;
2010-09-25 14:55:29 +02:00
$self->$_( delete $opts{$_} ) foreach (qw(extensions));
$self->SUPER::new(%opts);
#$self->{get_args} = sub { $self->param(@_) };
}
## @method protected void extensions()
# Manage "extensions" constructor parameter
2010-09-25 14:55:29 +02:00
sub extensions {
my $self = shift;
$self->{_extensions} = shift;
}
## @method protected list _mode_checkid(string mode, boolean redirect_for_setup)
# Overload Net::OpenID::Server::_mode_checkid to call extensions hook
# @param $mode OpenID mode
# @param $redirect_for_setup indicates that user must be redirected or not for
# setup
# @return (string $type, hashref parameters)
2010-09-25 14:55:29 +02:00
sub _mode_checkid {
2017-01-05 12:55:46 +01:00
my Lemonldap::NG::Portal::Lib::OpenID::Server $self = shift;
2010-09-25 14:55:29 +02:00
my ( $mode, $redirect_for_setup ) = @_;
my $return_to = $self->args("openid.return_to");
2010-09-26 10:16:56 +02:00
return $self->_fail("no_return_to")
unless ( $return_to
2017-01-06 07:02:52 +01:00
and $return_to =~ m!^https?://! );
2010-09-25 14:55:29 +02:00
my $trust_root = $self->args("openid.trust_root") || $return_to;
$trust_root = $self->args("openid.realm")
2017-01-05 09:59:05 +01:00
if $self->args('openid.ns') eq OPENID2_NS;
2010-09-25 14:55:29 +02:00
return $self->_fail("invalid_trust_root")
2010-09-26 10:16:56 +02:00
unless ( $trust_root =~ Lemonldap::NG::Common::Regexp::HTTP_URI
2010-09-28 18:26:35 +02:00
and Net::OpenID::Server::_url_is_under( $trust_root, $return_to ) );
2010-09-25 14:55:29 +02:00
my $identity = $self->args("openid.identity");
# chop off the query string, in case our trust_root came from the return_to URL
$trust_root =~ s/\?.*//;
my $u = $self->_proxy("get_user");
2017-01-05 09:59:05 +01:00
if ( $self->args('openid.ns') eq OPENID2_NS
&& $identity eq OPENID2_ID_SELECT )
2010-09-25 14:55:29 +02:00
{
$identity = $self->_proxy( "get_identity", $u, $identity );
}
my $is_identity = $self->_proxy( "is_identity", $u, $identity );
my $is_trusted =
$self->_proxy( "is_trusted", $u, $trust_root, $is_identity );
2010-09-25 16:15:53 +02:00
my ( %extVars, %is_ext_trusted );
2010-09-25 14:55:29 +02:00
my $is_exts_trusted = 1;
if ( ref( $self->{_extensions} ) ) {
my @list = $self->args->();
2010-09-25 16:40:38 +02:00
my %extArgs;
2010-09-25 14:55:29 +02:00
foreach my $arg (@list) {
next unless ( $arg =~ /^openid\.(\w+)\.([\w\.]+)?/ );
my $tmp = $1;
my $val = $2;
2010-09-26 10:16:56 +02:00
$extArgs{$tmp}->{$val} = scalar $self->args->($arg);
2010-09-25 14:55:29 +02:00
}
2010-09-25 16:40:38 +02:00
foreach my $ns ( keys %{ $self->{_extensions} } ) {
print STDERR "Launching OpenIP $ns hook\n" if (DEBUG);
2010-09-26 10:16:56 +02:00
my $h;
( $is_ext_trusted{$ns}, $h ) = $self->{_extensions}->{$ns}->(
$u, $trust_root, $is_identity, $is_trusted,
delete( $extArgs{$ns} ) || {}
);
if ($h) {
while ( my ( $k, $v ) = each %$h ) {
print STDERR "$ns returned data: $k => $v\n" if (DEBUG);
2010-09-28 18:26:35 +02:00
$extVars{"$ns.$k"} = $v;
2010-09-26 10:16:56 +02:00
}
2010-09-25 14:55:29 +02:00
}
$is_exts_trusted &&= $is_ext_trusted{$ns};
}
2010-09-26 10:16:56 +02:00
# TODO: warn if keys(%extArgs)
2010-09-25 14:55:29 +02:00
}
# assertion path:
if ( $is_identity && $is_trusted && $is_exts_trusted ) {
2010-09-28 18:26:35 +02:00
my %sArgs = (
2010-09-25 14:55:29 +02:00
identity => $identity,
claimed_id => $self->args('openid.claimed_id'),
return_to => $return_to,
assoc_handle => $self->args("openid.assoc_handle"),
ns => $self->args('openid.ns'),
2010-09-28 18:26:35 +02:00
);
2010-09-25 14:55:29 +02:00
$sArgs{additional_fields} = \%extVars if (%extVars);
my $ret_url = $self->signed_return_url(%sArgs);
return ( "redirect", $ret_url );
}
2010-09-26 10:16:56 +02:00
# Assertion could not be made, so user requires setup (login/trust...
# something). Two ways that can happen: caller might have asked us for an
# immediate return with a setup URL (the default), or explictly said that
# we're in control of the user-agent's full window, and we can do whatever
# we want with them now.
2010-09-25 14:55:29 +02:00
# TODO: call extension sub for setup
my %setup_args = (
$self->_setup_map("trust_root"), $trust_root,
$self->_setup_map("realm"), $trust_root,
$self->_setup_map("return_to"), $return_to,
$self->_setup_map("identity"), $identity,
$self->_setup_map("assoc_handle"), $self->args("openid.assoc_handle"),
%extVars,
2010-09-25 14:55:29 +02:00
);
$setup_args{ $self->_setup_map('ns') } = $self->args('openid.ns')
if $self->args('openid.ns');
2010-09-26 10:16:56 +02:00
my $setup_url = $self->{setup_url}
or Carp::croak("No setup_url defined.");
2010-09-25 14:55:29 +02:00
_push_url_arg( \$setup_url, %setup_args );
if ( $mode eq "checkid_immediate" ) {
my $ret_url = $return_to;
2017-01-05 09:59:05 +01:00
if ( $self->args('openid.ns') eq OPENID2_NS ) {
2010-09-25 14:55:29 +02:00
_push_url_arg( \$ret_url, "openid.ns", $self->args('openid.ns') );
_push_url_arg( \$ret_url, "openid.mode", "setup_needed" );
}
else {
_push_url_arg( \$ret_url, "openid.mode", "id_res" );
_push_url_arg( \$ret_url, "openid.user_setup_url", $setup_url );
}
return ( "redirect", $ret_url );
}
else {
# the "checkid_setup" mode, where we take control of the user-agent
# and return to their return_to URL later.
if ($redirect_for_setup) {
return ( "redirect", $setup_url );
}
else {
return ( "setup", \%setup_args );
}
}
}
1;
__END__
=encoding utf8
2010-09-25 14:55:29 +02:00
=head1 NAME
2017-01-05 12:55:46 +01:00
Lemonldap::NG::Portal::Lib::OpenID::Server - Add capability to manage extensions to
2010-09-25 14:55:29 +02:00
Net::OpenID::Server
=head1 DESCRIPTION
2017-01-05 12:55:46 +01:00
Lemonldap::NG::Portal::Lib::OpenID::Server adds capability to manage extensions to
2017-01-05 09:59:05 +01:00
Net::OpenID::Server.
2010-09-25 14:55:29 +02:00
=head1 SEE ALSO
2017-01-05 09:59:05 +01:00
L<http://lemonldap-ng.org>, L<Net::OpenID::Server>
2010-09-25 14:55:29 +02:00
2017-01-05 09:59:05 +01:00
=head1 AUTHORS
2010-09-25 14:55:29 +02:00
=over
2017-01-05 09:59:05 +01:00
=item LemonLDAP::NG team L<http://lemonldap-ng.org/team>
=back
=head1 BUG REPORT
Use OW2 system to report bug or ask for features:
2017-11-11 14:06:23 +01:00
L<https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues>
=head1 DOWNLOAD
Lemonldap::NG is available at
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
2010-09-25 14:55:29 +02:00
=head1 COPYRIGHT AND LICENSE
2017-01-05 09:59:05 +01:00
See COPYING file for details.
2010-09-25 14:55:29 +02:00
This library 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, or (at your option)
any later version.
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 the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see L<http://www.gnu.org/licenses/>.
2010-09-25 14:55:29 +02:00
=cut