AnyEvent-Yubico
view release on metacpan or search on metacpan
Revision history for Perl extension AnyEvent::Yubico.
0.9.3 Wed Mar 06 11:31:03 2013
- Replaced usage of AnyEvent->timer for timeouts with setting
the timeout parameter for each HTTP connection, as the timer
was showing some incorrect behavior.
0.9.2 Fri Feb 22 14:09:06 2013
- Fixed bug preventing verify from working.
- Lowered the required version of AnyEvent::HTTP to ensure that
all dependencies are available on Ubuntu 12.04
0.9.1 Thu Feb 21 15:38:02 2013
- Added dependencies to Makefile.PL
- Added COPYING
- Made tests requiring Internet access optional
Disable by setting the environment variable NO_INTERNET
0.9.0 Wed Feb 20 12:57:23 2013
lib/AnyEvent/Yubico.pm view on Meta::CPAN
our $VERSION = '0.9.3';
# Creates a new Yubico instance to be used for validation of OTPs.
sub new {
my $class = shift;
my $self = {
sign_request => 1,
local_timeout => 30.0,
urls => [
"https://api.yubico.com/wsapi/2.0/verify",
"https://api2.yubico.com/wsapi/2.0/verify",
"https://api3.yubico.com/wsapi/2.0/verify",
"https://api4.yubico.com/wsapi/2.0/verify",
"https://api5.yubico.com/wsapi/2.0/verify"
]
};
my $options = shift;
$self = { %$self, %$options };
return bless $self, $class;
};
# Verifies the given OTP and returns a true value if the OTP could be
# verified, false otherwise.
sub verify {
return verify_async(@_)->recv->{status} eq 'OK';
}
# Verifies the given OTP and returns a hash containing the server response.
sub verify_sync {
return verify_async(@_)->recv
}
# Non-blocking version of verify_sync, which returns a condition variable
# (see AnyEvent->condvar for details).
sub verify_async {
my($self, $otp, $callback) = @_;
my $nonce = create_UUID_as_string(UUID_V4);
$nonce =~ s/-//g;
my $params = {
id => $self->{client_id},
nonce => $nonce,
otp => $otp
};
lib/AnyEvent/Yubico.pm view on Meta::CPAN
Though AnyEvent is used internally, the module does not impose any particular
coding style on the caller. Provides both blocking and non-blocking methods of
OTP verification.
=head1 SYNOPSIS
use AnyEvent::Yubico;
$yk = AnyEvent::Yubico->new({ client_id => 4711, api_key => '<your API key here>' });
$result = $yk->verify('<YubiKey OTP here>');
if($result) ...
For more details about the response, instead call verify_sync($otp), which
returns a hash containing all the parameters that were in the response.
$result_details = $yk->verify_sync('<YubiKey OTP here>');
if($result_details->{status} == 'OK') ...
As an alternative, you can call verify_async, which will return a condition
variable immediately. This can be used if your application already uses an
asynchronous model. You can also pass a callback as a second parameter to
verify as well as verify_async, which will be invoked once validation has
completed, with the result.
$result_cv = $yk->verify_async('<YubiKey OTP here>', sub {
#Callback invoked when verification is done
$result_details = shift;
if($result_details->{status} eq 'OK') ...
});
#Wait for the result (blocking, same as calling verify directly).
$result_details = $result_cv->recv;
=head1 DESCRIPTION
Validates a YubiKey OTP (One Time Password) using the YKVAL 2.0 protocol as
defined here: https://github.com/Yubico/yubikey-val/wiki/ValidationProtocolV20
To use this module, an API key is required, which can be requested here:
https://upgrade.yubico.com/getapikey/
When creating the AnyEvent::Yubico instance, the following arguments can be passed:
=over 4
=item client_id = $id_int
Required. The client ID corresponding to the API key.
=item api_key => $api_key_string
Optional. The API key used to sign requests and verify responses. Without
this response signatures won't be verified.
=item urls => $array_of_urls
Optional. Defines which validation server URLs to query. The default uses
the public YubiCloud validation servers. Must support version 2.0 of the
validation protocol.
Example:
$yk = AnyEvent::Yubico->new({
client_id => ...,
api_key => ...,
urls => [
"http://example.com/wsapi/2.0/verify",
"http://127.0.0.1/wsapi/2.0/verify"
]
});
=item sign_requests => $enable
Optional. When enabled (enabled by default) requests will be signed, as long
as api_key is also provided.
=item timeout => $seconds
lib/AnyEvent/Yubico.pm view on Meta::CPAN
Optional. Security level parameter sent to the server, see the protocol
details for more information.
=item timestamp => $enable
Optional. When enabled, sends the timestamp parameter to the server, causing
YubiKey counter and timestamp information to be returned in the response.
=item local_timeout => $seconds
Optional. Sets the local timeout for how long the verify method will wait
until failing. The default is 30 seconds.
=back
=head1 SEE ALSO
The Yubico Validation Protocol 2.0 specification:
https://github.com/Yubico/yubikey-val/wiki/ValidationProtocolV20
More information about the YubiKey:
t/AnyEvent-Yubico.t view on Meta::CPAN
my $test_signature = "k7ZRKLOn3C6565YVqmG2rd4PHVU=";
ok(defined($validator) && ref $validator eq "AnyEvent::Yubico", "new() works");
is($validator->sign($test_params), $test_signature, "sign() works");
my $default_urls = $validator->{urls};
$validator->{urls} = [ "http://127.0.0.1:0" ];
is($validator->verify_async("vvgnkjjhndihvgdftlubvujrhtjnllfjneneugijhfll")->recv()->{status}, "Connection refused", "invalid URL");
$validator->{urls} = $default_urls;
$validator->{local_timeout} = 0.01;
is($validator->verify_sync("vvgnkjjhndihvgdftlubvujrhtjnllfjneneugijhfll")->{status}, "Connection timed out", "timeout");
$validator->{local_timeout} = 30.0;
subtest 'Tests that require access to the Internet' => sub {
if(exists($ENV{'NO_INTERNET'})) {
plan skip_all => 'Internet tests';
} else {
plan tests => 5;
}
is($validator->verify_sync("ccccccbhjkbulvkhvfuhlltctnjtgrvjuvcllliufiht")->{status}, "REPLAYED_OTP", "replayed OTP");
$validator = AnyEvent::Yubico->new({
client_id => $client_id,
});
my $result = $validator->verify_sync("ccccccbhjkbubrbnrtifbiuhevinenrhtlckuctjjuuu");
is($result->{status}, "BAD_OTP", "invalid OTP");
#Test manual signature verification
ok(exists($result->{h}), "signature exists");
my $sig = $result->{h};
delete $result->{h};
$validator->{api_key} = $api_key;
is($validator->sign($result), $sig, "signature is correct");
ok(! $validator->verify("ccccccbhjkbubrbnrtifbiuhevinenrhtlckuctjjuuu"), "verify(\$bad_otp)");
};
( run in 0.290 second using v1.01-cache-2.11-cpan-5467b0d2c73 )