How to hide my Unsplash api key in Laravel - laravel

How to hide my Unsplash api key in Laravel
I am making a call from a Vue component but my "Authorization id" api key is visible for everyone as you can see.
How can I hide the API key in Laravel? I am using Laravel 9.
I want to hide the "headers or just the "Authorization".
Hope someone can guide me :))
Unsplash.vue file:
const myAsync = async function fetchUnsplash() {
const response = await fetch('https://api.unsplash.com', {
headers: {
Authorization: 'Client-ID 1234',
},
});
};

I don't know anything about the API that you are using, nor about Laravel, but I assume, you have a fixed string, that you have to send in the HTTP requests.
Because you mentioned you are using Laravel, you have both frontend and backend code.
So in my opinion
you can create a new endpoint in your Laravel REST API: v1/entries
In the PHP code, you have to call the https://api.unsplash.com API, with the secret Client ID.
From the Vue component, you have to send your request to your Laravel API endpoint (example: http(s)://<api-baseurl>/v1/entries).

Related

Call laravel controller from vue file

I created a component in vue file and I want to fetch data from laravel controller function.
Currently, I have used axios to fetch data. But can I directly call laravel controller function?
Thanks in advance.
No, the only way to communicate with your laravel app is your web service. ( Ex: REST Api )
Because Laravel and Vuejs are completely separated.
Although in using web services you would have different methods.
Expose a route from Laravel/Lumen app
Call the route or url from vue using any http client(axios)
N.B: You cann't call the controller method on Laravel app directly from your Vue CLI
You need to do few steps.
in vue js file script area
const url = `https://www.naveedramzan.com/api/getData/users/4`;
Axios.defaults.headers.common['Authorization'] = `Bearer ${params.token}`; // if you are using some token authentication
Axios.get(url,{params: params})
.then((response) => {
res(response.data);
})
.catch((err) => {
rej(err);
});
In laravel, routes/api.php file
Route::post('getData/users', 'UsersController#getData');
In laravel, the controller file
use Illuminate\Http\Request;
public function getData(Request $request){
....
}

Verify user email without redirecting to RESTFUL API in Laravel

I have an http client what consumes an restful api both of them on Laravel, I need to verify the email of the user without redirect to the API.
I already have an EmailVerifyNotification in my resftul api exactly equal to the given for Laravel, but I can't custom the URL.
The situation is that the user requests to forward the mail to verify it from the http client to the api, the api processes the request, creates and sends the mail but sends it in relation to the path defined in the api, in this case:
// RESTFUL API routes/api.php
Route::name('verification.verify')->get('email/verify/{id}/{hash}', 'User\UserController#verify');
Example:
By clicking a button the user on the client side call a controller what do an http request to the api:
// this call a restful api route from the http client
// restulapi.com/email/resend
return $this->makeRequest('GET', "email/resend");
on the restful api I have a controller what call a notification equal to the given for Laravel, but that use a route verification.verify what I have to define on the routes of the api:
// RESTFUL API App/Notifications/VerifyEmailNotification
protected function verificationUrl($notifiable)
{
return URL::temporarySignedRoute(
'verification.verify', <----- I need to change this
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
[
'id' => $notifiable->getKey(),
'hash' => sha1($notifiable->getEmailForVerification()),
]
);
}
//
// RESTFUL API routes/api.php
// the button to verify the email call this route -> restfulapi.com/email/verify/{id}/{hash}
// but i need -> httpclient.com/email/verify/{id}/{hash}
Route::name('verification.verify')->get('email/verify/{id}/{hash}', 'User\UserController#verify');
The point its verify the user email without move from the http client.

Good practices to manage user session data with vue and laravel API

I am building a single-page application with Vue and laravel API as backend.
I've tried some packages like Vue Session and it worked well, however in almost every API call I always need to send 2 or 3 parameters that will always be the same (stored in vue-session), like user_id and company_id. I used to manage this with common PHP sessions (Zend_Session with Zend Framework) in my other applications, this way I always have that information stored in my backend session and don't need to send it every time by the frontend
Here's an example of how I used to do it with PHP session
$model->insert(array(
'user_id' => $this->session->user_id, //stored in session
'company_id' => $this->session->company_id, //stored in session
'field1' => $this->getParam('field1'), //frontend param (ajax)
'field2' => $this->getParam('field2') //frontend param (ajax)
));
And here's how I'm doing it with Vue and Laravel
const data = {
user_id: this.$session.get('user_id'), //this is what i'm trying to get rid of
company_id: this.$session.get('company_id'), //this is what i'm trying to get rid of²
field1: this.field1,
field2: this.field2
}
axios
.post('/api/some/endpoint', this.data)
.then(resp => {
//...//
})
Basically, in this example I want to not need to always send user_id and company_id as a post param.
Is there any way to get better code "reuse" in cases like this?
1, You can save your session data in the cookie. The browser will automatically send your cookie to the server. Don't forget to delete the cookie when the user logout.
2, If you still want to use Vue session or other storages, you can easily create a method that wraps your post method and add user's information to the payload
function postRequest(url, payload) {
payload.user_id = this.$session.get('user_id')
payload.company_id = this.$session.get('company_id')
return axios.post(url, payload)
}
Use this method whenever you want to make a post.

Is this a proper Laravel Passport use case?

So think of my application as a CMS (laravel 5.7). I'm slowly adding in more javascript to make it more reactive. So I had the usual validation logic that makes sure the user is logged in and all that. But now when I use Vue to submit a comment payload it looks a little like this:
So looking at this, anyone could just change/mock the this.user.id to any number, I would like to also send a login token with the payload which then gets validated in the backend once the server receives the post request.
In the backend, ideally I'd want to have some kind of safe guard that it checks whether the api_token of the user matches with this.user.id to ensure the user.id wasn't mocked on the front end.
I read this portion: https://laravel.com/docs/5.7/passport#consuming-your-api-with-javascript
Part of it says:
This Passport middleware will attach a laravel_token cookie to your outgoing responses. This cookie contains an encrypted JWT that Passport will use to authenticate API requests from your JavaScript application. Now, you may make requests to your application's API without explicitly passing an access token:
But I'm still a bit unsure how that JWT gets generated in the first place. I don't have the vue components for the create token crud added because I want it to be done automatically. I think I'm slightly overthinking this..
Is this a good use case for Laravel Passport? I was looking through the tutorial and right now I don't have a need for custom oauth token creations and all the crud. I just want a unique token to be saved on the user side, that can expire, but also be used to validate requests. Am I on the right track here with Passport or should I use a different approach?
postComment(){
axios.post('/api/view/' + this.query.id+'/comment',{
id: this.user.id,
body: this.commentBox
})
.then((response) =>{
//Unshift places data to top of array, shifts everything else down.
this.comments.unshift(response.data);
this.commentBox = '';
document.getElementById("commentBox").value = "";
flash
('Comment posted successfully');
})
.catch((error) => {
console.log(error);
})
},
Update - Reply to Jeff
Hi! Thanks for your answer. It's not an SPA (might be in the future), but the comment box and the comment section is also integrated with websockets and there's a laravel Echo instance on it.
I guess where I'm feeling uncertain is the security of it.
I pass a user prop with :user="{{Auth::check() ? Auth::user()->toJson() : 'null'}}" into the vue component that contains the postComment() function.
This is where the id: this.user.id comes from. The route is defined in the api.php in a route middleware group for ['api'] like so:
Route::group(['middleware' => ['api']], function(){
Route::post('/view/{query}/comment','CommentController#store');
});
In my controller which calls a service to create the comment, the $request
public function makejson(createNewCommentRequest $request, Query $query){
$comment = $query->comments()->create([
'body' => $request->get('body'),
])->user()->associate(User::find($request->id));
$id = $comment->id;
$comment->save();
}
The createNewCommentRequest is a FormRequest class.
For now the authorize() function just checks whether the request()->id is an int:
public function authorize()
{
if(is_int(request()->id)){
return true;
}
return false;
}
From within there if I log the request(), all it outputs is:
array ( 'id' => 1, 'body' => 'gg', )
I thought I would need to add logic to authorize the request based on whether the user token and the request() yield the same user id? I'd want to avoid the scenario where someone can modify the post request and comment using another users id.
In the Network section of devtools, in the Request headers, i see it pushed a laravel_token cookie. I'm assuming that laravel_token is what stores the user session? If so, how would one validate based on that token?
I was playing around and added the route:
Route::get('/token', function() {
return Auth::user()->createToken('test');
});
When I went to it i got the following:
{
"accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImE4NDE2NGVkM2NkODc5NDY3MzAxYzUyNmVkN2MyMGViZTllNzJlMGMzMjRiMmExNWYzZDgwZGNmMzEzMDk1MTRmNTY1NGMxYWUwMTE2ZGRkIn0.eyJhdWQiOiIxIiwianRpIjoiYTg0MTY0ZWQzY2Q4Nzk0NjczMDFjNTI2ZWQ3YzIwZWJlOWU3MmUwYzMyNGIyYTE1ZjNkODBkY2YzMTMwOTUxNGY1NjU0YzFhZTAxMTZkZGQiLCJpYXQiOjE1NDY1NTQzNDEsIm5iZiI6MTU0NjU1NDM0MSwiZXhwIjoxNTc4MDkwMzQwLCJzdWIiOiIxIiwic2NvcGVzIjpbXX0.NMETCBkOrMQGUsXlcas6CvTFJ0xRC8v4AJzC5GtWANdl8YsPBGlyCozMe1OGc8Fnq8GC_GZFkKmMT27umeVcSyaWriZB139kvtWzY6ylZ300vfa5iI-4XC_tJKoyuwDEofqMLDA4nyrtMrp_9YGqPcg6ddR61BLqdvfr0y3Nm5WWkyMqBzjKV-HFyuR0PyPQbnLtQGCzRFUQWbV4XWvH2rDgeI71S6EwmjP7J1aDA2UBVprGqNXdTbxWpSINMkZcgrDvl4hdqNzet-OwB2lu2453R-xKiJkl8ezwEqkURwMj70G-t9NjQGIBInoZ-d3gM2C3J9mEWMB5lyfSMaKzhrsnObgEHcotORw6jWNsDgRUxIipJrSJJ0OLx29LHBjkZWIWIrtsMClCGtLXURBzkP-Oc-O9Xa38m8m6O9z-P8i6craikAIckv9YutmYHIXCAFQN2cAe2mmKp7ds1--HWN_P5qqw6ytuR268_MbexxGDTyq8KzUYRBjtkgVyhuVsS7lDgUHgXvJfHNmdCulpiPhmbtviPfWaZM19likSjKHLTpIn2PpfTflddfhB9Eb4X24wGH7Y5hwxASe7gDs_R707LphS1EH4cTE8p2XW_lLv0jo89ep9IUPUO27pWLsqabt8uTr5OoKQeNZmXT6XiJ9tK3HhRgvIt7DYt8vqlRw",
"token": {
"id": "a84164ed3cd879467301c526ed7c20ebe9e72e0c324b2a15f3d80dcf31309514f5654c1ae0116ddd",
"user_id": 1,
"client_id": 1,
"name": "lol",
"scopes": [],
"revoked": false,
"created_at": "2019-01-03 22:25:40",
"updated_at": "2019-01-03 22:25:40",
"expires_at": "2020-01-03 22:25:40"
}
}
Now in Postman, when I send a get request to:
Route::middleware('auth:api')->get('/user', function (Request $request){return $request->user();});
I added a authorization header of type Bearer Token for the string captured in the variable: accessToken. In return I get the user, no issue. However where and how is the accessToken generated? It's not saved in the database?
Take the user ID that Laravel gives you from the token, rather than sending it from the front end. You can also check the scopes assigned to the token:
Route::post('/api/view/{query}/comment', function (Request $request, Query $query) {
if ($request->user()->tokenCan('comment-on-queries')) {
$query->comments()->create([
'body' => $request->get('body'),
'user_id' => $request->user()->id,
]);
}
});
If this isn't a single page app, and only the comment box is handled by ajax, the default Laravel scaffolding should handle this by adding a CSRF token to axios config. In that case you don't need Passport, because the user is stored in the session. Still though, don't take the user ID from the front end, get it from \Auth::id()
Here's the key difference: If they login using PHP, your server has a session stored and knows who is logged in.
If you are creating a single-page app separate from your Laravel app, you have to rely on Passport and tokens to ensure the user has the authority to do what they're trying to do.
Figured it out, was overthinking it. Basically didn't need a whole lot to get it working.
Added the CreateFreshApiToken middleware to the web group in app\Http\Kernel.php.
The axios responses attach that cookie on the outgoing responses
The api middleware group had to be 'auth:api'.
The user instance can be then called via request()->user() which is awesome.

laravel api using passport to fetch data from product?

Need help to fetch data from product table using sql query in laravel
via laravel passport api authentication.
Create a route in your api.php
Route::middleware(['auth:api', 'throttle:60'])->group(function () {
Route::get('products', 'Api\ProductController#getProducts');
}
Write the getProducts function in your ProductController
public function getProducts(){
return Product::all();
}
Send a get request into /api/products with Authorization header. Its value will be your access token. Do not forget to add 'Bearer ' before it. (there is space between your access token and Bearer word).
I recommend you to use Postman for this job.
handle access token using laravel passport api authentication.

Resources