Laracasts has a serie for that: https://laracasts.com/series/incremental-api-development
Laravel 5 API + AUTH for a mobile app or another web application
I want to learn how to use laravel as an actual RESTful API with auth.
Something that can be used by a mobile application, or can be accessed and used by other web applications. I've had alot of trouble finding information about how I would do the Authorization portion.
I know that I can make my routes and return JSON objects. The hard part for me to understand is how can I authenticate so I can protect the data in my API unless someone is authorized to use it.
Can someone give me some tips?
The main difference is that you use:
return Response::json([
//array of data
]);
instead of:
return view();
in your controller methods.
@blackbird I've been watching that series and everything makes sense, except this doesn't answer my question. The only authentication covered in this series is "basic authentication", using curl or postman. I'm not sure if basic Authentication is appropriate. It seems like with basic authentication you have to continually re-authenticate each request, and you have to use a username and password in the headers.
@Ruffles I understand the portion about using json instead of views. What I'm hoping is someone can give me some information from experience as the best way to setup authentication.
it seems there are only examples of Basic Auth. What would be more appropriate for a more advanced implementation? Has anybody actually been using laravel to make APIs other then very basic ones?
Look for some OAuth or JWT tutorials. I am not sure if there are any mixing with Laravel but you'll probably find a lot of them using javascript frameworks (Example: Express and Angular). The general things still apply.
@isaackearl I'd highly recommend JWT - https://github.com/firebase/php-jwt
Basically on authentication you create and store a token locally on the device. Then every time you make a call to the server, you check that token and ensure the user is who they say they are.
You can store tokens for expiration if you want, but not required since the data lives in the token.
Typically JWT is used in stateless apps, so you'll need to move away from the concept of a server session.
Thanks for the responses guys. I'm going to checkout JWT
@isaackearl What did you do at the end?
@luddinus I ended up implementing JWT using tymon/jwt-auth (https://github.com/tymondesigns/jwt-auth). It is really nice and getting it setup was pretty easy. It is very configurable as well which has been a nice bonus for us. If you decide to go the same route you can feel free to message me if you need an example.
@isaackearl can you provide an example
@isaackearl Do you how can we implement JWT for two different Authentication tables (One for User Credentials and other for Admin Credentials)
@shivamnetwork is there a specific example you are looking for? If you have a more specific question then I should probably be able to answer. Anyway, I will attempt to give you an example of how I'm using JWT to authenticate.
The examples provided in the wiki are a good start.
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
class AuthenticateController extends Controller
{
public function authenticate(Request $request)
{
// grab credentials from the request
$credentials = $request->only('email', 'password');
try {
// attempt to verify the credentials and create a token for the user
if (! $token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'invalid_credentials'], 401);
}
} catch (JWTException $e) {
// something went wrong whilst attempting to encode the token
return response()->json(['error' => 'could_not_create_token'], 500);
}
// all good so return the token
return response()->json(compact('token'));
}
}
Right here in this example a user authenticates using a username and password, but uses the JWTAuth Facade instead of the regular Auth stuff provided by laravel. At the end this action returns a token that can be used by your frontend to make subsequent requests.
You can then check subsequent requests using middleware to make sure the user has a valid token. Here is the example middleware:
class GetUserFromToken extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, \Closure $next)
{
if (! $token = $this->auth->setRequest($request)->getToken()) {
return $this->respond('tymon.jwt.absent', 'token_not_provided', 400);
}
try {
$user = $this->auth->authenticate($token);
} catch (TokenExpiredException $e) {
return $this->respond('tymon.jwt.expired', 'token_expired', $e->getStatusCode(), [$e]);
} catch (JWTException $e) {
return $this->respond('tymon.jwt.invalid', 'token_invalid', $e->getStatusCode(), [$e]);
}
if (! $user) {
return $this->respond('tymon.jwt.user_not_found', 'user_not_found', 404);
}
$this->events->fire('tymon.jwt.valid', $user);
return $next($request);
}
}
you can then use this middleware for your controllers to make sure they are authenticated first.
This is all pulled from the default stuff provided by the package. This isn't necessarily how I implemented it because each implementation has specific needs. If you have a more specific question I will try my best to help out.
Are you using some sort of multi auth package already? Tell me a little bit more about what you already have and what you are trying to accomplish and I will do my best to give you an answer.
My initial instinct is to tell you to put it all in one table and use roles to determine whether it is an admin or a regular user.
Then again I realize you might have a situation where you really want to keep them in separate tables because they don't have overlapping data other then they both need to be able to login or something like that.
If that is the case then I can recommend some things I've done in the past, but I'd like to know a bit more about your situation before I spend a bunch of time writing examples you might not need etc.
I am not using Multi auth package.
I have two entities/tables - One is Merchant and Other is Customer. Even Merchant user can be a customer for another merchant so the email_id will be same so I am not keeping the same table and using roles here. There are different custom claims based on different entities. I am looking to have two different tables here.
I have implemented as Sean has written in the wiki - https://github.com/tymondesigns/jwt-auth/wiki and you have written in the above reply. It's working fine for one entity/table. I am stuck about how to use with different entity.
Well, this jwt auth package is supposed to have one table that represents the user. It uses various functions like JWTAuth::toUser() etc that reads the user type from your jwt.php config file. But that doesn't mean that you have to change your structure.
This is how I would approach it if I were you.
I would create a separate users table from your customer and merchant table, and move the common elements in there such as password, and email or username. From what you said above you might already have a seperate table with emails in it, you might be able to use that..
Anyway, once you create that table, you add 2 columns to make a polymorphic relationship to the 2 types of models that need to be able to authenticate. so for example the users table would have an authenticatable_id and a authenticatable_type.
user morphs to either a customer or a merchant
// in User model
public function authenticatable()
{
return $this->morphTo('authenticatable');
}
merchant and customer both access one morphed user
// in Merchant model and Customer model.
public function user()
{
return $this->morphOne('App\User', 'authenticatable');
}
then you can authenticate using a user from the User model.. but directly afterwards you can use your Merchant model or your Customer model ($user->authenticatable returns either a merchant or a customer in this scenario). To go the other way you can simply say $customer->user to get the user properties.
you can setup different login portals and just make sure that the authenticated user has the correct type.
if ($user->authenticatable_type == 'App\\Merchant')
if you already have all the user email stored on customer and merchant and you don't want ot move common elements out, you could still make a User model with the same relationships.. but instead of accessing properties like $user->password, $user->email etc... you could create an interface and impliment it in both customer and merchant models. You could provide methods for getPassword, getEmail etc, so that way from your user model you can just say $user->getEmail() and it knows how to grab the email field off of the merchant or customer table.
If this is something that sounds like a good approach to you and want more help/clarification when you run into problems let me know. If not then I'm sorry I couldn't help out more, I don't know of another way to use 2 completely separate tables with this particular package.
@isaackearl Thanks for your reply.
Can I do it something like this? Users table with role_type
I have two login pages for both merchant and customer.
If I login from Merchant, I want users where role_type = 'Merchant' and same for 'Customer' But here is the catch. Merchant can be customer also with the same email Id.
- xyz@gmail.com | .... | Merchant
- abc@gmail.com | ... | Merchant
- xyz@gmail.com | ...| Customer
@isaackearl Is the token secure over http? seems not immune to man in the middle
Can this framework support once we get the token, we use token in the client to sign the data and generate the signature and only send the signature over the wire
and at server side, server uses same token and data to generate the signature and compare with the signature sent by client?
Roger
@rogeryu23 this article will give you an excellent understanding of the JWT architecture. Enjoy ;)
when the token is created it gets signed so the server knows that it is valid. This doesn't mean that it isn't vulnerable, but if you are worried about someone getting a token and figuring out how to exploit it in the time before it expires, you can choose the option to refresh the token on each request which makes it much more secure.
at this point you might want to consider using a rule package of some sort. You could have users and assign roles to them like
$user->assignRole('Merchant');
and use it like
$user->is('Merchant') // true or false
This is useful because you could simply assign 2 or more roles to users that you want to be both a merchant and a customer. that way you know what parts of the site they have access to.
Here is one I recommend highly: https://github.com/kodeine/laravel-acl
@isaackearl how are you? I need some help with jwt. i get this error {"error":"token_not_provided"} .
i'am creating an IOS APP and need work with tokens alright?
i'am trying to do something here...
CartasController.php
public function __construct()
{
$this->middleware('auth');
}
public function index() {
// dd(\Request::all());
// return view('cartas');
echo "ÍNDICE DA CONTROLLER CARTAS";
}
public function getCarta() {
// $carta = Cartas::where('carta_id', 1)->get();
// echo json_encode($carta);
//echo json_encode($dados);
echo "FUNÇÃO GETCARTA DA CONTROLLER CARTA";
}
routes.php
Route::get('cartas/getCarta', ['middleware' => 'jwt.auth', 'uses' => 'CartasController@getCarta']);
how can i do it? i don't understand the use of jwt-auth =S
hi, I was trying to connect an android app with my laravel web app using jwt .the idea was to
- receive a token and save it
- make a request with the token in header when i access the route using browser it returns a token but when i use 'chrome postman app' it returns token miss match
can anyone help please ... thank you :)
@Mhr did you ever figure out your issue? I'm looking into similar idea so I'm curious how you went about it.
It seems its been a while since this thread was created. Just an update on the Tymon package: following the wiki instructions of Tymon's packaged on Lumen 5.2 didn't seem to work without extra effort resolving DI issues.
It seems to be a problem with storages's container. Either the package expected Lumen to work the way Laravel does or something else. Remember Lumen is lightweight t and does not necessary have all the arsenals of full Laravel. So my heads up is to before start working on Lumen with this package first check the Issues tab of the project and make sure yourselves you dont stumble with the integration.
Since I did not have the time to resolve any potential container issues I've decided stepped aside and started working on custom for my app with a raw firebase/php-jwt.
- Jaz
I have similar question: http://stackoverflow.com/questions/36974163/laravel-rest-authentication-when-post-via-httpclient-android
I am interested with JWT. I will do a research about this. Hopefully there are any folks who will guide us.
I have the same situation :( What about authenticating facebook_id & access_token when they being sent to Laravel backend and return user's details in JSON format? How do I write an API for that? Any ideas would be appreciated!
Hi. I have read about JWT, and I understand the following:
- The user perform a first request with credentials, and the server generate and reponse a token.
- The user will use the token received in the header for the next requests.
I hope that someone can help me with my questions:
-
JWT reduces the amount of requests that contains the credentials, but the first request is vulnerable?
-
If the first request can be protected using HTTPS, then, why we have to use a token instead of the credentials?
Thank you all.
hi https://packagist.org/packages/skygdi/devicetoken I make one. you can try it.
Anyone interested in JWT, might want to look at this first. I'm also building an API to serve web, ios, windows, android. http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
Decided to just go back to regular server-side sessions.
Thanks @isaackearl but $this->auth->authenticate($token) line is outdated and I don't know how fix it.
Call to undefined method Illuminate\Database\Query\Builder::getAuthIdentifierName()
Please or to participate in this conversation.