| 70 | | elsif ($c->req->param('openid_check')) { |
| 71 | | if (my $setup_url = $csr->user_setup_url) { |
| 72 | | $c->res->redirect($setup_url); |
| 73 | | return; |
| 74 | | } |
| 75 | | elsif ($csr->user_cancel) { |
| 76 | | $c->log->debug('User cancel authentication') if $c->debug; |
| 77 | | return; |
| 78 | | } |
| 79 | | elsif (my $identity = $csr->verified_identity) { |
| 80 | | my $userinfo = +{ map { $_ => scalar $identity->$_ } |
| 81 | | qw( url display rss atom foaf declared_rss declared_atom declared_foaf foafmaker ) }; |
| 82 | | |
| 83 | | # override display using sreg nickname |
| 84 | | my $sreg_ns = 'http://openid.net/extensions/sreg/1.1'; |
| 85 | | if (my $sreg = $identity->extension_fields($sreg_ns)) { |
| 86 | | $userinfo->{display} = $sreg->{nickname} || $sreg->{fullname} || $userinfo->{display}; |
| 87 | | } |
| 88 | | |
| 89 | | $userinfo = Catalyst::Utils::merge_hashes($authinfo, $userinfo); |
| 90 | | my $user = $realm->find_user($userinfo, $c); |
| 91 | | if (ref($user)) { |
| 92 | | return $user; |
| 93 | | } |
| 94 | | else { |
| 95 | | $c->log->error("Unable to locate user matching user info provided"); |
| 96 | | return; |
| 97 | | } |
| 98 | | } |
| 99 | | else { |
| 100 | | $c->log->error("Error validating identity: " . $csr->err); |
| 101 | | return; |
| 102 | | } |
| 103 | | } |
| 104 | | else { |
| 105 | | return; |
| | 76 | elsif ($c->req->params->{openid_check}) { |
| | 77 | my $user; |
| | 78 | |
| | 79 | $csr->handle_server_response( |
| | 80 | not_openid => sub { |
| | 81 | $c->log->error('Not an OpenID Message'); |
| | 82 | }, |
| | 83 | setup_required => sub { |
| | 84 | my $setup_url = shift; |
| | 85 | $c->res->redirect($setup_url); |
| | 86 | $c->detach; |
| | 87 | }, |
| | 88 | cancelled => sub { |
| | 89 | $c->log->debug('User cancel authentication') if $c->debug; |
| | 90 | }, |
| | 91 | verified => sub { |
| | 92 | my $vident = shift; |
| | 93 | my $userinfo = +{ map { $_ => scalar $vident->$_ } qw( |
| | 94 | url display rss atom foaf declared_rss declared_atom declared_foaf foafmaker |
| | 95 | )}; |
| | 96 | |
| | 97 | # get extensions args |
| | 98 | my @ns = keys %{ $self->config->{extension_args} || {} }; |
| | 99 | if (@ns) { |
| | 100 | $userinfo->{extensions} = {}; |
| | 101 | |
| | 102 | for my $ns (@ns) { |
| | 103 | my $args = $vident->extension_fields($ns) || {}; |
| | 104 | $userinfo->{extensions}->{$ns} = $args; |
| | 105 | } |
| | 106 | } |
| | 107 | |
| | 108 | $userinfo = Catalyst::Utils::merge_hashes($authinfo, $userinfo); |
| | 109 | |
| | 110 | $user = $realm->find_user($userinfo, $c); |
| | 111 | unless (ref $user) { |
| | 112 | $c->log->error("Unable to locate user matching user info provided"); |
| | 113 | } |
| | 114 | }, |
| | 115 | error => sub { |
| | 116 | my ($code, $text) = @_; |
| | 117 | $c->log->error("Error validating identity: $code: $text"); |
| | 118 | }, |
| | 119 | ); |
| | 120 | |
| | 121 | return $user if ref $user; |
| | 173 | =head1 METHODS |
| | 174 | |
| | 175 | =head2 new |
| | 176 | |
| | 177 | You will never call this. Catalyst does it for you. The only important |
| | 178 | thing you might like to know about it is that it merges its realm |
| | 179 | configuration with its configuration proper. If this doesn't mean |
| | 180 | anything to you, don't worry. |
| | 181 | |
| | 182 | =head2 authenticate |
| | 183 | |
| | 184 | Call to authenticate the user via OpenID. Returns false if |
| | 185 | authorization is unsuccessful. Sets the user into the session and |
| | 186 | returns the user object if authentication succeeds. |
| | 187 | |
| | 188 | You can see in the call above that the authentication hash is empty. |
| | 189 | The implicit OpenID parameter is, as the 2.0 specification says it |
| | 190 | SHOULD be, B<openid_identifier>. You can set it anything you like in |
| | 191 | your realm configuration, though, under the key C<openid_field>. If |
| | 192 | you call C<authenticate()> with the empty info hash and no configured |
| | 193 | C<openid_field> then only C<openid_identifier> is checked. |
| | 194 | |
| | 195 | It implicitly does this (sort of, it checks the request method too)- |
| | 196 | |
| | 197 | my $claimed_uri = $c->req->params->{openid_identifier}; |
| | 198 | $c->authenticate({ openid_identifier => $claimed_uri }); |
| | 199 | |
| | 202 | Catalyst authentication is now configured entirely from your |
| | 203 | application's configuration. Do not, for example, put |
| | 204 | C<Credential::OpenID> into your C<use Catalyst ...> statement. |
| | 205 | Instead, tell your application that in one of your authentication |
| | 206 | realms you will use the credential. |
| | 207 | |
| | 208 | __PACKAGE__->config( |
| | 209 | name => 'MyApp', |
| | 210 | 'Plugin::Authentication' => { |
| | 211 | default_realm => 'openid', |
| | 212 | openid => { |
| | 213 | credential => { |
| | 214 | class => 'OpenID', |
| | 215 | consumer_secret => "Don't bother setting", |
| | 216 | ua_class => 'LWP::UserAgent', |
| | 217 | ua_args => { |
| | 218 | env_proxy => 1, |
| | 219 | parse_head => 0, |
| | 220 | }, |
| | 221 | # OpenID Extension |
| | 222 | extension_args => { |
| | 223 | 'http://openid.net/extensions/sreg/1.1' => { |
| | 224 | required => 'nickname,email', |
| | 225 | }, |
| | 226 | }, |
| | 227 | }, |
| | 228 | store => { |
| | 229 | class => 'Null', |
| | 230 | }, |
| | 231 | }, |
| | 232 | }, |
| | 233 | ); |
| | 234 | |
| 163 | | =item class |
| 164 | | |
| 165 | | The classname used for Credential. For this module to be used, |
| 166 | | this must be set to "OpenID". |
| 167 | | |
| 168 | | =item identity_field |
| 169 | | |
| 170 | | The field name in the Store class that contains the identity. |
| 171 | | Default value is "username". |
| 172 | | |
| 173 | | If authentication succeeded, |
| 174 | | this field in $authinfo is automatically set, |
| 175 | | and this module call find_user() in Realm class. |
| 176 | | |
| 177 | | =back |
| 178 | | |
| 179 | | =head1 METHODS |
| 180 | | |
| 181 | | =over 4 |
| 182 | | |
| 183 | | =item new |
| 184 | | |
| 185 | | =item authenticate |
| | 237 | =item ua_args and ua_class |
| | 238 | |
| | 239 | L<LWPx::ParanoidAgent> is the default agent E<mdash> C<ua_class>. You don't |
| | 240 | have to set it. I recommend that you do B<not> override it. You can |
| | 241 | with any well behaved L<LWP::UserAgent>. You probably should not. |
| | 242 | L<LWPx::ParanoidAgent> buys you many defenses and extra security |
| | 243 | checks. When you allow your application users freedom to initiate |
| | 244 | external requests, you open a big avenue for DoS (denial of service) |
| | 245 | attacks. L<LWPx::ParanoidAgent> defends against this. |
| | 246 | L<LWP::UserAgent> and any regular subclass of it will not. |
| | 247 | |
| | 248 | =item consumer_secret |
| | 249 | |
| | 250 | The underlying L<Net::OpenID::Consumer> object is seeded with a |
| | 251 | secret. If it's important to you to set your own, you can. The default |
| | 252 | uses this package name + its version + the sorted configuration keys |
| | 253 | of your Catalyst application (chopped at 255 characters if it's |
| | 254 | longer). This should generally be superior to any fixed string. |
| | 255 | |
| | 256 | =item extension_args |
| | 257 | |
| | 258 | set OpenID extension (eg. SREG) parameters for request. |
| | 259 | |
| | 260 | in credential section of config: |
| | 261 | |
| | 262 | credential => { |
| | 263 | class => 'OpenID', |
| | 264 | extension_args => { |
| | 265 | 'http://openid.net/extensions/sreg/1.1' => { |
| | 266 | required => 'nickname,email', |
| | 267 | }, |
| | 268 | # $namespace => { |
| | 269 | # $key1 => $value1, |
| | 270 | # $key2 => $value2, |
| | 271 | # ... |
| | 272 | # }, |
| | 273 | }, |
| | 274 | }, |
| | 275 | |
| | 276 | This means (OpenID Request): |
| | 277 | |
| | 278 | # openid.ns.sreg = http://openid.net/extensions/sreg/1.1 |
| | 279 | # openid.sreg.required = nickname,email |
| | 280 | |
| | 281 | and your controller: |
| | 282 | |
| | 283 | if (my $user = $c->authenticate) { |
| | 284 | my $sreg = $user->extensions->{'http://openid.net/extensions/sreg/1.1'}; |
| | 285 | my $nickname = $sreg->{nickname}; |
| | 286 | my $email = $sreg->{email}; |
| | 287 | } |
| | 288 | |
| | 289 | This means (OpenID Response): |
| | 290 | |
| | 291 | # openid.ns.sreg = http://openid.net/extensions/sreg/1.1 |
| | 292 | # openid.sreg.nickname = foo |
| | 293 | # openid.sreg.email = foo@example.com |