I've been working for a while on an API-including project. I have an ApiUsersController which handles all user's actions for the API and another API controller.
But I need to ensure that this is secure, so I've created an apiKey() function which detects if the user sending the request to my API has the right credentials.
My question now is where should I put the apiKey() function in order to make use of it in any API controller?
Any API security recommendations are also very welcomed.
Thank you in advance!
My question now is where should I put the apiKey() function in order
to make use of it in any Api controller?
Easy to answer, the correct place is an authentication adapter. Ceeram has already created a token (that's what you're using) adapter for CakePHP. See this link here.
If you want a more secure way you should go for OAuth as suggested by Dave. But instead of using a specific OAuth plugin I would go for Opauth for CakePHP, it comes with an OAuth Strategy adapter.
Also instead of creating API controllers I would use prefix routing and share most of the code for the API actions with the normal actions in a model. This way it can be reused very easy and no need to duplicate work.
Related
First important information: I’m new to Laravel, so your patience is appreciated.
I’m currently migrating a framework of mine to Laravel and still in the early stages. I know that Laravel has it’s own database construction mechanism that is recommended to use the migrations and the Models, however, for my purpose, I’d like to use my own database that I use in other systems that I’ve built in the past. The idea for this system is to have a shared database, but operable through different tech stacks.
This is my current scenario:
Laravel 8
Sanctum 2.14
Frontend (Laravel):
I’ve built a very simple login page that has a controller and sends data (user and password) to my backend (Laravel). In the backend (different server), I grab the data and check if the data is correct. Being correct, I send a json response with some data, like:
returnStatus = true
loginVerification = true
IDCrypt = asdfasd4fa654sd54a (encrypted ID to grab in the frontend again)
Up till here, it’s working fine, as I wanted and very similar to my legacy systems.
My idea would be to get this response in the frontend, via auth token managed by Sanctum and use a middleware to check the token in order to let the user access some web routes.
I’ve watched some videos, but I’m only finding videos that use all the database mechanism that Laravel provides.
However, my intention would be to generate the token with data from my own table and data objects I created (without any existing Laravel´s models).
Is there a way for me to do this?
How would I set the token in the backend and include in my response?
How would I grab the token in the frontend in a secure way?
Lets say you have a model LegacyUser and this is your existing authenticable entity.
In this model simply override methods defined in the Laravel\Sanctum\HasApiTokens trait. Specifically createToken and the tokens relation for your use case by the sounds.
Then you can create tokens anywhere like usual with
$user = LegacyUser::find( $id );
$token = $user->createToken('token-name');
Then us the token as usual.
NOTE: if you're also changing how the tokens are stored/retrieved you'll need to set the token model, docs cover that here: https://laravel.com/docs/8.x/sanctum#overriding-default-models
If you want to avoid using authenticable entites (ie, no laravel models) entirely that's going to be more complicated and Passport might be a better shout, as client_credentials dont need to be associated to a user entity.
Alternatively: Write your own middleware that is compatbile with your existing auth process.
I am building a weather app with laravel(almost finished) and i decided to implement the frontend with react/redux/react-router and use laravel from api calls. The only thing that i decided to leave the same is my custom laravel auth implementation with routes and views. However, i struggle to find a secure way to pass my Auth::user object after login in order to store on redux. I have 2 options:
1) After login and before render the main jsx, to make an axios request to specific route in order to return the Auth::user like:
in routes.php
Route::post('/auth/user' ,function(){
return response()->json(['user'=>auth()->user()]);
})->middleware('auth');
in js
axios.post('/auth/user').then((res)=>{console.log(res.data.user)}).catch((e)=>{console.log(e)})
2) pass Auth::user with blade, catch it with getAttribute, save it to redux and instantly remove from DOM:
<div id="app" data-usr="{{ auth()->user() }}"></div>
However neither of them seem to me like a secure way to pass this kind of data. Can anyone tell me his opinion about this or figure me with a better solution?
Thanks a lot.
I would create a Class to represent the user with just the vital information I need to show on the front-end.
So instead of passing auth->user() to the front, you can inject it into a decorator and generate a simpler user class with just the methods you wish to display.
Thankfully i found a solution with API TOKEN implementation built-in with Laravel. Also i destroy token after logout and recreate it in login, so nobody can use it with other services to collect data if he is not signed in
While building my SPA with angularJS, i came to the point where i want to implement user authentication in my angularJS website. However, i have no idea where to start and what the best practices are.
Basically i have a sure that can have one or more roles. I've looked for examples so i could get a basic understanding of how to handle this properly, but so far i've only came across examples that are very simple or are not so secure (like this).
So my question is, how to I implement a authentication service using REST (or custom API urls) to authenticate a user, and then display the user information on the page using angularJS, while also ensuring best security coverage by using (for example) the csrf token from Laravel?
Thanks in advance,
Nick van der Meij
I'm making an AngularJS app and an API RESTful made with Laravel 5 for the backend, and my approach for the authentication was:
Installed jwt-auth. Basically extends the Auth model of Laravel adding authorization with tokens.
Added simple role package to laravel. I used permiso. Has multiple roles/user and permissions/role. Very simple.
Added jStorage to frontend. (you can use AngularJS module instead).
So the steps are:
Frontend send user credentials (email and pass).
Server checks, jwt-auth makes a token to that user and send it backs.
Frontend save the token on the browser storage (no csrf needed with this approach).
All next calls to the API are made with Authorization: Bearer header (or with ?token=... )
I like the same approach that #neoroger takes using JSON Web Tokens with jwt-auth. I used the Satellizer package for storing the token on the front end and to send it along with each request to the API afterwards.
I put together a couple tutorials that show how to implement the two packages if you are interested:
https://scotch.io/tutorials/token-based-authentication-for-angularjs-and-laravel-apps
http://ryanchenkie.com/token-based-authentication-for-angularjs-and-laravel-apps/
I am attempting to build my HMVC codeigniter install into an API centric HMVC (yeah I know!)
I have ion_auth as the authorisation system at the moment.
The way I have it set-up is
MODELS
CONTROLLERS
- API CONTROLLER
- CONTROLLER
VIEWS
With the API controller accepting JSON encoded inputs and sending JSON encoded outputs.
Now - it all works fine -> I can access the API by calling controller/api and can pass it JSON and receive JSON back.
I then just call the controller/api from within my normal controller
My problem now comes with authorisation.
Nobody can access the API if they aren't logged in through Ion_auth (so it is secure) BUT
How do I then expose the API?
I presume I need to go down the O Auth route but I have tied myself in a knot trying to get my head around how I can use O Auth for the API and not impact the performance of my application when accessed via my controller.
It is down to not understanding how O Auth works fully (I can implement it and understand the hand-shakes etc. but the nitty gritty) -> if I found some way of authenticating a user via O Auth (I mean a site user not an API user) how does this carry through to my controllers - is it stored in a session? Can I give my controllers Authorisations? (Do I need to)
OR - is there a way of doing this with Ion Auth that I haven't heard about?
FOR CLARITY
I want my own application to be able to use it's own API, but do not know how to set up the authrosiation so the API can be consumed directly as well as locally by the application itself (when users are using the site)
HELP!!!!
Thanks in advance!
Maybe you can remove O auth for the API and just create a table of access key. When someone calls the API he needs a key that registered in the table. No ?
Using Promo's answer, plus a little thought after he pointed out the obvious all I did was this:
public function __construct()
{
parent::__construct();
//see if they logged in -> if they are no problem as they are obviously using the page through my application, if they aren't then we do checks for the API
if (!$this->authentication->logged_in())
{
$this->token = $this->input->get_post('token');
//API should have a token set before anything can happen, this is for every request
if($this->token){
//Check that the token is valid
if (!$this->checkToken($this->token)){
$this->error('Token did not match');
}
//all clear if we get to here - token matched
}else{ //no token was found
$this->error('No Token was sent');
}
}
}
I am working on a module to access certain information via REST for an expression engine backend (control panel).
I have worked out the REST function and delivery of the information, that works and tested.
Currently one of my module control panels has several functions that return a set of information while I am logged in and I pass in the session ID along with the request.
However, outside the session I cannot access the API because it redirects me to login instead. I am seeking to bypass the classic authentication for certain controller functions and replace it with a API token based authentication which would be passed with the web request.
I've tried searching how to disable authentication for certain pages in the backend, but haven't been able to find anything. If anyone can point in the right direction it would be very helpful.
Take a look at module actions. These are the URLs that look like /?ACT=123 where 123 refers to a specific module and method in that module. These URLs don't have any authentication required to be hit. You control what authentication you want for the methods.
Stephen Lewis has a nice article about this on his blog (the EE dev docs don't explain actions well, if at all). http://experienceinternet.co.uk/blog/a-brief-introduction-to-expressionengine-actions/
I can personally vouch for this approach with using APIs because our team built a CRUD Rest API for ExpressionEngine that uses these "action" URLs.