{"id":13549299,"url":"https://github.com/chillerlan/php-authenticator","last_synced_at":"2026-04-01T20:34:22.944Z","repository":{"id":62501706,"uuid":"47436867","full_name":"chillerlan/php-authenticator","owner":"chillerlan","description":"A generator for counter- and time based authentication codes (RFC-4226/RFC-6238, Google Authenticator).","archived":false,"fork":false,"pushed_at":"2026-03-30T20:49:29.000Z","size":333,"stargazers_count":56,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-03-30T22:23:47.359Z","etag":null,"topics":["2-factor","2fa","authenticator","google-authenticator","hotp","php","php-library","php7","php8","rfc4226","rfc6238","steamguard","totp"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chillerlan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"ko_fi":"codemasher","custom":"https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4"}},"created_at":"2015-12-05T01:15:46.000Z","updated_at":"2026-03-30T20:49:32.000Z","dependencies_parsed_at":"2024-07-17T03:08:07.211Z","dependency_job_id":null,"html_url":"https://github.com/chillerlan/php-authenticator","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/chillerlan/php-authenticator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chillerlan%2Fphp-authenticator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chillerlan%2Fphp-authenticator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chillerlan%2Fphp-authenticator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chillerlan%2Fphp-authenticator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chillerlan","download_url":"https://codeload.github.com/chillerlan/php-authenticator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chillerlan%2Fphp-authenticator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31291702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["2-factor","2fa","authenticator","google-authenticator","hotp","php","php-library","php7","php8","rfc4226","rfc6238","steamguard","totp"],"created_at":"2024-08-01T12:01:20.382Z","updated_at":"2026-04-01T20:34:22.939Z","avatar_url":"https://github.com/chillerlan.png","language":"PHP","readme":"# chillerlan/php-authenticator\n\nA generator for counter based ([RFC 4226](https://tools.ietf.org/html/rfc4226)) and time based ([RFC 6238](https://tools.ietf.org/html/rfc6238)) one time passwords (OTP). (a.k.a. Yet Another Google Authenticator Implementation!)\n\n[![PHP Version Support][php-badge]][php]\n[![version][packagist-badge]][packagist]\n[![License][license-badge]][license]\n[![GitHub actions workflow][gh-action-badge]][gh-action]\n[![Coverage][coverage-badge]][coverage]\n[![Codacy][codacy-badge]][codacy]\n[![Downloads][downloads-badge]][downloads]\n\n[php-badge]: https://img.shields.io/packagist/php-v/chillerlan/php-authenticator?logo=php\u0026color=8892BF\u0026logoColor=fff\n[php]: https://www.php.net/supported-versions.php\n[packagist-badge]: https://img.shields.io/packagist/v/chillerlan/php-authenticator.svg?logo=packagist\u0026logoColor=fff\n[packagist]: https://packagist.org/packages/chillerlan/php-authenticator\n[downloads-badge]: https://img.shields.io/packagist/dt/chillerlan/php-authenticator.svg?logo=packagist\u0026logoColor=fff\n[downloads]: https://packagist.org/packages/chillerlan/php-authenticator/stats\n[license-badge]: https://img.shields.io/github/license/chillerlan/php-authenticator.svg\n[license]: https://github.com/chillerlan/php-authenticator/blob/main/LICENSE\n[gh-action-badge]: https://img.shields.io/github/actions/workflow/status/chillerlan/php-authenticator/ci.yml?branch=main\u0026logo=github\u0026logoColor=fff\n[gh-action]: https://github.com/chillerlan/php-authenticator/actions?query=branch%3Amain\n[coverage-badge]: https://img.shields.io/codecov/c/gh/chillerlan/php-authenticator/main?logo=codecov\u0026logoColor=fff\n[coverage]: https://app.codecov.io/github/chillerlan/php-authenticator/tree/main\n[codacy-badge]: https://img.shields.io/codacy/grade/a2793225b448495c9659f27f7f52380a/main?logo=codacy\u0026logoColor=fff\n[codacy]: https://www.codacy.com/gh/chillerlan/php-authenticator/dashboard?branch=main\n\n# Documentation\n## Requirements\n- PHP 8.4+\n  - [`ext-curl`](https://www.php.net/manual/book.curl) for Steam Guard server time synchronization\n  - [`ext-sodium`](https://www.php.net/manual/book.sodium) for constant time implementations of base64 encode/decode and hex2bin/bin2hex\n    ([`paragonie/constant_time_encoding`](https://github.com/paragonie/constant_time_encoding) is used as fallback)\n\n## Installation\n**requires [composer](https://getcomposer.org)**\n\nvia terminal: `composer require chillerlan/php-authenticator`\n\n**composer.json**\n```json\n{\n\t\"require\": {\n\t\t\"php\": \"^8.4\",\n\t\t\"chillerlan/php-authenticator\": \"dev-main\"\n\t}\n}\n```\nNote: replace `dev-main` with a [version constraint](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints), e.g. `^5.0` - see [releases](https://github.com/chillerlan/php-authenticator/releases) for valid versions\n\nProfit!\n\n## Usage\n### Create a secret\nThe secret is usually being created once during the activation process in a user control panel.\nSo all you need to do there is to display it to the user in a convenient way -\nas a text string and QR code for example - and save it somewhere with the user data.\n```php\nuse chillerlan\\Authenticator\\{Authenticator, AuthenticatorOptions};\n\n$options = new AuthenticatorOptions;\n$options-\u003esecret_length = 32;\n\n$authenticator = new Authenticator($options);\n// create a secret (stored somewhere in a *safe* place on the server. safe... hahaha jk)\n$secret = $authenticator-\u003ecreateSecret();\n// you can also specify the length of the secret key, which overrides the options setting\n$secret = $authenticator-\u003ecreateSecret(20);\n// set an existing secret\n$authenticator-\u003esetSecret($secret);\n```\n\nA secret created with `Authenticator::createSecret()` will also be stored internally,\nso that you don't need to provide the secret you just created on follow-up operations with the current instance.\n\n### Verify a one time code\nNow during the login process - after the user has successfully entered their credentials - you would\nask them for a one time code to check it against the secret from your user database.\n\n```php\n// verify the code\nif($authenticator-\u003everify($otp)){\n\t// that's it - 2FA has never been easier! :D\n}\n```\n\n#### time based (TOTP)\nVerify adjacent codes\n```php\n// try the first adjacent\n$authenticator-\u003everify($otp, time() - $options-\u003eperiod); // -\u003e true\n// try the second adjacent, default is 1\n$authenticator-\u003everify($otp, time() + 2 * $options-\u003eperiod); // -\u003e false\n// allow 2 adjacent codes\n$options-\u003eadjacent = 2;\n$authenticator-\u003everify($otp, time() + 2 * $options-\u003eperiod); // -\u003e true\n```\n\n#### counter based (HOTP)\n```php\n// switch mode to HOTP\n$options-\u003emode = AuthenticatorInterface::HOTP;\n// user sends the OTP for code #42, which is equivalent to\n$otp = $authenticator-\u003ecode(42); // -\u003e 123456\n// verify [123456, 42]\n$authenticator-\u003everify($otp, $counterValueFromUserDatabase) // -\u003e true\n```\n\n### URI creation\nIn order to display a QR code for a mobile authenticator you'll need an `otpauth://` URI, which can be created using the following method.\n- `$label` should be something that identifies the account to which the secret belongs\n- `$issuer` is the name of your website or company for example, so that the user is able to identify multiple accounts.\n```php\n$uri = $authenticator-\u003egetUri($label, $issuer);\n\n// -\u003e otpauth://totp/my%20label?secret=NKSOQG7UKKID4IXW\u0026issuer=chillerlan.net\u0026digits=6\u0026period=30\u0026algorithm=SHA1\n```\n\n#### Notes\nKeep in mind that several URI settings are not (yet) recognized by all authenticators. Check [the Google Authenticator wiki](https://github.com/google/google-authenticator/wiki/Key-Uri-Format#parameters) for more info.\n\n```php\n// code length, currently 6 or 8\n$options-\u003edigits = 8;\n// valid period between 15 and 60 seconds\n$options-\u003eperiod = 45;\n// set the HMAC hash algorithm\n$options-\u003ealgorithm = AuthenticatorInterface::ALGO_SHA512;\n```\n\n## API\n### `Authenticator`\n| method                                                                                      | return          | description                                                      |\n|---------------------------------------------------------------------------------------------|-----------------|------------------------------------------------------------------|\n| `__construct(SettingsContainerInterface $options = null, string $secret = null)`            | -               |                                                                  |\n| `setOptions(SettingsContainerInterface $options)`                                           | `Authenticator` | called internally by `__construct()`                             |\n| `setSecret(string $secret)`                                                                 | `Authenticator` | called internally by `__construct()`                             |\n| `getSecret()`                                                                               | `string`        |                                                                  |\n| `createSecret(int $length = null)`                                                          | `string`        | `$length` overrides `AuthenticatorOptions` setting               |\n| `code(int $data = null)`                                                                    | `string`        | `$data` may be a UNIX timestamp (TOTP) or a counter value (HOTP) |\n| `verify(string $otp, int $data = null)`                                                     | `bool`          | for `$data` see `Authenticator::code()`                          |\n| `getUri(string $label, string $issuer, int $hotpCounter = null, bool $omitSettings = null)` | `string`        |                                                                  |\n\n### `AuthenticatorOptions`\n#### Properties\n| property            | type     | default | allowed                                | description                                                                     |\n|---------------------|----------|---------|----------------------------------------|---------------------------------------------------------------------------------|\n| `$digits`           | `int`    | 6       | 6 or 8                                 | auth code length                                                                |\n| `$period`           | `int`    | 30      | 15 - 60                                | validation period (seconds)                                                     |\n| `$secret_length`    | `int`    | 20      | \u0026gt;= 16                               | length of the secret phrase (bytes, unencoded binary)                           |\n| `$algorithm`        | `string` | `SHA1`  | `SHA1`, `SHA256` or `SHA512`           | HMAC hash algorithm, see `AuthenticatorInterface::HASH_ALGOS`                   |\n| `$mode`             | `string` | `totp`  | `totp`, `hotp`, `battlenet` or `steam` | authenticator mode: time- or counter based, see `AuthenticatorInterface::MODES` |\n| `$adjacent`         | `int`    | 1       | \u0026gt;= 0                                | number of allowed adjacent codes                                                |\n| `$time_offset`      | `int`    | 0       | *                                      | fixed time offset that will be added to the current time value                  |\n| `$useLocalTime`     | `bool`   | true    | *                                      | whether to use local time or request server time                                |\n| `$forceTimeRefresh` | `bool`   | false   | *                                      | whether to force refreshing server time on each call                            |\n\n### `AuthenticatorInterface`\n#### Methods\n| method                                            | return                   | description |\n|---------------------------------------------------|--------------------------|-------------|\n| `setOptions(SettingsContainerInterface $options)` | `AuthenticatorInterface` |             |\n| `setSecret(string $encodedSecret)`                | `AuthenticatorInterface` |             |\n| `getSecret()`                                     | `string`                 |             |\n| `createSecret(int $length = null)`                | `string`                 |             |\n| `getServertime()`                                 | `int`                    |             |\n| `getCounter(int $data = null)`                    | `int`                    | internal    |\n| `getHMAC(int $counter)`                           | `string`                 | internal    |\n| `getCode(string $hmac)`                           | `int`                    | internal    |\n| `getOTP(int $code)`                               | `string`                 | internal    |\n| `code(int $data = null)`                          | `string`                 |             |\n| `verify(string $otp, int $data = null)`           | `bool`                   |             |\n\n#### Constants\n| constant      | type     | description                       |\n|---------------|----------|-----------------------------------|\n| `TOTP`        | `string` |                                   |\n| `HOTP`        | `string` |                                   |\n| `STEAM_GUARD` | `string` |                                   |\n| `ALGO_SHA1`   | `string` |                                   |\n| `ALGO_SHA256` | `string` |                                   |\n| `ALGO_SHA512` | `string` |                                   |\n| `MODES`       | `array`  | map of mode -\u003e classname          |\n| `HASH_ALGOS`  | `array`  | list of available hash algorithms |\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://twofactorauth.org\"\u003e\n    \u003cimg alt=\"2FA ALL THE THINGS!\" src=\"https://raw.githubusercontent.com/chillerlan/php-authenticator/main/.github/images/2fa-all-the-things.jpg\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n","funding_links":["https://ko-fi.com/codemasher","https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4"],"categories":["PHP"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchillerlan%2Fphp-authenticator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchillerlan%2Fphp-authenticator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchillerlan%2Fphp-authenticator/lists"}