├── src
├── Interfaces
│ └── PhoneVerificationCodeGrantUserInterface.php
├── PhoneVerificationCodeGrantServiceProvider.php
├── Bridge
│ └── UserRepository.php
└── PhoneVerificationCodeGrant.php
├── phpunit.xml.dist
├── composer.json
├── LICENSE.txt
├── README-zh-CN.md
└── README.md
/src/Interfaces/PhoneVerificationCodeGrantUserInterface.php:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 | ./tests/
16 |
17 |
18 |
19 |
20 | ./src/
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "qiutuleng/laravel-passport-phone-verification-code-grant",
3 | "description": "Resource owner phone verification code credentials grant for Laravel Passport",
4 | "license": "MIT",
5 | "authors": [
6 | {
7 | "name": "Qiu Tuleng",
8 | "email": "qiutuleng@gmail.com"
9 | }
10 | ],
11 | "require": {
12 | "php": ">=5.6.4",
13 | "laravel/passport": "*"
14 | },
15 | "autoload": {
16 | "psr-4": {
17 | "QiuTuleng\\PhoneVerificationCodeGrant\\": "src/"
18 | }
19 | },
20 | "extra": {
21 | "laravel": {
22 | "providers": [
23 | "QiuTuleng\\PhoneVerificationCodeGrant\\PhoneVerificationCodeGrantServiceProvider"
24 | ]
25 | }
26 | },
27 | "minimum-stability": "dev"
28 | }
29 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/src/PhoneVerificationCodeGrantServiceProvider.php:
--------------------------------------------------------------------------------
1 | app->resolving(AuthorizationServer::class, function (AuthorizationServer $server) {
21 | $server->enableGrantType($this->makeVerificationCodeGrant(), Passport::tokensExpireIn());
22 | });
23 | }
24 |
25 | protected function makeVerificationCodeGrant()
26 | {
27 | $grant = new PhoneVerificationCodeGrant(
28 | $this->app->make(UserRepository::class),
29 | $this->app->make(RefreshTokenRepository::class)
30 | );
31 |
32 | $grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn());
33 |
34 | return $grant;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Bridge/UserRepository.php:
--------------------------------------------------------------------------------
1 | findOrCreateForPassportVerifyCodeGrant($phoneNumber);
35 |
36 | if (!$user || !$user->validateForPassportVerifyCodeGrant($verificationCode)) {
37 | return;
38 | }
39 |
40 | return new User($user->getAuthIdentifier());
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/README-zh-CN.md:
--------------------------------------------------------------------------------
1 | # Laravel Passport Phone Verification Code Grant
2 |
3 | ## 介绍
4 |
5 | 基于Laravel Passport的手机验证码授权
6 |
7 | ## 安装
8 |
9 | 进入到你的项目目录,然后运行以下命令
10 |
11 | ```bash
12 | composer require qiutuleng/laravel-passport-phone-verification-code-grant
13 | ```
14 |
15 | ## 设置
16 |
17 | ### Laravel
18 |
19 | 如果你的Laravel版本大于等于`5.5`,服务提供者将会自动注册到程序中。
20 |
21 | 其他版本你需要把`\QiuTuleng\PhoneVerificationCodeGrant\PhoneVerificationCodeGrantServiceProvider::class`添加到`config/app.php`中的`providers`属性中。
22 |
23 | ```php
24 | 'providers' => [
25 | /*
26 | * Package Service Providers...
27 | */
28 | ...
29 | \QiuTuleng\PhoneVerificationCodeGrant\PhoneVerificationCodeGrantServiceProvider::class,
30 | ]
31 | ```
32 |
33 | ### Lumen
34 |
35 | 你可以在`app/Providers/AppServiceProvider.php`的`register`函数中添加以下代码注册服务提供者。
36 |
37 | ```php
38 | $app->register(\QiuTuleng\PhoneVerificationCodeGrant\PhoneVerificationCodeGrantServiceProvider::class);
39 | ```
40 |
41 | ## 如何使用?
42 |
43 | ### 配置
44 |
45 | 1. 你必须在 `User` Model中实现 `\QiuTuleng\PhoneVerificationCodeGrant\Interfaces\PhoneVerificationCodeGrantUserInterface` 接口。
46 |
47 | ```php
48 | $phoneNumber]);
76 |
77 | // If the phone number is not exists in users table, will be fail to authenticate.
78 | // return static::where('mobile', '=', $phoneNumber)->first();
79 | }
80 |
81 | /**
82 | * Check the verification code is valid.
83 | *
84 | * @param $verificationCode
85 | * @return boolean
86 | */
87 | public function validateForPassportVerifyCodeGrant($verificationCode)
88 | {
89 | // Check verification code is valid.
90 | // return \App\Code::where('mobile', $this->mobile)->where('code', '=', $verificationCode)->where('expired_at', '>', now()->toDatetimeString())->exists();
91 | return true;
92 | }
93 | ```
94 |
95 | 3. (可选) 你还可以在配置文件中重命名 `phone_number` 和 `verification_code` 字段:
96 |
97 | 为此,请在“config/passport.php”中添加字段,例如:
98 |
99 | ```php
100 | //...
101 | 'phone_verification' => [
102 | 'phone_number_request_key' => 'phone',
103 | 'verification_code_request_key' => 'verification_code',
104 | ],
105 | //...
106 | ```
107 |
108 |
109 | ### 请求Token
110 |
111 | 你可以使用`POST`方式访问`/oautn/token`接口来获取Token,具体请求参数参照以下代码。
112 |
113 | ```php
114 | $http = new GuzzleHttp\Client;
115 |
116 | $response = $http->post('http://your-app.com/oauth/token', [
117 | 'form_params' => [
118 | 'grant_type' => 'phone_verification_code',
119 | 'client_id' => 'client-id',
120 | 'client_secret' => 'client-secret',
121 | 'phone_number' => '+8613416292625',
122 | 'verification_code' => 927068,
123 | 'scope' => '',
124 | ],
125 | ]);
126 |
127 | return json_decode((string) $response->getBody(), true);
128 | ```
129 |
130 | ## 更多
131 |
132 | 你可以访问 [Laravel/Passport](https://laravel.com/docs/master/passport) 官方文档来了解更多信息。
133 |
134 | ## 贡献
135 |
136 | 你可以在此仓库中创建一个 [pull requests](https://github.com/qiutuleng/vue-router-modern/pulls) 。
137 |
138 | 期待你的想法或代码。
139 |
140 | ## Issues
141 |
142 | 如果你有任何问题,请在 [Issues](https://github.com/qiutuleng/vue-router-modern/issues) 中提出,我将会尽力为你解决。
143 |
--------------------------------------------------------------------------------
/src/PhoneVerificationCodeGrant.php:
--------------------------------------------------------------------------------
1 | setUserRepository($userRepository);
27 | $this->setRefreshTokenRepository($refreshTokenRepository);
28 |
29 | $this->refreshTokenTTL = new \DateInterval('P1M');
30 | }
31 |
32 | /**
33 | * Respond to an incoming request.
34 | *
35 | * @param ServerRequestInterface $request
36 | * @param ResponseTypeInterface $responseType
37 | * @param \DateInterval $accessTokenTTL
38 | *
39 | * @return ResponseTypeInterface
40 | */
41 | public function respondToAccessTokenRequest(
42 | ServerRequestInterface $request,
43 | ResponseTypeInterface $responseType,
44 | \DateInterval $accessTokenTTL
45 | )
46 | {
47 | // Validate request
48 | $client = $this->validateClient($request);
49 | $scopes = $this->validateScopes($this->getRequestParameter('scope', $request, $this->defaultScope));
50 | $user = $this->validateUser($request, $client);
51 |
52 | // Finalize the requested scopes
53 | $finalizedScopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $user->getIdentifier());
54 |
55 | // Issue and persist new tokens
56 | $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $user->getIdentifier(), $finalizedScopes);
57 | $refreshToken = $this->issueRefreshToken($accessToken);
58 |
59 | // Inject tokens into response
60 | $responseType->setAccessToken($accessToken);
61 | $responseType->setRefreshToken($refreshToken);
62 |
63 | return $responseType;
64 | }
65 |
66 | /**
67 | * @param ServerRequestInterface $request
68 | * @param ClientEntityInterface $client
69 | *
70 | * @throws OAuthServerException
71 | *
72 | * @return UserEntityInterface
73 | */
74 | protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client)
75 | {
76 | $requestPhoneNumberKey = config('passport.phone_verification.phone_number_request_key', 'phone_number');
77 | $phoneNumber = $this->getRequestParameter($requestPhoneNumberKey, $request);
78 | if (is_null($phoneNumber)) {
79 | throw OAuthServerException::invalidRequest($requestPhoneNumberKey);
80 | }
81 |
82 | $requestVerificationCode = config('passport.phone_verification.verification_code_request_key', 'verification_code');
83 | $verificationCode = $this->getRequestParameter($requestVerificationCode, $request);
84 | if (is_null($verificationCode)) {
85 | throw OAuthServerException::invalidRequest($requestVerificationCode);
86 | }
87 |
88 | $user = $this->userRepository->getUserEntityByUserCredentials(
89 | $phoneNumber,
90 | $verificationCode,
91 | $this->getIdentifier(),
92 | $client
93 | );
94 | if ($user instanceof UserEntityInterface === false) {
95 | $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));
96 |
97 | throw OAuthServerException::invalidCredentials();
98 | }
99 |
100 | return $user;
101 | }
102 |
103 | /**
104 | * Return the grant identifier that can be used in matching up requests.
105 | *
106 | * @return string
107 | */
108 | public function getIdentifier()
109 | {
110 | return 'phone_verification_code';
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Laravel Passport Phone Verification Code Grant
2 |
3 | ## Introduction
4 |
5 | Resource owner phone verification code credentials grant for Laravel Passport
6 |
7 | [中文文档 / Chinese document](./README-zh-CN.md)
8 |
9 | ## Install
10 |
11 | Under your working folder and run the command in terminal:
12 |
13 | ```bash
14 | composer require qiutuleng/laravel-passport-phone-verification-code-grant
15 | ```
16 |
17 | ## Setup
18 |
19 | ### Laravel
20 |
21 | If your laravel version is greater or equal to `5.5`, the service provider will be attached automatically.
22 |
23 | Other versions, you must needs add `\QiuTuleng\PhoneVerificationCodeGrant\PhoneVerificationCodeGrantServiceProvider::class` to the `providers` array in `config/app.php`:
24 |
25 | ```php
26 | 'providers' => [
27 | /*
28 | * Package Service Providers...
29 | */
30 | ...
31 | \QiuTuleng\PhoneVerificationCodeGrant\PhoneVerificationCodeGrantServiceProvider::class,
32 | ]
33 | ```
34 |
35 | ### Lumen
36 |
37 | ```php
38 | $app->register(\QiuTuleng\PhoneVerificationCodeGrant\PhoneVerificationCodeGrantServiceProvider::class);
39 | ```
40 |
41 | ## How to use?
42 |
43 | ### Configure
44 |
45 | 1. You must needs implement `\QiuTuleng\PhoneVerificationCodeGrant\Interfaces\PhoneVerificationCodeGrantUserInterface` interface in your `User` model.
46 |
47 | ```php
48 | $phoneNumber]);
76 |
77 | // If the phone number is not exists in users table, will be fail to authenticate.
78 | // return static::where('mobile', '=', $phoneNumber)->first();
79 | }
80 |
81 | /**
82 | * Check the verification code is valid.
83 | *
84 | * @param $verificationCode
85 | * @return boolean
86 | */
87 | public function validateForPassportVerifyCodeGrant($verificationCode)
88 | {
89 | // Check verification code is valid.
90 | // return \App\Code::where('mobile', $this->mobile)->where('code', '=', $verificationCode)->where('expired_at', '>', now()->toDatetimeString())->exists();
91 | return true;
92 | }
93 | ```
94 |
95 | 3. (Optional) Also you can rename `phone_number` and `verification_code` fields in config file:
96 |
97 | To do this, add keys in `config/passport.php`, example:
98 |
99 | ```php
100 | //...
101 | 'phone_verification' => [
102 | 'phone_number_request_key' => 'phone',
103 | 'verification_code_request_key' => 'verification_code',
104 | ],
105 | //...
106 | ```
107 |
108 |
109 | ### Request Tokens
110 |
111 | You may request an access token by issuing a `POST` request to the `/oauth/token` route with the user's phone number and verification code.
112 |
113 | ```php
114 | $http = new GuzzleHttp\Client;
115 |
116 | $response = $http->post('http://your-app.com/oauth/token', [
117 | 'form_params' => [
118 | 'grant_type' => 'phone_verification_code',
119 | 'client_id' => 'client-id',
120 | 'client_secret' => 'client-secret',
121 | 'phone_number' => '+8613416292625',
122 | 'verification_code' => 927068,
123 | 'scope' => '',
124 | ],
125 | ]);
126 |
127 | return json_decode((string) $response->getBody(), true);
128 | ```
129 |
130 | ## More
131 |
132 | You can check out the [Laravel/Passport](https://laravel.com/docs/master/passport) official documentation to learn more
133 |
134 | ## Contributing
135 |
136 | You can create a [pull requests](https://github.com/qiutuleng/vue-router-modern/pulls) to this repository.
137 |
138 | Welcome your ideas or code.
139 |
140 | ## Issues
141 |
142 | If you have any questions, please ask your question in the [Issues](https://github.com/qiutuleng/vue-router-modern/issues) and I will try my best to help you.
143 |
--------------------------------------------------------------------------------