Skip to content

Commit

Permalink
Merge pull request #6 from schinkel/master
Browse files Browse the repository at this point in the history
Fixed code to follow Key Uri Format according to spec
  • Loading branch information
ChristianRiesen committed Jul 27, 2015
2 parents 81a50b3 + fd3dc93 commit 1d8b748
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 8 deletions.
20 changes: 13 additions & 7 deletions src/Otp/GoogleAuthenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ public static function getKeyUri($type, $label, $secret, $counter = null, $optio
throw new \InvalidArgumentException('Label has to be one or more printable characters');
}

if (substr_count($label, ':') > 2) {
throw new \InvalidArgumentException('Account name contains illegal colon characters');
}

// Secret needs to be here
if (strlen($secret) < 1) {
throw new \InvalidArgumentException('No secret present');
Expand All @@ -61,36 +65,38 @@ public static function getKeyUri($type, $label, $secret, $counter = null, $optio
}

// This is the base, these are at least required
$otpauth = 'otpauth://' . $type . '/' . $label . '?secret=' . $secret;
$otpauth = 'otpauth://' . $type . '/' . str_replace(array(':', ' '), array('%3A', '%20'), $label) . '?secret=' . rawurlencode($secret);

if ($type == 'hotp' && !is_null($counter)) {
$otpauth .= '&counter=' . $counter;
$otpauth .= '&counter=' . intval($counter);
}

// Now check the options array

// algorithm (currently ignored by Authenticator)
// Defaults to SHA1
if (array_key_exists('algorithm', $options)) {
$otpauth .= '&algorithm=' . $options['algorithm'];
$otpauth .= '&algorithm=' . rawurlencode($options['algorithm']);
}

// digits (currently ignored by Authenticator)
// Defaults to 6
if (array_key_exists('digits', $options)) {
$otpauth .= '&digits=' . $options['digits'];
if (array_key_exists('digits', $options) && intval($options['digits']) !== 6 && intval($options['digits']) !== 8) {
throw new \InvalidArgumentException('Digits can only have the values 6 or 8, ' . $options['digits'] . ' given');
} elseif (array_key_exists('digits', $options)) {
$otpauth .= '&digits=' . intval($options['digits']);
}

// period, only for totp (currently ignored by Authenticator)
// Defaults to 30
if ($type == 'totp' && array_key_exists('period', $options)) {
$otpauth .= '&period=' . $options['period'];
$otpauth .= '&period=' . rawurlencode($options['period']);
}

// issuer
// Defaults to none
if (array_key_exists('issuer', $options)) {
$otpauth .= '&issuer=' . $options['issuer'];
$otpauth .= '&issuer=' . rawurlencode($options['issuer']);
}

return $otpauth;
Expand Down
20 changes: 19 additions & 1 deletion tests/Otp/GoogleAuthenticatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,30 @@ public function testGetKeyUri()
'otpauth://totp/[email protected]?secret=MEP3EYVA6XNFNVNM',
GoogleAuthenticator::getKeyUri('totp', '[email protected]', $secret)
);

// hotp (include a counter)
$this->assertEquals(
'otpauth://hotp/[email protected]?secret=MEP3EYVA6XNFNVNM&counter=1234',
GoogleAuthenticator::getKeyUri('hotp', '[email protected]', $secret, 1234)
);

// totp/hotp with an issuer in the label
$this->assertEquals(
'otpauth://hotp/issuer%[email protected]?secret=MEP3EYVA6XNFNVNM&counter=1234',
GoogleAuthenticator::getKeyUri('hotp', 'issuer:[email protected]', $secret, 1234)
);

// totp/hotp with an issuer and spaces in the label
$this->assertEquals(
'otpauth://hotp/an%20issuer%3A%[email protected]?secret=MEP3EYVA6XNFNVNM&counter=1234',
GoogleAuthenticator::getKeyUri('hotp', 'an issuer: [email protected]', $secret, 1234)
);

// totp/hotp with an issuer as option
$this->assertEquals(
'otpauth://hotp/an%20issuer%[email protected]?secret=MEP3EYVA6XNFNVNM&counter=1234&issuer=an%20issuer',
GoogleAuthenticator::getKeyUri('hotp', 'an issuer:[email protected]', $secret, 1234, array('issuer' => 'an issuer'))
);
}

/**
Expand Down

0 comments on commit 1d8b748

Please sign in to comment.