Add OAuth client
This commit is contained in:
parent
25a7134d63
commit
91fbb42431
@ -11,6 +11,7 @@ use App\Rules\Captcha;
|
||||
use Auth;
|
||||
use Cache;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
use Mail;
|
||||
use Session;
|
||||
use URL;
|
||||
@ -301,4 +302,44 @@ class AuthController extends Controller
|
||||
{
|
||||
return json(['token' => Auth::guard('jwt')->refresh()]);
|
||||
}
|
||||
|
||||
public function oauthLogin($driver)
|
||||
{
|
||||
return Socialite::driver($driver)->redirect();
|
||||
}
|
||||
|
||||
public function oauthCallback($driver)
|
||||
{
|
||||
$remoteUser = Socialite::driver($driver)->user();
|
||||
|
||||
$email = $remoteUser->email;
|
||||
if (empty($email)) {
|
||||
abort(500, 'Unsupported OAuth Server which does not provide email.');
|
||||
}
|
||||
|
||||
$user = User::where('email', $email)->first();
|
||||
if ($user) {
|
||||
event(new Events\UserLoggedIn($user));
|
||||
|
||||
Auth::login($user);
|
||||
} else {
|
||||
$user = new User();
|
||||
$user->email = $email;
|
||||
$user->nickname = $remoteUser->nickname ?? $remoteUser->name ?? $email;
|
||||
$user->score = option('user_initial_score');
|
||||
$user->avatar = 0;
|
||||
$user->password = '';
|
||||
$user->ip = get_client_ip();
|
||||
$user->permission = User::NORMAL;
|
||||
$user->register_at = get_datetime_string();
|
||||
$user->last_sign_at = get_datetime_string(time() - 86400);
|
||||
|
||||
$user->save();
|
||||
event(new Events\UserRegistered($user));
|
||||
|
||||
Auth::login($user);
|
||||
}
|
||||
|
||||
return redirect('/user');
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,9 @@ class AppServiceProvider extends ServiceProvider
|
||||
$this->app->singleton('parsedown', \Parsedown::class);
|
||||
$this->app->singleton(\App\Services\Webpack::class);
|
||||
$this->app->singleton(\App\Services\Filter::class);
|
||||
$this->app->singleton('oauth.providers', function () {
|
||||
return new \Illuminate\Support\Collection();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,5 +83,9 @@ class ViewServiceProvider extends ServiceProvider
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
View::composer('auth.oauth', function ($view) {
|
||||
$view->with('providers', resolve('oauth.providers'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -4,45 +4,46 @@
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=7.2.0",
|
||||
"ext-zip": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-pdo": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-json": "*",
|
||||
"predis/predis": "~1.0",
|
||||
"doctrine/inflector": "1.1.0",
|
||||
"laravel/framework": "6.*",
|
||||
"nesbot/carbon": "^2.0",
|
||||
"ext-zip": "*",
|
||||
"composer/ca-bundle": "^1.2",
|
||||
"composer/semver": "^1.4",
|
||||
"doctrine/dbal": "^2.9",
|
||||
"doctrine/inflector": "1.1.0",
|
||||
"facade/ignition": "^1.4",
|
||||
"gregwar/captcha": "1.*",
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
"doctrine/dbal": "^2.9",
|
||||
"tymon/jwt-auth": "dev-develop",
|
||||
"laravel/framework": "6.*",
|
||||
"laravel/passport": "^7.3",
|
||||
"composer/ca-bundle": "^1.2",
|
||||
"facade/ignition": "^1.4",
|
||||
"nesbot/carbon": "^2.0",
|
||||
"predis/predis": "~1.0",
|
||||
"rcrowe/twigbridge": "^0.11.1",
|
||||
"socialiteproviders/manager": "^3.4",
|
||||
"spatie/laravel-translation-loader": "^2.4",
|
||||
"symfony/process": "^4.4",
|
||||
"symfony/yaml": "^4.3",
|
||||
"twig/twig": "^2.11",
|
||||
"rcrowe/twigbridge": "^0.11.1"
|
||||
"tymon/jwt-auth": "dev-develop"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-debugbar": "^3.2",
|
||||
"barryvdh/laravel-ide-helper": "^2.6",
|
||||
"beyondcode/laravel-dump-server": "^1.2",
|
||||
"fzaninotto/faker": "~1.8",
|
||||
"laravel/browser-kit-testing": "~5.0",
|
||||
"laravel/tinker": "^1.0",
|
||||
"mockery/mockery": "^1.2.2",
|
||||
"phpdocumentor/reflection-docblock": "3.2.2",
|
||||
"phpunit/phpunit": "~8.0",
|
||||
"laravel/browser-kit-testing": "~5.0",
|
||||
"laravel/tinker": "^1.0",
|
||||
"barryvdh/laravel-debugbar": "^3.2",
|
||||
"beyondcode/laravel-dump-server": "^1.2",
|
||||
"symfony/dom-crawler": "^4.3",
|
||||
"symfony/css-selector": "^4.3",
|
||||
"barryvdh/laravel-ide-helper": "^2.6"
|
||||
"symfony/dom-crawler": "^4.3"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
@ -72,6 +73,13 @@
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"dont-discover": [
|
||||
"laravel/socialite"
|
||||
]
|
||||
}
|
||||
},
|
||||
"repositories": {
|
||||
"packagist": {
|
||||
"type": "composer",
|
||||
|
206
composer.lock
generated
206
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "5cc00172e30620b65fb629cecea98e5b",
|
||||
"content-hash": "1d98f570b7b67b1ecd3b72dfcec58e7b",
|
||||
"packages": [
|
||||
{
|
||||
"name": "composer/ca-bundle",
|
||||
@ -1459,6 +1459,70 @@
|
||||
],
|
||||
"time": "2019-10-08T16:45:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/socialite",
|
||||
"version": "v4.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/socialite.git",
|
||||
"reference": "2d670d5b100ef2dc72dc578126b2b97985791f52"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/socialite/zipball/2d670d5b100ef2dc72dc578126b2b97985791f52",
|
||||
"reference": "2d670d5b100ef2dc72dc578126b2b97985791f52",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/guzzle": "~6.0",
|
||||
"illuminate/http": "~5.7.0|~5.8.0|^6.0|^7.0",
|
||||
"illuminate/support": "~5.7.0|~5.8.0|^6.0|^7.0",
|
||||
"league/oauth1-client": "~1.0",
|
||||
"php": "^7.1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"illuminate/contracts": "~5.7.0|~5.8.0|^6.0|^7.0",
|
||||
"mockery/mockery": "^1.0",
|
||||
"phpunit/phpunit": "^7.0|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.0-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Laravel\\Socialite\\SocialiteServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Socialite": "Laravel\\Socialite\\Facades\\Socialite"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\Socialite\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.",
|
||||
"homepage": "https://laravel.com",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"oauth"
|
||||
],
|
||||
"time": "2019-11-26T17:39:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lcobucci/jwt",
|
||||
"version": "3.3.1",
|
||||
@ -1648,6 +1712,69 @@
|
||||
],
|
||||
"time": "2019-12-08T21:46:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/oauth1-client",
|
||||
"version": "1.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/oauth1-client.git",
|
||||
"reference": "fca5f160650cb74d23fc11aa570dd61f86dcf647"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/fca5f160650cb74d23fc11aa570dd61f86dcf647",
|
||||
"reference": "fca5f160650cb74d23fc11aa570dd61f86dcf647",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6.0",
|
||||
"php": ">=5.5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^0.9",
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"squizlabs/php_codesniffer": "^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\OAuth1\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Corlett",
|
||||
"email": "bencorlett@me.com",
|
||||
"homepage": "http://www.webcomm.com.au",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "OAuth 1.0 Client Library",
|
||||
"keywords": [
|
||||
"Authentication",
|
||||
"SSO",
|
||||
"authorization",
|
||||
"bitbucket",
|
||||
"identity",
|
||||
"idp",
|
||||
"oauth",
|
||||
"oauth1",
|
||||
"single sign on",
|
||||
"trello",
|
||||
"tumblr",
|
||||
"twitter"
|
||||
],
|
||||
"time": "2016-08-17T00:36:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/oauth2-server",
|
||||
"version": "7.4.0",
|
||||
@ -2047,16 +2174,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpoption/phpoption",
|
||||
"version": "1.7.0",
|
||||
"version": "1.7.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/schmittjoh/php-option.git",
|
||||
"reference": "318ad673ba36e53e10ca510aec1c54b4f2a5f2ae"
|
||||
"reference": "100a25207566930efd926cf205542946aa692e01"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/318ad673ba36e53e10ca510aec1c54b4f2a5f2ae",
|
||||
"reference": "318ad673ba36e53e10ca510aec1c54b4f2a5f2ae",
|
||||
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/100a25207566930efd926cf205542946aa692e01",
|
||||
"reference": "100a25207566930efd926cf205542946aa692e01",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2098,7 +2225,7 @@
|
||||
"php",
|
||||
"type"
|
||||
],
|
||||
"time": "2019-12-13T00:10:22+00:00"
|
||||
"time": "2019-12-14T13:46:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
@ -2755,6 +2882,63 @@
|
||||
],
|
||||
"time": "2019-12-13T21:54:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "socialiteproviders/manager",
|
||||
"version": "v3.4.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/SocialiteProviders/Manager.git",
|
||||
"reference": "09903d33429f9f6c0da32c545c036a3e18964bbf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/09903d33429f9f6c0da32c545c036a3e18964bbf",
|
||||
"reference": "09903d33429f9f6c0da32c545c036a3e18964bbf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "~5.4|~5.7.0|~5.8.0|^6.0",
|
||||
"laravel/socialite": "~3.0|~4.0",
|
||||
"php": "^5.6 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^0.9.4",
|
||||
"phpunit/phpunit": "^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"SocialiteProviders\\Manager\\ServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"SocialiteProviders\\Manager\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andy Wendt",
|
||||
"email": "andy@awendt.com"
|
||||
},
|
||||
{
|
||||
"name": "Anton Komarev",
|
||||
"email": "a.komarev@cybercog.su"
|
||||
},
|
||||
{
|
||||
"name": "Miguel Piedrafita",
|
||||
"email": "soy@miguelpiedrafita.com"
|
||||
}
|
||||
],
|
||||
"description": "Easily add new or override built-in providers in Laravel Socialite.",
|
||||
"time": "2019-09-25T06:06:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-translation-loader",
|
||||
"version": "2.4.0",
|
||||
@ -7557,15 +7741,15 @@
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.2.0",
|
||||
"ext-zip": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-pdo": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-json": "*"
|
||||
"ext-zip": "*"
|
||||
},
|
||||
"platform-dev": []
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ rotation: Rotation
|
||||
pause: Pause
|
||||
reset: Reset
|
||||
|
||||
more: More
|
||||
submit: Submit
|
||||
cancel: Cancel
|
||||
yes: Yes
|
||||
|
@ -15,6 +15,7 @@
|
||||
- Added badge "STAFF" for administrators.
|
||||
- Added badges at texture detail page.
|
||||
- Added FAQ link at error page.
|
||||
- Added login with 3rd-party services.
|
||||
|
||||
## Tweaked
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
- 增加管理员专有的「STAFF」badge
|
||||
- 在材质详情页中显示上传者的 badge
|
||||
- 在错误页面增加指向 FAQ 页面的链接
|
||||
- 第三方登录
|
||||
|
||||
## 调整
|
||||
|
||||
|
@ -11,7 +11,10 @@
|
||||
{% endif %}
|
||||
<form></form>
|
||||
<br>
|
||||
<a href="{{ url('auth/register') }}">{{ trans('auth.register-link') }}</a>
|
||||
{{ include('auth.oauth') }}
|
||||
<div>
|
||||
<a href="{{ url('auth/register') }}">{{ trans('auth.register-link') }}</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block before_foot %}
|
||||
|
9
resources/views/auth/oauth.twig
Normal file
9
resources/views/auth/oauth.twig
Normal file
@ -0,0 +1,9 @@
|
||||
<div class="mb-3 text-center">
|
||||
<div class="mb-1">- {{ trans('general.more') }} -</div>
|
||||
{% for name, provider in providers %}
|
||||
<a href="{{ url("/auth/login/#{name}") }}" class="btn btn-block bg-light border-secondary">
|
||||
<img src="{{ url("/app/brand-icons/#{provider.icon}.svg") }}" width="20">
|
||||
{{ provider.displayName }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
@ -7,6 +7,7 @@
|
||||
{{ trans('auth.register.message', {sitename: site_name}) }}
|
||||
</p>
|
||||
<form></form>
|
||||
{{ include('auth.oauth') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block before_foot %}
|
||||
|
@ -27,6 +27,9 @@ Route::group(['prefix' => 'auth'], function () {
|
||||
Route::get('/register', 'AuthController@register');
|
||||
Route::get('/forgot', 'AuthController@forgot');
|
||||
Route::get('/reset/{uid}', 'AuthController@reset')->name('auth.reset')->middleware('signed');
|
||||
|
||||
Route::get('/login/{driver}', 'AuthController@oauthLogin');
|
||||
Route::get('/login/{driver}/callback', 'AuthController@oauthCallback');
|
||||
});
|
||||
|
||||
Route::any('/logout', 'AuthController@logout');
|
||||
|
@ -13,6 +13,9 @@ if (Test-Path ./public/app) {
|
||||
# Run webpack
|
||||
yarn build
|
||||
|
||||
New-Item -ItemType Directory ./public/app/brand-icons
|
||||
Copy-Item -Path ./node_modules/@fortawesome/fontawesome-free/svgs/brands/*.svg -Destination ./public/app/brand-icons
|
||||
|
||||
if ($Simple) {
|
||||
exit
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Socialite\AbstractUser;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
|
||||
class AuthControllerTest extends TestCase
|
||||
{
|
||||
@ -606,4 +608,80 @@ class AuthControllerTest extends TestCase
|
||||
])->decodeResponseJson('token');
|
||||
$this->assertTrue(is_string($token));
|
||||
}
|
||||
|
||||
public function testOAuthLogin()
|
||||
{
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('github')
|
||||
->once()
|
||||
->andReturn(new class() {
|
||||
public function redirect()
|
||||
{
|
||||
return redirect('/');
|
||||
}
|
||||
});
|
||||
|
||||
$this->get('/auth/login/github')->assertRedirect();
|
||||
}
|
||||
|
||||
public function testOAuthCallback()
|
||||
{
|
||||
Event::fake();
|
||||
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('github')
|
||||
->times(3)
|
||||
->andReturn(
|
||||
new class() {
|
||||
public function user()
|
||||
{
|
||||
return new class() extends AbstractUser {
|
||||
};
|
||||
}
|
||||
},
|
||||
new class() {
|
||||
public function user()
|
||||
{
|
||||
return new class() extends AbstractUser {
|
||||
public $email = 'a@b.c';
|
||||
|
||||
public $nickname = 'abc';
|
||||
};
|
||||
}
|
||||
},
|
||||
new class() {
|
||||
public function user()
|
||||
{
|
||||
return new class() extends AbstractUser {
|
||||
public $email = 'a@b.c';
|
||||
|
||||
public $nickname = 'abc';
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$this->get('/auth/login/github/callback')
|
||||
->assertStatus(500)
|
||||
->assertSee('Unsupported');
|
||||
|
||||
$this->get('/auth/login/github/callback')->assertRedirect('/user');
|
||||
$this->assertDatabaseHas('users', [
|
||||
'email' => 'a@b.c',
|
||||
'nickname' => 'abc',
|
||||
'score' => option('user_initial_score'),
|
||||
'avatar' => 0,
|
||||
'ip' => '127.0.0.1',
|
||||
'permission' => User::NORMAL,
|
||||
]);
|
||||
Event::assertDispatched(Events\UserRegistered::class);
|
||||
$this->assertAuthenticated();
|
||||
|
||||
auth()->logout();
|
||||
$this->assertGuest();
|
||||
|
||||
$this->get('/auth/login/github/callback')->assertRedirect('/user');
|
||||
Event::assertDispatched(Events\UserLoggedIn::class);
|
||||
$this->assertAuthenticated();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user