Skip to content

A collection of classes to provide second factor authentication like Yubico OTP (Yubikey), Oath (TOTP, HOTP, GoogleAuthenticator) server-side written in PHP.

License

Notifications You must be signed in to change notification settings

chroma-x/php-oath-server-suite

Repository files navigation

PHP Oath Server Suite

Build Status Test Coverage Dependency Status SensioLabs Insight Code Climate Latest Stable Version Total Downloads License

A collection of classes to provide second factor authentication like Yubico OTP (Yubikey), Oath (TOTP, HOTP, GoogleAuthenticator) server-side.

For more information about Oath check out https://openauthentication.org/.

More information about TOTP (Time-based One-time Password Algorithm) can be found at Wikipedia.

More information about HOTP (HMAC-based One-time Password Algorithm) can be found at Wikipedia.

For more information about the Yubico OTP authentication mechanism read the „What is YubiKey OTP?“ article at https://developers.yubico.com/OTP/.

Installation

{
   	"require": {
        "chroma-x/oath-server-suite": "~4.0"
    }
}

Usage

Autoloading and namesapce

require_once('path/to/vendor/autoload.php');

Yubico OTP (YubiCloud)

To use Yubico OTP you need YubiCloud access. You can get free API credentials from https://upgrade.yubico.com/getapikey/.

Validating a Yubico one time password

use ChromaX\CommonException\NetworkException\Base\NetworkException;

$otp = $_POST['otp'];
$userPublicId = 'fetchedFromDatabaseOrSimilar';

$validator = new OathServerSuite\Validation\YubicoOtp\Validator('yubiCloudClientId', 'yubiCloudSecretKey');
try {
	$validator->validate($otp, $userPublicId);
	if ($validator->isValid()) {
		// Validation was successful
	} else {
		// Validation failed
	}
} catch (NetworkException $exception) {
	// Accessing the YubiCloud webservice failed.
}

Oath – Google Authenticator style

Sharing the key name and secret

To allow authentication the client and server has to share a secret. Usually the server dices a secret and displays it alltogether with the key name and the authentication mechanism as a QR code.

Google Authenticator and some other applications and hardware items – like the Yubikey – do not follow the standard by expecting the secrets not as hexadecimal but as Base32 encoded data.

TOTP (Time-based One-time Password Algorithm)
use ChromaX\OathServerSuite\SecretSharing\SharedSecretQrCodeProvider\SharedSecretQrCodeProvider;
use ChromaX\OathServerSuite\SecretSharing\SharedSecretUrlEncoder\TotpBase32SharedSecretUrlEncoder;
use ChromaX\QrCodeSuite\QrEncode\QrEncoder;

// Initialize Oath URL encoder for TOTP (Time-based One-time Password Algorithm)
$contentEncoder = new TotpBase32SharedSecretUrlEncoder();

// Setting the key name
$keyName = 'My Username';

// Setting the issuer name
$issuerName = 'Awesome Application';

// Setting a secret
// Attention: This is just an example value
// Use a random value of a proper length stored with your user credentials
$sharedSecret = openssl_random_pseudo_bytes(30);

// Getting the shared secret URL for usage wihtout QR code provision
$sharedSecretUrl = $contentEncoder->encode($keyName, $sharedSecret);

// Start QR code provision
// Initialize the QR code provider with Oath URL encoder for TOTP
$sharedSecretQrProvider = new SharedSecretQrCodeProvider(new TotpBase32SharedSecretUrlEncoder(), $keyName, $sharedSecret, $issuerName);

// Configure the QR code renderer for your needs
$sharedSecretQrProvider->getQrEncoder()
	->setLevel(QrEncoder::QR_CODE_LEVEL_LOW)
	->setTempDir('/path/to/a/writable/temp-dir');

// Persist the QR code PNG to the filesystem
$sharedSecretQrProvider->provideQrCode('/path/to/the/qrcode.png');
HOTP (HMAC-based One-time Password Algorithm)
use ChromaX\OathServerSuite\SecretSharing\SharedSecretQrCodeProvider\SharedSecretQrCodeProvider;
use ChromaX\OathServerSuite\SecretSharing\SharedSecretUrlEncoder\HotpBase32SharedSecretUrlEncoder;
use ChromaX\QrCodeSuite\QrEncode\QrEncoder;

// Initialize Oath URL encoder for HOTP (HMAC-based One-time Password Algorithm)
$contentEncoder = new HotpBase32SharedSecretUrlEncoder();

// Setting the key name
$keyName = 'My Username';

// Setting the issuer name
$issuerName = 'Awesome Application';

// Setting a secret
// Attention: This is just an example value
// Use a random value of a proper length stored with your user credentials
$sharedSecret = openssl_random_pseudo_bytes(30);

// Getting the shared secret URL for usage wihtout QR code provision
$sharedSecretUrl = $contentEncoder->encode($keyName, $sharedSecret);

// Start QR code provision
// Initialize the QR code provider with Oath URL encoder for HOTP
$sharedSecretQrProvider = new SharedSecretQrCodeProvider(new HotpBase32SharedSecretUrlEncoder(), $keyName, $sharedSecret, $issuerName);

// Configure the QR code renderer for your needs
$sharedSecretQrProvider->getQrEncoder()
	->setLevel(QrEncoder::QR_CODE_LEVEL_LOW)
	->setTempDir('/path/to/a/writable/temp-dir');

// Persist the QR code PNG to the filesystem
$sharedSecretQrProvider->provideQrCode('/path/to/the/qrcode.png');

Validating a Oath one time password

TOTP (Time-based One-time Password Algorithm)
$totp = $_POST['totp'];
$sharedSecret = 'fetchedFromDatabaseOrSimilar';

$validator = new OathServerSuite\Validation\Oath\TotpValidator();
$validator->validate($totp, $sharedSecret);
if ($validator->isValid()) {
	// Validation was successful
} else {
	// Validation failed
}
HOTP (HMAC-based One-time Password Algorithm)
$hotp = $_POST['hotp'];
$sharedSecret = 'fetchedFromDatabaseOrSimilar';
$counter = (int)'fetchedFromDatabaseOrSimilar';

$validator = new OathServerSuite\Validation\Oath\HotpValidator();
$validator->validate($hotp, $sharedSecret, $counter);
if ($validator->isValid()) {
	// Validation was successful
} else {
	// Validation failed
}

Oath – following the standard

Sharing the key name and secret

TOTP (Time-based One-time Password Algorithm)
use ChromaX\OathServerSuite\SecretSharing\SharedSecretQrCodeProvider\SharedSecretQrCodeProvider;
use ChromaX\OathServerSuite\SecretSharing\SharedSecretUrlEncoder\TotpSharedSecretUrlEncoder;
use ChromaX\QrCodeSuite\QrEncode\QrEncoder;

// Initialize Oath URL encoder for TOTP (Time-based One-time Password Algorithm)
$contentEncoder = new TotpSharedSecretUrlEncoder();

// Setting the key name
$keyName = 'My Username';

// Setting the issuer name
$issuerName = 'Awesome Application';

// Setting a secret
// Attention: This is just an example value
// Use a random value of a proper length stored with your user credentials
$sharedSecret = openssl_random_pseudo_bytes(30);

// Getting the shared secret URL for usage wihtout QR code provision
$sharedSecretUrl = $contentEncoder->encode($keyName, $sharedSecret);

// Start QR code provision
// Initialize the QR code provider with Oath URL encoder for TOTP
$sharedSecretQrProvider = new SharedSecretQrCodeProvider(new TotpSharedSecretUrlEncoder(), $keyName, $sharedSecret, $issuerName);

// Configure the QR code renderer for your needs
$sharedSecretQrProvider->getQrEncoder()
	->setLevel(QrEncoder::QR_CODE_LEVEL_LOW)
	->setTempDir('/path/to/a/writable/temp-dir');

// Persist the QR code PNG to the filesystem
$sharedSecretQrProvider->provideQrCode('/path/to/the/qrcode.png');
HOTP (HMAC-based One-time Password Algorithm)
use ChromaX\OathServerSuite\SecretSharing\SharedSecretQrCodeProvider\SharedSecretQrCodeProvider;
use ChromaX\OathServerSuite\SecretSharing\SharedSecretUrlEncoder\HotpSharedSecretUrlEncoder;
use ChromaX\QrCodeSuite\QrEncode\QrEncoder;

// Initialize Oath URL encoder for HOTP (HMAC-based One-time Password Algorithm)
$contentEncoder = new HotpSharedSecretUrlEncoder();

// Setting the key name
$keyName = 'My Username';

// Setting the issuer name
$issuerName = 'Awesome Application';

// Setting a secret
// Attention: This is just an example value
// Use a random value of a proper length stored with your user credentials
$sharedSecret = openssl_random_pseudo_bytes(30);

// Getting the shared secret URL for usage wihtout QR code provision
$sharedSecretUrl = $contentEncoder->encode($keyName, $sharedSecret);

// Start QR code provision
// Initialize the QR code provider with Oath URL encoder for HOTP
$sharedSecretQrProvider = new SharedSecretQrCodeProvider(new HotpSharedSecretUrlEncoder(), $keyName, $sharedSecret, $issuerName);

// Configure the QR code renderer for your needs
$sharedSecretQrProvider->getQrEncoder()
	->setLevel(QrEncoder::QR_CODE_LEVEL_LOW)
	->setTempDir('/path/to/a/writable/temp-dir');

// Persist the QR code PNG to the filesystem
$sharedSecretQrProvider->provideQrCode('/path/to/the/qrcode.png');

Validating a Oath one time password

TOTP (Time-based One-time Password Algorithm)
$totp = $_POST['totp'];
$sharedSecret = 'fetchedFromDatabaseOrSimilar';

$validator = new OathServerSuite\Validation\Oath\TotpValidator();
$validator->validate($totp, $sharedSecret);
if ($validator->isValid()) {
	// Validation was successful
} else {
	// Validation failed
}
HOTP (HMAC-based One-time Password Algorithm)
$hotp = $_POST['hotp'];
$sharedSecret = 'fetchedFromDatabaseOrSimilar';
$counter = (int)'fetchedFromDatabaseOrSimilar';

$validator = new OathServerSuite\Validation\Oath\HotpValidator();
$validator->validate($hotp, $sharedSecret, $counter);
if ($validator->isValid()) {
	// Validation was successful
} else {
	// Validation failed
}

Exception handling

PHP Oath Server Suite provides different exceptions – some provided by the PHP Common Exceptions project – for proper handling.
You can find more information about PHP Common Exceptions at Github.


Contribution

Contributing to our projects is always very appreciated.
But: please follow the contribution guidelines written down in the CONTRIBUTING.md document.

License

PHP Oath Server Suite is under the MIT license.