#!/usr/bin/perl # Author: Alex Efros , 2008 # License: Public Domain # # Personal OpenID server with SRE support. # # Installation: # 1. Setup %USER, $SETUP_URL and $SERVER_SECRET below. # 2. Add this to .htaccess: # # RewriteEngine On # RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] # # 3. Add this to web page which will be your OpenID: # # use version; $VERSION = qv('0.1.0'); use warnings; use strict; use CGI; use MIME::Base64; use Net::OpenID::Server; # Configuration: setup users, their passwords, OpenID urls, filter for # allowed RP (Relying Party), and additional data sent to RP. my %USER = ( 'YOUR_LOGIN' => { pass => 'YOUR_PASSWORD', url => 'http://YOUR.DOMAIN/OPENID_PATH', trust_root => qr//, # http://openid.net/specs/openid-simple-registration-extension-1_0.html sre => { 'sreg.nickname' => 'YOUR_NICKNAME', 'sreg.fullname' => 'YOUR FULLNAME', }, }, ); # Where to redirect in case of wrong login/pass, wrong OpenID url, or # failed filter for RP: my $SETUP_URL = 'http://YOUR.DOMAIN/ERROR.html'; my $SERVER_SECRET = 'PUT_ANY_RANDOM_JUNK_HERE'; my $cgi = new CGI; my $nos = Net::OpenID::Server->new( get_args => $cgi, post_args => $cgi, get_user => \&get_user, is_identity => \&is_identity, is_trusted => \&is_trusted, server_secret => $SERVER_SECRET, setup_url => $SETUP_URL, ); my ($type, $data) = $nos->handle_page(); if ($type eq 'redirect') { my $user = $nos->get_user()->(); my $url = $nos->signed_return_url( identity => $nos->args('openid.identity'), return_to => $nos->args('openid.return_to'), assoc_handle => $nos->args('openid.assoc_handle'), trust_root => $nos->args('openid.trust_root'), additional_fields => $USER{$user}{sre}, ); print "Status: 301\r\n"; print "Location: $url\r\n\r\n"; } elsif ($type eq 'setup') { my $url = $nos->setup_url(); print "Status: 301\r\n"; print "Location: $url\r\n\r\n"; } else { print "Status: 200\r\n"; print "Content-Type: $type\r\n\r\n$data"; } exit; # Return name of logged in user or undef if user don't logged in. sub get_user { my ($login, $pass) = _get_auth(); if (!defined $login) { _require_auth(); } elsif (!exists $USER{$login}) { return; } elsif ($USER{$login}{pass} ne $pass) { _require_auth(); } else { return $login; } } # Return true if $user own $url. # $url usually come from sub is_identity { my ($user, $url) = @_; return if !defined $user; return $USER{$user}{url} eq $url; } # Returning true if the logged in $user trusts the URL given by $trust_root # to know his identity. # $trust_root is url of RP (website which is checking user's OpenID) sub is_trusted { my ($user, $trust_root, $is_identity) = @_; return if !defined $user || !$is_identity; return $trust_root =~ /$USER{$user}{trust_root}/; } # Process HTTP Basic authorization. Require this in .htaccess to work: # # RewriteEngine On # RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] # sub _get_auth { return if $ENV{HTTP_AUTHORIZATION} !~ /\ABasic\s+(\S+)\z/; return split /:/, decode_base64($1), 2; } sub _require_auth { print "Status: 401 Authorization Required\r\n"; print "WWW-Authenticate: Basic realm=\"OpenIDsrv\"\r\n\r\n"; exit; }