How should I make sure that the user who accesses the third-party interface is authenticated?

I use Laravel and Angular to write a web application.

At the front, Laravel is used to create a basic template, but is otherwise managed by Angular. At the back, laravel is used to create a soothing API.

I have several routes like this:

Route::group(['domain' => 'domain.com'], function() { Route::get('/', ['as' => 'home', function () { return view('homepage'); }]); Route::get('/login', ['as' => 'login', function () { return view('login'); }]); //users should be authenticated before accessing this page Route::get('/dashboard', ['as' => 'dashboard', function () { return view('dashboard'); }]); }); Route::group(['domain' => 'api.domain.com', 'middleware' => ['oauth']], function() { Route::post('/post/create', ['uses' => ' PostController@store ']); Route::get('/post/{id}', ['uses' => ' PostController@show ']); //other API endpoints // ... }); 

I want to make sure my domain.com/dashboard URL is only available to authenticated users.

In my backend, I have OAuth implemented for my routes API, which ensures that the user accessing these routes is authentic. Laravel Auth::once() used by the OAuth library to verify that the user credentials are correct, and then generates an access_token . Since Auth::once() is a stateless function, no session or cookies are used, and I cannot use Auth::check() to make sure the user is authenticated before the panel page is displayed.

How can I check if a user is trying to access domain.com/dashboard ? Should I send the access_token in the header when I forward the user from /login to /dashboard ? Or should I implement Laravel session / cookie based authentication?


EDIT: Accordingly: Adding http headers to window.location.href in an Angular application I cannot redirect a user to a control panel page using Authorization .

To reuse my API for mobile apps, I highly recommend using some token based authentication.

+5
source share
5 answers

@Pierre Cordier @Mr_Antivius Thank you guys for your answer, it helped me figure out the problem and allowed me to mess with JWT, but in the end did not work out a solution for me.

To allow only authenticated users access to domain.com/dashboard , I had to implement a hybrid session and OAuth authentication system. I decided to go with Sentinel (instead of Laravel from the auth system) because it has a user permission system that I need elsewhere in my application. I use this library for an OAuth server.

Here is what I do in the controller:

POST domain.com/auth/authenticate :

 public function processLogin(Request $request) { $credentials = [ 'email' => $request->input('username'), 'password' => $request->input('password'), ]; try { $sentinel = Sentinel::authenticate($credentials); } catch (\Cartalyst\Sentinel\Checkpoints\ThrottlingException $e) { $response = ['error' => [$e->getMessage()]]; $httpStatus = 429; return response()->json($response, $httpStatus); } catch (\Cartalyst\Sentinel\Checkpoints\NotActivatedException $e) { $response = ['error' => [$e->getMessage()]]; $httpStatus = 401; return response()->json($response, $httpStatus); } if ($sentinel) //user credentials correct { //get oauth token $oauthToken = Authorizer::issueAccessToken(); $response = ['success' => true, 'user' => ['id' => $sentinel->id, 'email' => $sentinel->email]] + $oauthToken; $httpStatus = 200; } else { $response = ['success' => false, 'error' => ['Incorrect credentials']]; $httpStatus = 401; } return response()->json($response, $httpStatus); } 

Here is the method that the OAuth library executes to authenticate the user:

 public function verifyAuth($email, $password) { $credentials = [ 'email' => $email, 'password' => $password, ]; if ($user = Sentinel::stateless($credentials)) { return $user->id; } else { return false; } } 

This will create a response like this:

 { "success": true, "user": { "id": 1, "email": " email@domain.tld " }, "access_token": "6a204bd89f3c8348afd5c77c717a097a", "token_type": "Bearer", "expires_in": 28800, "refresh_token": "092a8e1a7025f700af39e38a638e199b" } 

Hope this helps someone out there.


Side note: I am sending a POST request to domain.com/auth/authenticate instead of api.domain.com/auth/authenticate because I could not get domain.com/dashboard to recognize the cookie sender if I sent it to api.domain.com . I tried changing the domain in config/session.php to .domain.com , but still nothing. Maybe I'm doing something wrong?

+1
source

I would suggest using JWT ( JSON Web Tokens ) for authentication.

I think there are several tutorials for using them with Lavarel and AngularJS . I am more in Python and I use Flask , but the following are interesting:

+4
source

Pierre was right in offering JWT for your auth based token.

When the user successfully logs in before completing the request, you can create a JWT and pass it on to the client. You can save it on the client (localStorage, sessionStorage) if you want. Then, in subsequent requests, install the JWT inside the authorization header. You can then check this header in the middleware and prevent access to your API routes if the token is valid. You can also use this token on the client and prevent Angular from switching routes if the token does not exist or is invalid.

Now, if you are trying to prevent the user from accessing the page completely at boot (opens a browser, goes directly to domain.com/dashboard), then I believe that this is impossible, since there is no way to get information about the client without first downloading The first code on the page.

+3
source

Not sure about Angular since I never used it, but have you tried targeting the controller using your panel’s route? for instance

 Route::get('/dashboard', [ 'uses' => ' UserController@getDashboard ', 'as' => 'dashboard', 'middleware' => 'auth' ]); 

UserController.php (I assume you have a blade called dashboard.blade.php)

 <?php namespace App\Http\Controllers; use Illuminate\Support\Facades\Auth; use Illuminate\Http\Request; use Illuminate\Support\Facades\Session; class UserController extends Controller { public function getDashboard() { if(Auth::user()) { return view('dashboard'); } else { redirect()->back(); } } } 

In addition, you can always group the routes you want to protect with this (taken from the Laravel 5.2 documentation ):

 Route::group(['middleware' => 'auth'], function () { Route::get('/', function () { // Uses Auth Middleware }); Route::get('user/profile', function () { // Uses Auth Middleware }); }); 

EDIT. As for the session token, your login should have this in its code:

  <input type="hidden" name="_token" value="{{ Session::token() }}"> 
+2
source

When the HTML / dashboard is loaded, does it already include data specific to the user account?

I would suggest downloading the HTML / dashboard separately from user data and hiding control panel items using ng-cloak , and Angular loads the data to populate it.

  • Redirect to Control Panel URL
  • Load (static?) HTML / Angular toolbars, hiding all parts with ng-cloak.
  • Have Angular access the API using access_token to load all control panel data.
  • Display parts of the control panel when receiving data from the API or display an error message if access_token is invalid.

Thus, your HTML code can be just a static HTML file and be directly served by a web server and cached by any proxy server along the way.


If this is not an option, you can put your access_token in a Javascript cookie that runs in the / login view, then redirects to / dashboard, and then your server / dashboard view reads the cookie to check if access_token is valid. But it sounds dirty and mixes things that need to be shared.

+1
source

Source: https://habr.com/ru/post/1244780/


All Articles