| 1 | package OpenID2Server::App; |
|---|
| 2 | |
|---|
| 3 | use strict; |
|---|
| 4 | |
|---|
| 5 | use Net::OpenID::Server; |
|---|
| 6 | use MT::Util qw( perl_sha1_digest_hex ); |
|---|
| 7 | use Data::Dumper; |
|---|
| 8 | |
|---|
| 9 | use constant IDENTIIFER_SELECT => 'http://specs.openid.net/auth/2.0/identifier_select'; |
|---|
| 10 | |
|---|
| 11 | sub llog { |
|---|
| 12 | open my $fh, '>>', 'c:\\temp\\hoge\\hoge.txt'; |
|---|
| 13 | print $fh '"'.join('","', @_) . '"'; |
|---|
| 14 | close $fh; |
|---|
| 15 | } |
|---|
| 16 | |
|---|
| 17 | sub openid_xrds { |
|---|
| 18 | my $app = shift; |
|---|
| 19 | my $plugin = $app->component('openid2-server'); |
|---|
| 20 | # return XRDS-YADIS document location |
|---|
| 21 | if ( 'GET' eq $app->request_method ) { |
|---|
| 22 | $app->response_content_type('application/xrds+xml'); |
|---|
| 23 | if ( 'openid_xrds' eq $app->mode ) { |
|---|
| 24 | my $param = { |
|---|
| 25 | openid2_endpoint => $app->base . $app->mt_uri('mode' => 'openid'), |
|---|
| 26 | openid1_endpoint => $app->base . $app->mt_uri('mode' => 'openid'), |
|---|
| 27 | }; |
|---|
| 28 | return $plugin->load_tmpl( 'xrds-server.tmpl', $param ); |
|---|
| 29 | } |
|---|
| 30 | elsif ( 'openid_xrds_id' eq $app->mode ) { |
|---|
| 31 | my $param = { |
|---|
| 32 | openid2_endpoint => |
|---|
| 33 | $app->base . $app->mt_uri('mode' => 'openid', args => { 'id' => $app->param('id') }), |
|---|
| 34 | openid1_endpoint => |
|---|
| 35 | $app->base . $app->mt_uri('mode' => 'openid', args => { 'id' => $app->param('id') }), |
|---|
| 36 | }; |
|---|
| 37 | return $plugin->load_tmpl( 'xrds-signon.tmpl', $param ); |
|---|
| 38 | } |
|---|
| 39 | } |
|---|
| 40 | elsif ( 'HEAD' eq $app->request_method ) { |
|---|
| 41 | $app->set_header( 'X-XRDS-Location' => $app->base . $app->mt_uri('mode' => $app->mode) ); |
|---|
| 42 | return q(); |
|---|
| 43 | } |
|---|
| 44 | return $app->error($plugin->translate('Invalid request')); |
|---|
| 45 | } |
|---|
| 46 | |
|---|
| 47 | sub _build_nos { |
|---|
| 48 | my $app = shift; |
|---|
| 49 | my $path = $app->uri; |
|---|
| 50 | if ($path =~ m!^/!) { |
|---|
| 51 | # relative path, prepend domain name |
|---|
| 52 | my $domain = "http://" . $ENV{'HTTP_HOST'}; |
|---|
| 53 | $path = $domain . $path; |
|---|
| 54 | } |
|---|
| 55 | return Net::OpenID::Server->new( |
|---|
| 56 | post_args => $app->{query}, |
|---|
| 57 | get_args => $app->{query}, |
|---|
| 58 | get_user => sub { $app }, |
|---|
| 59 | get_identity => \&get_identity, |
|---|
| 60 | is_identity => \&is_identity, |
|---|
| 61 | is_trusted => \&is_trusted, |
|---|
| 62 | server_secret => $app->config->SecretToken, |
|---|
| 63 | setup_url => $app->base . $app->mt_uri('mode' => 'openid_setup'), |
|---|
| 64 | endpoint_url => $app->base . $app->mt_uri('mode' => 'openid'), |
|---|
| 65 | ); |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | sub openid { |
|---|
| 69 | my $app = shift; |
|---|
| 70 | |
|---|
| 71 | if ( 'HEAD' eq $app->request_method ) { |
|---|
| 72 | if ( $app->param('id') ) { |
|---|
| 73 | $app->set_header( 'X-XRDS-Location' => |
|---|
| 74 | $app->base . $app->mt_uri( |
|---|
| 75 | 'mode' => 'openid_xrds_id', |
|---|
| 76 | 'args' => { 'id' => $app->param('id') } |
|---|
| 77 | ) ); |
|---|
| 78 | } |
|---|
| 79 | else { |
|---|
| 80 | $app->set_header( 'X-XRDS-Location' => |
|---|
| 81 | $app->base . $app->mt_uri( |
|---|
| 82 | 'mode' => 'openid_xrds' |
|---|
| 83 | ) ); |
|---|
| 84 | } |
|---|
| 85 | return q(); |
|---|
| 86 | } |
|---|
| 87 | |
|---|
| 88 | my $plugin = $app->component('openid2-server'); |
|---|
| 89 | my $nos = _build_nos($app); |
|---|
| 90 | my ($type, $data) = $nos->handle_page(); |
|---|
| 91 | |
|---|
| 92 | if ( 'redirect' eq $type ) { |
|---|
| 93 | # we handle login by leveraging requires_login |
|---|
| 94 | $app->redirect($data); |
|---|
| 95 | } elsif ( 'setup' eq $type ) { |
|---|
| 96 | ## Was it an identity or trust failure? Cancel. |
|---|
| 97 | return $app->error( |
|---|
| 98 | $plugin->translate('Your account is not authorized to assert the requested identity.')) |
|---|
| 99 | if $app->user; |
|---|
| 100 | |
|---|
| 101 | my $url = $nos->setup_url; |
|---|
| 102 | $url .= '&'. $_ .'='. MT::Util::encode_url($data->{$_}) |
|---|
| 103 | for qw( trust_root return_to identity assoc_handle ns ); |
|---|
| 104 | return $app->redirect($url); |
|---|
| 105 | } |
|---|
| 106 | elsif ( 'GET' eq $app->request_method && ( my $id = $app->param('id') ) ) { |
|---|
| 107 | my $user = $app->model('author')->load($id); |
|---|
| 108 | if ( $user->url ) { |
|---|
| 109 | return $app->redirect( $user->url ); |
|---|
| 110 | } |
|---|
| 111 | } |
|---|
| 112 | else { |
|---|
| 113 | $app->response_content_type($type); |
|---|
| 114 | $app->set_header( 'X-XRDS-Location' => $app->base . $app->mt_uri('mode' => $app->mode) ); |
|---|
| 115 | return $data; |
|---|
| 116 | } |
|---|
| 117 | return $app->error($plugin->translate('Invalid request.')); |
|---|
| 118 | |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | sub get_identity { |
|---|
| 122 | my ( $app, $identity ) = @_; |
|---|
| 123 | |
|---|
| 124 | return undef unless $app; |
|---|
| 125 | return undef unless $app->user; |
|---|
| 126 | |
|---|
| 127 | if ( IDENTIIFER_SELECT() eq $identity ) { |
|---|
| 128 | return undef; |
|---|
| 129 | } |
|---|
| 130 | $app->user->url; |
|---|
| 131 | } |
|---|
| 132 | |
|---|
| 133 | sub is_identity { |
|---|
| 134 | my ( $app, $identity ) = @_; |
|---|
| 135 | |
|---|
| 136 | return 0 unless $app; |
|---|
| 137 | return 0 unless $app->user; |
|---|
| 138 | $app->user->url eq $identity ? 1 : 0; |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | sub is_trusted { |
|---|
| 142 | my ( $app, $trust_root, $is_identity ) = @_; |
|---|
| 143 | return 0 unless $app; |
|---|
| 144 | return 0 unless $app->user; |
|---|
| 145 | $is_identity; |
|---|
| 146 | } |
|---|
| 147 | |
|---|
| 148 | sub setup { |
|---|
| 149 | my $app = shift; |
|---|
| 150 | my $q = $app->param; |
|---|
| 151 | my $plugin = $app->component('openid2-server'); |
|---|
| 152 | my $nos = _build_nos($app); |
|---|
| 153 | |
|---|
| 154 | return $app->error($plugin->translate('Invalid login')) |
|---|
| 155 | unless $app->user; |
|---|
| 156 | |
|---|
| 157 | my %param = map { $_ => $q->param( $_ ) } |
|---|
| 158 | qw( return_to identity trust_root assoc_handle ns ); |
|---|
| 159 | $param{'ng_url'} = $nos->cancel_return_url( return_to => $q->param('return_to') ); |
|---|
| 160 | $plugin->load_tmpl( 'setup.tmpl', \%param ); |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | sub confirm { |
|---|
| 164 | my $app = shift; |
|---|
| 165 | $app->validate_magic or return; |
|---|
| 166 | my $q = $app->param; |
|---|
| 167 | |
|---|
| 168 | my $nos = _build_nos($app); |
|---|
| 169 | my %param = map { $_ => $q->param( $_ ) } |
|---|
| 170 | qw( return_to identity trust_root assoc_handle ns ); |
|---|
| 171 | $param{'identity'} = |
|---|
| 172 | $app->base . $app->mt_uri('mode' => 'openid', args => { 'id' => $app->user->id }) |
|---|
| 173 | unless $param{'identity'}; |
|---|
| 174 | my $redirect = $nos->signed_return_url( %param ); |
|---|
| 175 | $app->redirect($redirect); |
|---|
| 176 | } |
|---|
| 177 | |
|---|
| 178 | 1; |
|---|
| 179 | __END__ |
|---|