File Coverage

blib/lib/VisualDreams/Yubikey/online.pm
Criterion Covered Total %
statement 18 63 28.5
branch 0 6 0.0
condition 0 6 0.0
subroutine 6 12 50.0
pod 5 6 83.3
total 29 93 31.1


line stmt bran cond sub pod time code
1             package VisualDreams::Yubikey::online;
2              
3             our $VERSION = '0.06';
4              
5 1     1   6608 use warnings;
  1         2  
  1         37  
6 1     1   5 use strict;
  1         2  
  1         36  
7 1     1   821 use Digest::HMAC_SHA1 qw(hmac_sha1);
  1         8967  
  1         48  
8 1     1   834 use LWP::Simple;
  1         103453  
  1         10  
9 1     1   1659 use MIME::Base64;
  1         826  
  1         71  
10 1     1   7 use URI::Escape;
  1         2  
  1         648  
11              
12             =head1 NAME
13            
14             VisualDreams::Yubikey::online - Yubikey online authentication
15              
16             =head1 DESCRIPTION
17            
18             This module will authenticate with the online Yubico API authentication server and return its results
19             in a HASH. This module is to be implemented in the VisualDreams engine.
20            
21             =head1 VERSION
22              
23             Version 0.06
24              
25             =head1 SYNOPSIS
26            
27             use VisualDreams::Yubikey::online;
28              
29             my $yubify = VisualDreams::Yubikey::online->new("ID","Base64 encoded API key");
30              
31             my $yubirecord = $yubify->verifyOnline($otp);
32              
33             my $url = $yubify->createUrl($otp);
34             my $signedurl = $yubify->createSignedUrl($otp);
35             my $signUrl = $yubify->signUrl($url);
36              
37             =head1 FUNCTIONS
38              
39             =head2 new
40              
41             Input : API-ID and API-KEY
42              
43             Initializes the module to standard API-ID, API-KEY and API-URL.
44             WARNING: Signed messages will automagically work with a valid Base-64 API key!
45              
46             =cut
47              
48             sub new {
49 0     0 1   my $class = shift;
50 0   0       my $apiId = shift || die("Need atleast an Yubikey API ID");
51 0   0       my $apiKey = shift || "";
52 0   0       my $apiUrl = shift || 'http://api.yubico.com/wsapi/verify?';
53 0           my $self = { apiId => $apiId,
54             apiKey => $apiKey,
55             apiUrl => $apiUrl,
56             };
57              
58 0           bless $self, $class;
59 0           return $self;
60             }
61              
62             =head2 signUrl
63              
64             Signs the URL with API-ID, API-KEY and incoming url
65              
66             Input : url
67             Output : signed base-64 encoded hmac
68              
69             =cut
70              
71             sub signUrl($) {
72 0     0 1   my $self = shift;
73 0           my $message = shift;
74 0           my $apiKeyDecoded = MIME::Base64::decode($self->{apiKey});
75 0           my $hmac = hmac_sha1($message, $apiKeyDecoded);
76 0           my $signature = uri_escape(MIME::Base64::encode($hmac),"\x2b");
77 0           return($signature);
78             }
79              
80             =head2 createUrl
81              
82             Create standard URL with API-ID and OTP
83              
84             Input : otp
85             Output : piece of url containing id and otp
86              
87             =cut
88              
89              
90             sub createUrl {
91 0     0 1   my $self = shift;
92 0           my $otp = shift;
93 0           my $message = "id=$self->{apiId}&otp=$otp";
94 0           return($message);
95             }
96              
97             =head2 createSignedUrl
98              
99             Create Signed URL with API-ID, API-KEY and OTP
100              
101             Input : otp
102             Output : piece of url containing id, otp and base-64 hmac signature
103              
104             =cut
105              
106             sub createSignedUrl {
107 0     0 1   my $self = shift;
108 0           my $otp = shift;
109 0           my $message = $self->createUrl($otp);
110 0           my $apiSignature = $self->signUrl($message);
111 0           $message .= "&h=$apiSignature";
112 0           return($message);
113             }
114              
115             sub returnYubiField {
116 0     0 0   my $self = shift;
117 0           my $content = shift;
118 0           my $identifier = shift;
119 0           chomp($content);
120 0 0         if ($content =~ m/$identifier=(.*)/i) {
121 0           my $return = $1;
122 0           return($return);
123             }
124             }
125              
126             =head2 verifyOnline
127              
128             Verify the OTP with the Yubico server
129              
130             Input : otp
131             Output : record with hmac, status and timestamp
132              
133             =cut
134              
135              
136             sub verifyOnline {
137 0     0 1   my $self = shift;
138 0           my $otp = shift;
139 0           my $signed;
140 0           my $url = $self->{apiUrl};
141 0           my $yubirecord;
142             my $errorstatus;
143              
144 0 0         if ($self->{apiKey}) {
145 0           $url .= $self->createSignedUrl($otp);
146             } else {
147 0           $url .= $self->createUrl($otp);
148             }
149              
150 0           my $content = get($url);
151              
152             # offer support for more responses later on!
153              
154 0 0         if ($content) {
155 0           my %yubiResponses = ("hmac", "h",
156             "time", "t",
157             "status", "status");
158              
159            
160 0           while (my ($humanIdentifier, $yubIdentifier) = each(%yubiResponses)) {
161 0           $yubirecord->{$humanIdentifier} = $self->returnYubiField($content,$yubIdentifier);
162             }
163              
164             } else {
165 0           $yubirecord->{status} = "Could not retrieve status from Yubico";
166             }
167              
168 0           return($yubirecord);
169             }
170              
171              
172              
173             1;
174             __END__