RemoteAuthController.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\RemoteAuth;
  4. use App\Services\Account\RemoteAuthService;
  5. use App\Services\EmailService;
  6. use App\Services\MediaStorageService;
  7. use App\User;
  8. use App\Util\ActivityPub\Helpers;
  9. use App\Util\Lexer\RestrictedNames;
  10. use Illuminate\Auth\Events\Registered;
  11. use Illuminate\Http\Request;
  12. use Illuminate\Support\Facades\Auth;
  13. use Illuminate\Support\Facades\Hash;
  14. use Illuminate\Support\Str;
  15. use App\Rules\PixelfedUsername;
  16. use InvalidArgumentException;
  17. use Purify;
  18. class RemoteAuthController extends Controller
  19. {
  20. public function start(Request $request)
  21. {
  22. abort_unless((
  23. config_cache('pixelfed.open_registration') &&
  24. config('remote-auth.mastodon.enabled')
  25. ) || (
  26. config('remote-auth.mastodon.ignore_closed_state') &&
  27. config('remote-auth.mastodon.enabled')
  28. ), 404);
  29. if ($request->user()) {
  30. return redirect('/');
  31. }
  32. return view('auth.remote.start');
  33. }
  34. public function startRedirect(Request $request)
  35. {
  36. return redirect('/login');
  37. }
  38. public function getAuthDomains(Request $request)
  39. {
  40. abort_unless((
  41. config_cache('pixelfed.open_registration') &&
  42. config('remote-auth.mastodon.enabled')
  43. ) || (
  44. config('remote-auth.mastodon.ignore_closed_state') &&
  45. config('remote-auth.mastodon.enabled')
  46. ), 404);
  47. if (config('remote-auth.mastodon.domains.only_custom')) {
  48. $res = config('remote-auth.mastodon.domains.custom');
  49. if (! $res || ! strlen($res)) {
  50. return [];
  51. }
  52. $res = explode(',', $res);
  53. return response()->json($res);
  54. }
  55. if (config('remote-auth.mastodon.domains.custom') &&
  56. ! config('remote-auth.mastodon.domains.only_default') &&
  57. strlen(config('remote-auth.mastodon.domains.custom')) > 3 &&
  58. strpos(config('remote-auth.mastodon.domains.custom'), '.') > -1
  59. ) {
  60. $res = config('remote-auth.mastodon.domains.custom');
  61. if (! $res || ! strlen($res)) {
  62. return [];
  63. }
  64. $res = explode(',', $res);
  65. return response()->json($res);
  66. }
  67. $res = config('remote-auth.mastodon.domains.default');
  68. $res = explode(',', $res);
  69. return response()->json($res);
  70. }
  71. public function redirect(Request $request)
  72. {
  73. abort_unless((
  74. config_cache('pixelfed.open_registration') &&
  75. config('remote-auth.mastodon.enabled')
  76. ) || (
  77. config('remote-auth.mastodon.ignore_closed_state') &&
  78. config('remote-auth.mastodon.enabled')
  79. ), 404);
  80. $this->validate($request, ['domain' => 'required']);
  81. $domain = $request->input('domain');
  82. if (str_starts_with(strtolower($domain), 'http')) {
  83. $res = [
  84. 'domain' => $domain,
  85. 'ready' => false,
  86. 'action' => 'incompatible_domain',
  87. ];
  88. return response()->json($res);
  89. }
  90. $validateInstance = Helpers::validateUrl('https://'.$domain.'/?block-check='.time());
  91. if (! $validateInstance) {
  92. $res = [
  93. 'domain' => $domain,
  94. 'ready' => false,
  95. 'action' => 'blocked_domain',
  96. ];
  97. return response()->json($res);
  98. }
  99. $compatible = RemoteAuthService::isDomainCompatible($domain);
  100. if (! $compatible) {
  101. $res = [
  102. 'domain' => $domain,
  103. 'ready' => false,
  104. 'action' => 'incompatible_domain',
  105. ];
  106. return response()->json($res);
  107. }
  108. if (config('remote-auth.mastodon.domains.only_default')) {
  109. $defaultDomains = explode(',', config('remote-auth.mastodon.domains.default'));
  110. if (! in_array($domain, $defaultDomains)) {
  111. $res = [
  112. 'domain' => $domain,
  113. 'ready' => false,
  114. 'action' => 'incompatible_domain',
  115. ];
  116. return response()->json($res);
  117. }
  118. }
  119. if (config('remote-auth.mastodon.domains.only_custom') && config('remote-auth.mastodon.domains.custom')) {
  120. $customDomains = explode(',', config('remote-auth.mastodon.domains.custom'));
  121. if (! in_array($domain, $customDomains)) {
  122. $res = [
  123. 'domain' => $domain,
  124. 'ready' => false,
  125. 'action' => 'incompatible_domain',
  126. ];
  127. return response()->json($res);
  128. }
  129. }
  130. $client = RemoteAuthService::getMastodonClient($domain);
  131. abort_unless($client, 422, 'Invalid mastodon client');
  132. $request->session()->put('state', $state = Str::random(40));
  133. $request->session()->put('oauth_domain', $domain);
  134. $query = http_build_query([
  135. 'client_id' => $client->client_id,
  136. 'redirect_uri' => $client->redirect_uri,
  137. 'response_type' => 'code',
  138. 'scope' => 'read',
  139. 'state' => $state,
  140. ]);
  141. $request->session()->put('oauth_redirect_to', 'https://'.$domain.'/oauth/authorize?'.$query);
  142. $dsh = Str::random(17);
  143. $res = [
  144. 'domain' => $domain,
  145. 'ready' => true,
  146. 'dsh' => $dsh,
  147. ];
  148. return response()->json($res);
  149. }
  150. public function preflight(Request $request)
  151. {
  152. abort_unless((
  153. config_cache('pixelfed.open_registration') &&
  154. config('remote-auth.mastodon.enabled')
  155. ) || (
  156. config('remote-auth.mastodon.ignore_closed_state') &&
  157. config('remote-auth.mastodon.enabled')
  158. ), 404);
  159. if (! $request->filled('d') || ! $request->filled('dsh') || ! $request->session()->exists('oauth_redirect_to')) {
  160. return redirect('/login');
  161. }
  162. return redirect()->away($request->session()->pull('oauth_redirect_to'));
  163. }
  164. public function handleCallback(Request $request)
  165. {
  166. abort_unless((
  167. config_cache('pixelfed.open_registration') &&
  168. config('remote-auth.mastodon.enabled')
  169. ) || (
  170. config('remote-auth.mastodon.ignore_closed_state') &&
  171. config('remote-auth.mastodon.enabled')
  172. ), 404);
  173. $domain = $request->session()->get('oauth_domain');
  174. if ($request->filled('code')) {
  175. $code = $request->input('code');
  176. $state = $request->session()->pull('state');
  177. throw_unless(
  178. strlen($state) > 0 && $state === $request->state,
  179. InvalidArgumentException::class,
  180. 'Invalid state value.'
  181. );
  182. $res = RemoteAuthService::getToken($domain, $code);
  183. if (! $res || ! isset($res['access_token'])) {
  184. $request->session()->regenerate();
  185. return redirect('/login');
  186. }
  187. $request->session()->put('oauth_remote_session_token', $res['access_token']);
  188. return redirect('/auth/mastodon/getting-started');
  189. }
  190. return redirect('/login');
  191. }
  192. public function onboarding(Request $request)
  193. {
  194. abort_unless((
  195. config_cache('pixelfed.open_registration') &&
  196. config('remote-auth.mastodon.enabled')
  197. ) || (
  198. config('remote-auth.mastodon.ignore_closed_state') &&
  199. config('remote-auth.mastodon.enabled')
  200. ), 404);
  201. if ($request->user()) {
  202. return redirect('/');
  203. }
  204. return view('auth.remote.onboarding');
  205. }
  206. public function sessionCheck(Request $request)
  207. {
  208. abort_unless((
  209. config_cache('pixelfed.open_registration') &&
  210. config('remote-auth.mastodon.enabled')
  211. ) || (
  212. config('remote-auth.mastodon.ignore_closed_state') &&
  213. config('remote-auth.mastodon.enabled')
  214. ), 404);
  215. abort_if($request->user(), 403);
  216. abort_unless($request->session()->exists('oauth_domain'), 403);
  217. abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
  218. $domain = $request->session()->get('oauth_domain');
  219. $token = $request->session()->get('oauth_remote_session_token');
  220. $res = RemoteAuthService::getVerifyCredentials($domain, $token);
  221. abort_if(! $res || ! isset($res['acct']), 403, 'Invalid credentials');
  222. $webfinger = strtolower('@'.$res['acct'].'@'.$domain);
  223. $request->session()->put('oauth_masto_webfinger', $webfinger);
  224. if (config('remote-auth.mastodon.max_uses.enabled')) {
  225. $limit = config('remote-auth.mastodon.max_uses.limit');
  226. $uses = RemoteAuthService::lookupWebfingerUses($webfinger);
  227. if ($uses >= $limit) {
  228. return response()->json([
  229. 'code' => 200,
  230. 'msg' => 'Success!',
  231. 'action' => 'max_uses_reached',
  232. ]);
  233. }
  234. }
  235. $exists = RemoteAuth::whereDomain($domain)->where('webfinger', $webfinger)->whereNotNull('user_id')->first();
  236. if ($exists && $exists->user_id) {
  237. return response()->json([
  238. 'code' => 200,
  239. 'msg' => 'Success!',
  240. 'action' => 'redirect_existing_user',
  241. ]);
  242. }
  243. return response()->json([
  244. 'code' => 200,
  245. 'msg' => 'Success!',
  246. 'action' => 'onboard',
  247. ]);
  248. }
  249. public function sessionGetMastodonData(Request $request)
  250. {
  251. abort_unless((
  252. config_cache('pixelfed.open_registration') &&
  253. config('remote-auth.mastodon.enabled')
  254. ) || (
  255. config('remote-auth.mastodon.ignore_closed_state') &&
  256. config('remote-auth.mastodon.enabled')
  257. ), 404);
  258. abort_if($request->user(), 403);
  259. abort_unless($request->session()->exists('oauth_domain'), 403);
  260. abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
  261. $domain = $request->session()->get('oauth_domain');
  262. $token = $request->session()->get('oauth_remote_session_token');
  263. $res = RemoteAuthService::getVerifyCredentials($domain, $token);
  264. $res['_webfinger'] = strtolower('@'.$res['acct'].'@'.$domain);
  265. $res['_domain'] = strtolower($domain);
  266. $request->session()->put('oauth_remasto_id', $res['id']);
  267. $ra = RemoteAuth::updateOrCreate([
  268. 'domain' => $domain,
  269. 'webfinger' => $res['_webfinger'],
  270. ], [
  271. 'software' => 'mastodon',
  272. 'ip_address' => $request->ip(),
  273. 'bearer_token' => $token,
  274. 'verify_credentials' => $res,
  275. 'last_verify_credentials_at' => now(),
  276. 'last_successful_login_at' => now(),
  277. ]);
  278. $request->session()->put('oauth_masto_raid', $ra->id);
  279. return response()->json($res);
  280. }
  281. public function sessionValidateUsername(Request $request)
  282. {
  283. abort_unless((
  284. config_cache('pixelfed.open_registration') &&
  285. config('remote-auth.mastodon.enabled')
  286. ) || (
  287. config('remote-auth.mastodon.ignore_closed_state') &&
  288. config('remote-auth.mastodon.enabled')
  289. ), 404);
  290. abort_if($request->user(), 403);
  291. abort_unless($request->session()->exists('oauth_domain'), 403);
  292. abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
  293. $this->validate($request, [
  294. 'username' => [
  295. 'required',
  296. 'min:2',
  297. 'max:30',
  298. new PixelfedUsername(),
  299. ],
  300. ]);
  301. $username = strtolower($request->input('username'));
  302. $exists = User::where('username', $username)->exists();
  303. return response()->json([
  304. 'code' => 200,
  305. 'username' => $username,
  306. 'exists' => $exists,
  307. ]);
  308. }
  309. public function sessionValidateEmail(Request $request)
  310. {
  311. abort_unless((
  312. config_cache('pixelfed.open_registration') &&
  313. config('remote-auth.mastodon.enabled')
  314. ) || (
  315. config('remote-auth.mastodon.ignore_closed_state') &&
  316. config('remote-auth.mastodon.enabled')
  317. ), 404);
  318. abort_if($request->user(), 403);
  319. abort_unless($request->session()->exists('oauth_domain'), 403);
  320. abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
  321. $this->validate($request, [
  322. 'email' => [
  323. 'required',
  324. 'email:strict,filter_unicode,dns,spoof',
  325. ],
  326. ]);
  327. $email = $request->input('email');
  328. $banned = EmailService::isBanned($email);
  329. $exists = User::where('email', $email)->exists();
  330. return response()->json([
  331. 'code' => 200,
  332. 'email' => $email,
  333. 'exists' => $exists,
  334. 'banned' => $banned,
  335. ]);
  336. }
  337. public function sessionGetMastodonFollowers(Request $request)
  338. {
  339. abort_unless((
  340. config_cache('pixelfed.open_registration') &&
  341. config('remote-auth.mastodon.enabled')
  342. ) || (
  343. config('remote-auth.mastodon.ignore_closed_state') &&
  344. config('remote-auth.mastodon.enabled')
  345. ), 404);
  346. abort_unless($request->session()->exists('oauth_domain'), 403);
  347. abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
  348. abort_unless($request->session()->exists('oauth_remasto_id'), 403);
  349. $domain = $request->session()->get('oauth_domain');
  350. $token = $request->session()->get('oauth_remote_session_token');
  351. $id = $request->session()->get('oauth_remasto_id');
  352. $res = RemoteAuthService::getFollowing($domain, $token, $id);
  353. if (! $res) {
  354. return response()->json([
  355. 'code' => 200,
  356. 'following' => [],
  357. ]);
  358. }
  359. $res = collect($res)->filter(fn ($acct) => Helpers::validateUrl($acct['url']))->values()->toArray();
  360. return response()->json([
  361. 'code' => 200,
  362. 'following' => $res,
  363. ]);
  364. }
  365. public function handleSubmit(Request $request)
  366. {
  367. abort_unless((
  368. config_cache('pixelfed.open_registration') &&
  369. config('remote-auth.mastodon.enabled')
  370. ) || (
  371. config('remote-auth.mastodon.ignore_closed_state') &&
  372. config('remote-auth.mastodon.enabled')
  373. ), 404);
  374. abort_unless($request->session()->exists('oauth_domain'), 403);
  375. abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
  376. abort_unless($request->session()->exists('oauth_remasto_id'), 403);
  377. abort_unless($request->session()->exists('oauth_masto_webfinger'), 403);
  378. abort_unless($request->session()->exists('oauth_masto_raid'), 403);
  379. $this->validate($request, [
  380. 'email' => 'required|email:strict,filter_unicode,dns,spoof',
  381. 'username' => [
  382. 'required',
  383. 'min:2',
  384. 'max:30',
  385. 'unique:users,username',
  386. function ($attribute, $value, $fail) {
  387. $dash = substr_count($value, '-');
  388. $underscore = substr_count($value, '_');
  389. $period = substr_count($value, '.');
  390. if (ends_with($value, ['.php', '.js', '.css'])) {
  391. return $fail('Username is invalid.');
  392. }
  393. if (($dash + $underscore + $period) > 1) {
  394. return $fail('Username is invalid. Can only contain one dash (-), period (.) or underscore (_).');
  395. }
  396. if (! ctype_alnum($value[0])) {
  397. return $fail('Username is invalid. Must start with a letter or number.');
  398. }
  399. if (! ctype_alnum($value[strlen($value) - 1])) {
  400. return $fail('Username is invalid. Must end with a letter or number.');
  401. }
  402. $val = str_replace(['_', '.', '-'], '', $value);
  403. if (! ctype_alnum($val)) {
  404. return $fail('Username is invalid. Username must be alpha-numeric and may contain dashes (-), periods (.) and underscores (_).');
  405. }
  406. $restricted = RestrictedNames::get();
  407. if (in_array(strtolower($value), array_map('strtolower', $restricted))) {
  408. return $fail('Username cannot be used.');
  409. }
  410. },
  411. ],
  412. 'password' => 'required|string|min:8|confirmed',
  413. 'name' => 'nullable|max:30',
  414. ]);
  415. $email = $request->input('email');
  416. $username = $request->input('username');
  417. $password = $request->input('password');
  418. $name = $request->input('name');
  419. $user = $this->createUser([
  420. 'name' => $name,
  421. 'username' => $username,
  422. 'password' => $password,
  423. 'email' => $email,
  424. ]);
  425. $raid = $request->session()->pull('oauth_masto_raid');
  426. $webfinger = $request->session()->pull('oauth_masto_webfinger');
  427. $token = $user->createToken('Onboarding')->accessToken;
  428. $ra = RemoteAuth::where('id', $raid)->where('webfinger', $webfinger)->firstOrFail();
  429. $ra->user_id = $user->id;
  430. $ra->save();
  431. return [
  432. 'code' => 200,
  433. 'msg' => 'Success',
  434. 'token' => $token,
  435. ];
  436. }
  437. public function storeBio(Request $request)
  438. {
  439. abort_unless((
  440. config_cache('pixelfed.open_registration') &&
  441. config('remote-auth.mastodon.enabled')
  442. ) || (
  443. config('remote-auth.mastodon.ignore_closed_state') &&
  444. config('remote-auth.mastodon.enabled')
  445. ), 404);
  446. abort_unless($request->user(), 404);
  447. abort_unless($request->session()->exists('oauth_domain'), 403);
  448. abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
  449. abort_unless($request->session()->exists('oauth_remasto_id'), 403);
  450. $this->validate($request, [
  451. 'bio' => 'required|nullable|max:500',
  452. ]);
  453. $profile = $request->user()->profile;
  454. $profile->bio = Purify::clean($request->input('bio'));
  455. $profile->save();
  456. return [200];
  457. }
  458. public function accountToId(Request $request)
  459. {
  460. abort_unless((
  461. config_cache('pixelfed.open_registration') &&
  462. config('remote-auth.mastodon.enabled')
  463. ) || (
  464. config('remote-auth.mastodon.ignore_closed_state') &&
  465. config('remote-auth.mastodon.enabled')
  466. ), 404);
  467. abort_if($request->user(), 404);
  468. abort_unless($request->session()->exists('oauth_domain'), 403);
  469. abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
  470. abort_unless($request->session()->exists('oauth_remasto_id'), 403);
  471. $this->validate($request, [
  472. 'account' => 'required|url',
  473. ]);
  474. $account = $request->input('account');
  475. abort_unless(substr(strtolower($account), 0, 8) === 'https://', 404);
  476. $host = strtolower(config('pixelfed.domain.app'));
  477. $domain = strtolower(parse_url($account, PHP_URL_HOST));
  478. if ($domain == $host) {
  479. $username = Str::of($account)->explode('/')->last();
  480. $user = User::where('username', $username)->first();
  481. if ($user) {
  482. return ['id' => (string) $user->profile_id];
  483. } else {
  484. return [];
  485. }
  486. } else {
  487. try {
  488. $profile = Helpers::profileFetch($account);
  489. if ($profile) {
  490. return ['id' => (string) $profile->id];
  491. } else {
  492. return [];
  493. }
  494. } catch (\GuzzleHttp\Exception\RequestException $e) {
  495. return;
  496. } catch (Exception $e) {
  497. return [];
  498. }
  499. }
  500. }
  501. public function storeAvatar(Request $request)
  502. {
  503. abort_unless((
  504. config_cache('pixelfed.open_registration') &&
  505. config('remote-auth.mastodon.enabled')
  506. ) || (
  507. config('remote-auth.mastodon.ignore_closed_state') &&
  508. config('remote-auth.mastodon.enabled')
  509. ), 404);
  510. abort_unless($request->user(), 404);
  511. $this->validate($request, [
  512. 'avatar_url' => 'required|active_url',
  513. ]);
  514. $user = $request->user();
  515. $profile = $user->profile;
  516. abort_if(! $profile->avatar, 404, 'Missing avatar');
  517. $avatar = $profile->avatar;
  518. $avatar->remote_url = $request->input('avatar_url');
  519. $avatar->save();
  520. MediaStorageService::avatar($avatar, (bool) config_cache('pixelfed.cloud_storage') == false);
  521. return [200];
  522. }
  523. public function finishUp(Request $request)
  524. {
  525. abort_unless((
  526. config_cache('pixelfed.open_registration') &&
  527. config('remote-auth.mastodon.enabled')
  528. ) || (
  529. config('remote-auth.mastodon.ignore_closed_state') &&
  530. config('remote-auth.mastodon.enabled')
  531. ), 404);
  532. abort_unless($request->user(), 404);
  533. $currentWebfinger = '@'.$request->user()->username.'@'.config('pixelfed.domain.app');
  534. $ra = RemoteAuth::where('user_id', $request->user()->id)->firstOrFail();
  535. RemoteAuthService::submitToBeagle(
  536. $ra->webfinger,
  537. $ra->verify_credentials['url'],
  538. $currentWebfinger,
  539. $request->user()->url()
  540. );
  541. return [200];
  542. }
  543. public function handleLogin(Request $request)
  544. {
  545. abort_unless((
  546. config_cache('pixelfed.open_registration') &&
  547. config('remote-auth.mastodon.enabled')
  548. ) || (
  549. config('remote-auth.mastodon.ignore_closed_state') &&
  550. config('remote-auth.mastodon.enabled')
  551. ), 404);
  552. abort_if($request->user(), 404);
  553. abort_unless($request->session()->exists('oauth_domain'), 403);
  554. abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
  555. abort_unless($request->session()->exists('oauth_masto_webfinger'), 403);
  556. $domain = $request->session()->get('oauth_domain');
  557. $wf = $request->session()->get('oauth_masto_webfinger');
  558. $ra = RemoteAuth::where('webfinger', $wf)->where('domain', $domain)->whereNotNull('user_id')->firstOrFail();
  559. $user = User::findOrFail($ra->user_id);
  560. abort_if($user->is_admin || $user->status != null, 422, 'Invalid auth action');
  561. Auth::loginUsingId($ra->user_id);
  562. return [200];
  563. }
  564. protected function createUser($data)
  565. {
  566. event(new Registered($user = User::create([
  567. 'name' => Purify::clean($data['name']),
  568. 'username' => $data['username'],
  569. 'email' => $data['email'],
  570. 'password' => Hash::make($data['password']),
  571. 'email_verified_at' => config('remote-auth.mastodon.contraints.skip_email_verification') ? now() : null,
  572. 'app_register_ip' => request()->ip(),
  573. 'register_source' => 'mastodon',
  574. ])));
  575. $this->guarder()->login($user);
  576. return $user;
  577. }
  578. protected function guarder()
  579. {
  580. return Auth::guard();
  581. }
  582. }