Няма описание

AuthController.php 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. <?php namespace App\Http\Controllers;
  2. use Hash;
  3. use Config;
  4. use Validator;
  5. use Firebase\JWT\JWT;
  6. use Illuminate\Http\Request;
  7. use GuzzleHttp;
  8. use GuzzleHttp\Subscriber\Oauth\Oauth1;
  9. use App\User;
  10. class AuthController extends Controller {
  11. /**
  12. * Generate JSON Web Token.
  13. */
  14. protected function createToken($user)
  15. {
  16. $payload = [
  17. 'sub' => $user->id,
  18. 'iat' => time(),
  19. 'exp' => time() + (2 * 7 * 24 * 60 * 60)
  20. ];
  21. return JWT::encode($payload, Config::get('app.token_secret'));
  22. }
  23. /**
  24. * Unlink provider.
  25. */
  26. public function unlink(Request $request, $provider)
  27. {
  28. $user = User::find($request['user']['sub']);
  29. if (!$user)
  30. {
  31. return response()->json(['message' => 'User not found']);
  32. }
  33. $user->$provider = '';
  34. $user->save();
  35. return response()->json(array('token' => $this->createToken($user)));
  36. }
  37. /**
  38. * Log in with Email and Password.
  39. */
  40. public function login(Request $request)
  41. {
  42. $email = $request->input('email');
  43. $password = $request->input('password');
  44. $user = User::where('email', '=', $email)->first();
  45. if (!$user)
  46. {
  47. return response()->json(['message' => 'Wrong email and/or password'], 401);
  48. }
  49. if (Hash::check($password, $user->password))
  50. {
  51. unset($user->password);
  52. return response()->json(['token' => $this->createToken($user)]);
  53. }
  54. else
  55. {
  56. return response()->json(['message' => 'Wrong email and/or password'], 401);
  57. }
  58. }
  59. /**
  60. * Create Email and Password Account.
  61. */
  62. public function signup(Request $request)
  63. {
  64. $validator = Validator::make($request->all(), [
  65. 'displayName' => 'required',
  66. 'email' => 'required|email|unique:users,email',
  67. 'password' => 'required'
  68. ]);
  69. if ($validator->fails()) {
  70. return response()->json(['message' => $validator->messages()], 400);
  71. }
  72. $user = new User;
  73. $user->displayName = $request->input('displayName');
  74. $user->email = $request->input('email');
  75. $user->password = Hash::make($request->input('password'));
  76. $user->save();
  77. return response()->json(['token' => $this->createToken($user)]);
  78. }
  79. /**
  80. * Login with Facebook.
  81. */
  82. public function facebook(Request $request)
  83. {
  84. $client = new GuzzleHttp\Client();
  85. $params = [
  86. 'code' => $request->input('code'),
  87. 'client_id' => $request->input('clientId'),
  88. 'redirect_uri' => $request->input('redirectUri'),
  89. 'client_secret' => Config::get('app.facebook_secret')
  90. ];
  91. // Step 1. Exchange authorization code for access token.
  92. $accessTokenResponse = $client->request('GET', 'https://graph.facebook.com/v2.5/oauth/access_token', [
  93. 'query' => $params
  94. ]);
  95. $accessToken = json_decode($accessTokenResponse->getBody(), true);
  96. // Step 2. Retrieve profile information about the current user.
  97. $fields = 'id,email,first_name,last_name,link,name';
  98. $profileResponse = $client->request('GET', 'https://graph.facebook.com/v2.5/me', [
  99. 'query' => [
  100. 'access_token' => $accessToken['access_token'],
  101. 'fields' => $fields
  102. ]
  103. ]);
  104. $profile = json_decode($profileResponse->getBody(), true);
  105. // Step 3a. If user is already signed in then link accounts.
  106. if ($request->header('Authorization'))
  107. {
  108. $user = User::where('facebook', '=', $profile['id']);
  109. if ($user->first())
  110. {
  111. return response()->json(['message' => 'There is already a Facebook account that belongs to you'], 409);
  112. }
  113. $token = explode(' ', $request->header('Authorization'))[1];
  114. $payload = (array) JWT::decode($token, Config::get('app.token_secret'), array('HS256'));
  115. $user = User::find($payload['sub']);
  116. $user->facebook = $profile['id'];
  117. $user->email = $user->email ?: $profile['email'];
  118. $user->displayName = $user->displayName ?: $profile['name'];
  119. $user->save();
  120. return response()->json(['token' => $this->createToken($user)]);
  121. }
  122. // Step 3b. Create a new user account or return an existing one.
  123. else
  124. {
  125. $user = User::where('facebook', '=', $profile['id']);
  126. if ($user->first())
  127. {
  128. return response()->json(['token' => $this->createToken($user->first())]);
  129. }
  130. $user = new User;
  131. $user->facebook = $profile['id'];
  132. $user->email = $profile['email'];
  133. $user->displayName = $profile['name'];
  134. $user->save();
  135. return response()->json(['token' => $this->createToken($user)]);
  136. }
  137. }
  138. /**
  139. * Login with Google.
  140. */
  141. public function google(Request $request)
  142. {
  143. $client = new GuzzleHttp\Client();
  144. $params = [
  145. 'code' => $request->input('code'),
  146. 'client_id' => $request->input('clientId'),
  147. 'client_secret' => Config::get('app.google_secret'),
  148. 'redirect_uri' => $request->input('redirectUri'),
  149. 'grant_type' => 'authorization_code',
  150. ];
  151. // Step 1. Exchange authorization code for access token.
  152. $accessTokenResponse = $client->request('POST', 'https://accounts.google.com/o/oauth2/token', [
  153. 'form_params' => $params
  154. ]);
  155. $accessToken = json_decode($accessTokenResponse->getBody(), true);
  156. // Step 2. Retrieve profile information about the current user.
  157. $profileResponse = $client->request('GET', 'https://www.googleapis.com/plus/v1/people/me/openIdConnect', [
  158. 'headers' => array('Authorization' => 'Bearer ' . $accessToken['access_token'])
  159. ]);
  160. $profile = json_decode($profileResponse->getBody(), true);
  161. // Step 3a. If user is already signed in then link accounts.
  162. if ($request->header('Authorization'))
  163. {
  164. $user = User::where('google', '=', $profile['sub']);
  165. if ($user->first())
  166. {
  167. return response()->json(['message' => 'There is already a Google account that belongs to you'], 409);
  168. }
  169. $token = explode(' ', $request->header('Authorization'))[1];
  170. $payload = (array) JWT::decode($token, Config::get('app.token_secret'), array('HS256'));
  171. $user = User::find($payload['sub']);
  172. $user->google = $profile['sub'];
  173. $user->displayName = $user->displayName ?: $profile['name'];
  174. $user->save();
  175. return response()->json(['token' => $this->createToken($user)]);
  176. }
  177. // Step 3b. Create a new user account or return an existing one.
  178. else
  179. {
  180. $user = User::where('google', '=', $profile['sub']);
  181. if ($user->first())
  182. {
  183. return response()->json(['token' => $this->createToken($user->first())]);
  184. }
  185. $user = new User;
  186. $user->google = $profile['sub'];
  187. $user->displayName = $profile['name'];
  188. $user->save();
  189. return response()->json(['token' => $this->createToken($user)]);
  190. }
  191. }
  192. /**
  193. * Login with LinkedIn.
  194. */
  195. public function linkedin(Request $request)
  196. {
  197. $client = new GuzzleHttp\Client();
  198. $params = [
  199. 'code' => $request->input('code'),
  200. 'client_id' => $request->input('clientId'),
  201. 'client_secret' => Config::get('app.linkedin_secret'),
  202. 'redirect_uri' => $request->input('redirectUri'),
  203. 'grant_type' => 'authorization_code',
  204. ];
  205. // Step 1. Exchange authorization code for access token.
  206. $accessTokenResponse = $client->request('POST', 'https://www.linkedin.com/uas/oauth2/accessToken', [
  207. 'form_params' => $params
  208. ]);
  209. $accessToken = json_decode($accessTokenResponse->getBody(), true);
  210. // Step 2. Retrieve profile information about the current user.
  211. $profileResponse = $client->request('GET', 'https://api.linkedin.com/v1/people/~:(id,first-name,last-name,email-address)', [
  212. 'query' => [
  213. 'oauth2_access_token' => $accessToken['access_token'],
  214. 'format' => 'json'
  215. ]
  216. ]);
  217. $profile = json_decode($profileResponse->getBody(), true);
  218. // Step 3a. If user is already signed in then link accounts.
  219. if ($request->header('Authorization'))
  220. {
  221. $user = User::where('linkedin', '=', $profile['id']);
  222. if ($user->first())
  223. {
  224. return response()->json(['message' => 'There is already a LinkedIn account that belongs to you'], 409);
  225. }
  226. $token = explode(' ', $request->header('Authorization'))[1];
  227. $payload = (array) JWT::decode($token, Config::get('app.token_secret'), array('HS256'));
  228. $user = User::find($payload['sub']);
  229. $user->linkedin = $profile['id'];
  230. $user->displayName = $user->displayName ?: $profile['firstName'] . ' ' . $profile['lastName'];
  231. $user->save();
  232. return response()->json(['token' => $this->createToken($user)]);
  233. }
  234. // Step 3b. Create a new user account or return an existing one.
  235. else
  236. {
  237. $user = User::where('linkedin', '=', $profile['id']);
  238. if ($user->first())
  239. {
  240. return response()->json(['token' => $this->createToken($user->first())]);
  241. }
  242. $user = new User;
  243. $user->linkedin = $profile['id'];
  244. $user->displayName = $profile['firstName'] . ' ' . $profile['lastName'];
  245. $user->save();
  246. return response()->json(['token' => $this->createToken($user)]);
  247. }
  248. }
  249. /**
  250. * Login with Twitter.
  251. */
  252. public function twitter(Request $request)
  253. {
  254. $stack = GuzzleHttp\HandlerStack::create();
  255. // Part 1 of 2: Initial request from Satellizer.
  256. if (!$request->input('oauth_token') || !$request->input('oauth_verifier'))
  257. {
  258. $stack = GuzzleHttp\HandlerStack::create();
  259. $requestTokenOauth = new Oauth1([
  260. 'consumer_key' => Config::get('app.twitter_key'),
  261. 'consumer_secret' => Config::get('app.twitter_secret'),
  262. 'callback' => $request->input('redirectUri'),
  263. 'token' => '',
  264. 'token_secret' => ''
  265. ]);
  266. $stack->push($requestTokenOauth);
  267. $client = new GuzzleHttp\Client([
  268. 'handler' => $stack
  269. ]);
  270. // Step 1. Obtain request token for the authorization popup.
  271. $requestTokenResponse = $client->request('POST', 'https://api.twitter.com/oauth/request_token', [
  272. 'auth' => 'oauth'
  273. ]);
  274. $oauthToken = array();
  275. parse_str($requestTokenResponse->getBody(), $oauthToken);
  276. // Step 2. Send OAuth token back to open the authorization screen.
  277. return response()->json($oauthToken);
  278. }
  279. // Part 2 of 2: Second request after Authorize app is clicked.
  280. else
  281. {
  282. $accessTokenOauth = new Oauth1([
  283. 'consumer_key' => Config::get('app.twitter_key'),
  284. 'consumer_secret' => Config::get('app.twitter_secret'),
  285. 'token' => $request->input('oauth_token'),
  286. 'verifier' => $request->input('oauth_verifier'),
  287. 'token_secret' => ''
  288. ]);
  289. $stack->push($accessTokenOauth);
  290. $client = new GuzzleHttp\Client([
  291. 'handler' => $stack
  292. ]);
  293. // Step 3. Exchange oauth token and oauth verifier for access token.
  294. $accessTokenResponse = $client->request('POST', 'https://api.twitter.com/oauth/access_token', [
  295. 'auth' => 'oauth'
  296. ]);
  297. $accessToken = array();
  298. parse_str($accessTokenResponse->getBody(), $accessToken);
  299. $profileOauth = new Oauth1([
  300. 'consumer_key' => Config::get('app.twitter_key'),
  301. 'consumer_secret' => Config::get('app.twitter_secret'),
  302. 'oauth_token' => $accessToken['oauth_token'],
  303. 'token_secret' => ''
  304. ]);
  305. $stack->push($profileOauth);
  306. $client = new GuzzleHttp\Client([
  307. 'handler' => $stack
  308. ]);
  309. // Step 4. Retrieve profile information about the current user.
  310. $profileResponse = $client->request('GET', 'https://api.twitter.com/1.1/users/show.json?screen_name=' . $accessToken['screen_name'], [
  311. 'auth' => 'oauth'
  312. ]);
  313. $profile = json_decode($profileResponse->getBody(), true);
  314. // Step 5a. Link user accounts.
  315. if ($request->header('Authorization'))
  316. {
  317. $user = User::where('twitter', '=', $profile['id']);
  318. if ($user->first())
  319. {
  320. return response()->json(['message' => 'There is already a Twitter account that belongs to you'], 409);
  321. }
  322. $token = explode(' ', $request->header('Authorization'))[1];
  323. $payload = (array) JWT::decode($token, Config::get('app.token_secret'), array('HS256'));
  324. $user = User::find($payload['sub']);
  325. $user->twitter = $profile['id'];
  326. $user->displayName = $user->displayName ?: $profile['screen_name'];
  327. $user->save();
  328. return response()->json(['token' => $this->createToken($user)]);
  329. }
  330. // Step 5b. Create a new user account or return an existing one.
  331. else
  332. {
  333. $user = User::where('twitter', '=', $profile['id']);
  334. if ($user->first())
  335. {
  336. return response()->json(['token' => $this->createToken($user->first())]);
  337. }
  338. $user = new User;
  339. $user->twitter = $profile['id'];
  340. $user->displayName = $profile['screen_name'];
  341. $user->save();
  342. return response()->json(['token' => $this->createToken($user)]);
  343. }
  344. }
  345. }
  346. /**
  347. * Login with Foursquare.
  348. */
  349. public function foursquare(Request $request)
  350. {
  351. $client = new GuzzleHttp\Client();
  352. $params = [
  353. 'code' => $request->input('code'),
  354. 'client_id' => $request->input('clientId'),
  355. 'client_secret' => Config::get('app.foursquare_secret'),
  356. 'redirect_uri' => $request->input('redirectUri'),
  357. 'grant_type' => 'authorization_code',
  358. ];
  359. // Step 1. Exchange authorization code for access token.
  360. $accessTokenResponse = $client->request('POST', 'https://foursquare.com/oauth2/access_token', [
  361. 'form_params' => $params
  362. ]);
  363. $accessToken = json_decode($accessTokenResponse->getBody(), true);
  364. // Step 2. Retrieve profile information about the current user.
  365. $profileResponse = $client->request('GET', 'https://api.foursquare.com/v2/users/self', [
  366. 'query' => [
  367. 'v' => '20140806',
  368. 'oauth_token' => $accessToken['access_token']
  369. ]
  370. ]);
  371. $profile = json_decode($profileResponse->getBody(), true)['response']['user'];
  372. // Step 3a. If user is already signed in then link accounts.
  373. if ($request->header('Authorization'))
  374. {
  375. $user = User::where('foursquare', '=', $profile['id']);
  376. if ($user->first())
  377. {
  378. return response()->json(array('message' => 'There is already a Foursquare account that belongs to you'), 409);
  379. }
  380. $token = explode(' ', $request->header('Authorization'))[1];
  381. $payload = (array) JWT::decode($token, Config::get('app.token_secret'), array('HS256'));
  382. $user = User::find($payload['sub']);
  383. $user->foursquare = $profile['id'];
  384. $user->displayName = $user->displayName ?: $profile['firstName'] . ' ' . $profile['lastName'];
  385. $user->save();
  386. return response()->json(['token' => $this->createToken($user)]);
  387. }
  388. // Step 3b. Create a new user account or return an existing one.
  389. else
  390. {
  391. $user = User::where('foursquare', '=', $profile['id']);
  392. if ($user->first())
  393. {
  394. return response()->json(['token' => $this->createToken($user->first())]);
  395. }
  396. $user = new User;
  397. $user->foursquare = $profile['id'];
  398. $user->displayName = $profile['firstName'] . ' ' . $profile['lastName'];
  399. $user->save();
  400. return response()->json(['token' => $this->createToken($user)]);
  401. }
  402. }
  403. /**
  404. * Login with Instagram.
  405. */
  406. public function instagram(Request $request)
  407. {
  408. $client = new GuzzleHttp\Client();
  409. $params = [
  410. 'code' => $request->input('code'),
  411. 'client_id' => $request->input('clientId'),
  412. 'client_secret' => Config::get('app.instagram_secret'),
  413. 'redirect_uri' => $request->input('redirectUri'),
  414. 'grant_type' => 'authorization_code',
  415. ];
  416. // Step 1. Exchange authorization code for access token.
  417. $accessTokenResponse = $client->request('POST', 'https://api.instagram.com/oauth/access_token', [
  418. 'body' => $params
  419. ]);
  420. $accessToken = json_decode($accessTokenResponse->getBody(), true);
  421. // Step 2a. If user is already signed in then link accounts.
  422. if ($request->header('Authorization'))
  423. {
  424. $user = User::where('instagram', '=', $accessToken['user']['id']);
  425. if ($user->first())
  426. {
  427. return response()->json(array('message' => 'There is already an Instagram account that belongs to you'), 409);
  428. }
  429. $token = explode(' ', $request->header('Authorization'))[1];
  430. $payload = (array) JWT::decode($token, Config::get('app.token_secret'), array('HS256'));
  431. $user = User::find($payload['sub']);
  432. $user->instagram = $accessToken['user']['id'];
  433. $user->displayName = $user->displayName ?: $accessToken['user']['username'];
  434. $user->save();
  435. return response()->json(['token' => $this->createToken($user)]);
  436. }
  437. // Step 2b. Create a new user account or return an existing one.
  438. else
  439. {
  440. $user = User::where('instagram', '=', $accessToken['user']['id']);
  441. if ($user->first())
  442. {
  443. return response()->json(['token' => $this->createToken($user->first())]);
  444. }
  445. $user = new User;
  446. $user->instagram = $accessToken['user']['id'];
  447. $user->displayName = $accessToken['user']['username'];
  448. $user->save();
  449. return response()->json(['token' => $this->createToken($user)]);
  450. }
  451. }
  452. /**
  453. * Login with GitHub.
  454. */
  455. public function github(Request $request)
  456. {
  457. $client = new GuzzleHttp\Client();
  458. $params = [
  459. 'code' => $request->input('code'),
  460. 'client_id' => $request->input('clientId'),
  461. 'client_secret' => Config::get('app.github_secret'),
  462. 'redirect_uri' => $request->input('redirectUri')
  463. ];
  464. // Step 1. Exchange authorization code for access token.
  465. $accessTokenResponse = $client->request('GET', 'https://github.com/login/oauth/access_token', [
  466. 'query' => $params
  467. ]);
  468. $accessToken = array();
  469. parse_str($accessTokenResponse->getBody(), $accessToken);
  470. // Step 2. Retrieve profile information about the current user.
  471. $profileResponse = $client->request('GET', 'https://api.github.com/user', [
  472. 'headers' => ['User-Agent' => 'Satellizer'],
  473. 'query' => $accessToken
  474. ]);
  475. $profile = json_decode($profileResponse->getBody(), true);
  476. // Step 3a. If user is already signed in then link accounts.
  477. if ($request->header('Authorization'))
  478. {
  479. $user = User::where('github', '=', $profile['id']);
  480. if ($user->first())
  481. {
  482. return response()->json(['message' => 'There is already a GitHub account that belongs to you'], 409);
  483. }
  484. $token = explode(' ', $request->header('Authorization'))[1];
  485. $payload = (array) JWT::decode($token, Config::get('app.token_secret'), array('HS256'));
  486. $user = User::find($payload['sub']);
  487. $user->github = $profile['id'];
  488. $user->displayName = $user->displayName ?: $profile['name'];
  489. $user->save();
  490. return response()->json(['token' => $this->createToken($user)]);
  491. }
  492. // Step 3b. Create a new user account or return an existing one.
  493. else
  494. {
  495. $user = User::where('github', '=', $profile['id']);
  496. if ($user->first())
  497. {
  498. return response()->json(['token' => $this->createToken($user->first())]);
  499. }
  500. $user = new User;
  501. $user->github = $profile['id'];
  502. $user->displayName = $profile['name'];
  503. $user->save();
  504. return response()->json(['token' => $this->createToken($user)]);
  505. }
  506. }
  507. }