realm
algorithm
use_uri_for
+ no_unprompted_authorization_required
+ require_ssl
+ broken_dotnet_digest_without_query_string
/);
-our $VERSION = '1.013';
+our $VERSION = '1.014';
sub new {
my ($class, $config, $app, $realm) = @_;
my ( $self, $c, $realm, $auth_info ) = @_;
my $auth;
+ $self->authentication_failed( $c, $realm, $auth_info )
+ if $self->require_ssl ? $c->req->base->scheme ne 'https' : 0;
+
$auth = $self->authenticate_digest($c, $realm, $auth_info) if $self->_is_http_auth_type('digest');
return $auth if $auth;
$auth = $self->authenticate_basic($c, $realm, $auth_info) if $self->_is_http_auth_type('basic');
return $auth if $auth;
- $self->authorization_required_response($c, $realm, $auth_info);
- die $Catalyst::DETACH;
+ $self->authentication_failed( $c, $realm, $auth_info );
+}
+
+sub authentication_failed {
+ my ( $self, $c, $realm, $auth_info ) = @_;
+ unless ($self->no_unprompted_authorization_required) {
+ $self->authorization_required_response($c, $realm, $auth_info);
+ die $Catalyst::DETACH;
+ }
}
sub authenticate_basic {
my $algorithm = $res{algorithm} || 'MD5';
my $nonce_count = '0x' . $res{nc};
- my $check = $uri eq $res{uri}
+ my $check = ($uri eq $res{uri} ||
+ ($self->broken_dotnet_digest_without_query_string &&
+ $c->request->uri->path eq $res{uri}))
&& ( exists $res{username} )
&& ( exists $res{qop} )
&& ( exists $res{cnonce} )
sub foo : Local {
my ( $self, $c ) = @_;
- $c->authenticate({ realm => "example" });
+ $c->authenticate({}, "example");
# either user gets authenticated or 401 is sent
# Note that the authentication realm sent to the client (in the
# RFC 2617 sense) is overridden here, but this *does not*
You may override these methods. By default they will call C<get> and C<set> on
C<< $c->cache >>.
+=item authentication_failed
+
+Sets the 401 response and calls C<< $ctx->detach >>.
+
=back
=head1 CONFIGURATION
-All configuration is stored in C<< YourApp->config(authentication => { yourrealm => { credential => { class => 'HTTP', %config } } } >>.
+All configuration is stored in C<< YourApp->config('Plugin::Authentication' => { yourrealm => { credential => { class => 'HTTP', %config } } } >>.
This should be a hash, and it can contain the following entries:
of your domain, and you want to ensure that authentication credentials from your application are not shared with
other applications on the same server.
+=item require_ssl
+
+If this configuration key has a true value then authentication will be denied
+(and a 401 issued in normal circumstances) unless the request is via https.
+
+=item no_unprompted_authorization_required
+
+Causes authentication to fail as normal modules do, without calling
+C<< $c->detach >>. This means that the basic auth credential can be used as
+part of the progressive realm.
+
+However use like this is probably not optimum it also means that users in
+browsers ill never get a HTTP authenticate dialogue box (unless you manually
+return a 401 response in your application), and even some automated
+user agents (for APIs) will not send the Authorization header without
+specific manipulation of the request headers.
+
+=item broken_dotnet_digest_without_query_string
+
+Enables support for .NET (or other similarly broken clients), which
+fails to include the query string in the uri in the digest
+Authorization header, contrary to rfc2617.
+
+This option has no effect on clients that include the query string;
+they will continue to work as normal.
+
=back
=head1 RESTRICTIONS
=item Devin Austin (dhoss) C<dhoss@cpan.org>
+=item Ronald J Kimball
+
=back
=head1 SEE ALSO