{"id":15813553,"url":"https://github.com/ybelenko/oauth2_email_grant","last_synced_at":"2025-04-01T01:44:07.383Z","repository":{"id":49809249,"uuid":"518174123","full_name":"ybelenko/oauth2_email_grant","owner":"ybelenko","description":"Custom OAuth2 Email Grant compliant with league/oauth2-server package.","archived":false,"fork":false,"pushed_at":"2022-11-22T23:37:45.000Z","size":19,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-06T04:02:55.152Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/ybelenko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-26T18:26:19.000Z","updated_at":"2022-07-26T18:31:00.000Z","dependencies_parsed_at":"2022-09-14T11:11:35.141Z","dependency_job_id":null,"html_url":"https://github.com/ybelenko/oauth2_email_grant","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ybelenko%2Foauth2_email_grant","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ybelenko%2Foauth2_email_grant/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ybelenko%2Foauth2_email_grant/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ybelenko%2Foauth2_email_grant/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ybelenko","download_url":"https://codeload.github.com/ybelenko/oauth2_email_grant/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246569006,"owners_count":20798341,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-10-05T04:03:04.105Z","updated_at":"2025-04-01T01:44:07.366Z","avatar_url":"https://github.com/ybelenko.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OAuth 2.0 Email Grant(Custom)\n\n[![Tests](https://github.com/ybelenko/oauth2_email_grant/actions/workflows/main.yml/badge.svg)](https://github.com/ybelenko/oauth2_email_grant/actions/workflows/main.yml)\n[![Coverage Status](https://coveralls.io/repos/github/ybelenko/oauth2_email_grant/badge.svg?branch=main)](https://coveralls.io/github/ybelenko/oauth2_email_grant?branch=main)\n\n## Requirements\n* PHP 8.x\n\n## Important Notice\n\u003e If you decide to extend some of the classes make sure you **DON'T expose access token** somewhere.\n\u003e Check that you DON'T `echo/print/var_dump` access token or instance of it.\n\n## Installation via [Composer](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos)\nRun in command line:\n```console\ncomposer require ybelenko/oauth2_email_grant\n```\n\n## Basic Usage\n\nAssuming you already have [PHP League OAuth 2.0 Server](https://oauth2.thephpleague.com) installed and configured.\n\n```php\nuse League\\OAuth2\\Server\\Entities\\AccessTokenEntityInterface;\nuse League\\OAuth2\\Server\\Entities\\ClientEntityInterface;\nuse League\\OAuth2\\Server\\Entities\\UserEntityInterface;\nuse Ybelenko\\OAuth2\\Server\\Grant\\CustomEmailGrant;\n\n// if you want to use class method instead of anonymous functions\n// do $onAccessToken = \\Closure::fromCallable([$this, 'onAccessToken'])\n// or when method is static $onAccessToken = \\Closure::fromCallable([UserClass::class, 'onAccessToken'])\n\n$grant = new CustomEmailGrant(\n    $userRepository, // repository used in your oauth2 server implementation\n    static function (\n        string $email,\n        AccessTokenEntityInterface $accessToken,\n        ClientEntityInterface $client, \n        UserEntityInterface $user,\n        array $scopes\n    ) {\n        // send access token to user via email\n        // or do something else\n    },\n    static function (string $email) {\n        // validate email the way you want\n        // throw an exception or return true|false\n        // everything beside true return will stop token creation\n    }\n);\n\n// all other repos should be added from auth server automatically\n// right after you call\n$server-\u003eenableGrantType($grant, new \\DateInterval('PT1H'));\n```\n\nthen in your `UserRepositoryInterface` implementation handle new custom grant:\n```php\n/**\n * {@inheritdoc}\n */\npublic function getUserEntityByUserCredentials(\n    $username,\n    $password,\n    $grantType,\n    ClientEntityInterface $clientEntity\n) {\n    if ($grantType === 'custom_email') {\n        // password is empty string now\n        // just for readability\n        $email = $username;\n        // if user with provided email exists return new entity\n        // otherwise return null\n        // don't need to check password since we send token\n        // to provided email, works like common account recover flow\n        $user = new FakeUserEntity();\n        $user-\u003esetIdentifier($email);\n        return $user;\n    }\n\n    // handle other grants also check password from now\n\n    return null;\n}\n```\n\nTo use new grant user can send POST with a small change(`grant_type` changed to `custom_email`, new field `email`):\n```json\n{\n    \"grant_type\": \"custom_email\",\n    \"client_id\": \"client\",\n    \"client_secret\": \"secret\",\n    \"email\": \"johndoe@example.dev\",\n    \"scope\": \"foo baz bar\"\n}\n```\nit's also possible to send `client_id` and `client_secret` as `\"Authorization: Basic {base64_encode($clientId . ':' . $clientSecret)}\"` HTTP header.\n\nInstead of usual access token response user receives payload like:\n```json\n{\n    \"message\": \"Mail with recover link has been sent to provided address\",\n    \"expires_in\": 3600\n}\n```\n\n## Author\n[Yuriy Belenko](https://github.com/ybelenko)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fybelenko%2Foauth2_email_grant","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fybelenko%2Foauth2_email_grant","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fybelenko%2Foauth2_email_grant/lists"}