How to retrieve User Access Token After Creation in Laravel [closed] - laravel

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I can generate user access when I log in or Register a User
I want to be able to use the token later in API
I have questions
Is it safe to store user access token in the database after creation
How do I retrieve access token after creation
I tried this
public function showprofile(Request $request)
{
$user = new UserResource(User::find($request->id));
$token = $user->token();
dd($token);
// return response ($user);
}
It returned null, I have checked oauth access token table, the user id I am sending is present.
Thanks.

1) yes, this is no problem. In fact, if you're using Laravel Passport, it will be done automatically. Passport's default migrations will make sure it's stored in a safe way. You can optionally publish the migrations yourself to adjust them if needed:
php artisan vendor:publish --tag=passport-migrations
2) If you've added the HasApiTokens trait to your user model. You'll be able to access the token like this:
$user->token()
Or if you need all tokens $user->tokens(). More info can be found in the passport documentation.
Update
You're trying to access the token on the UserResource. This doesn't contain the token(). Try to access the token before creating the resource like this:
public function showprofile(Request $request)
{
$user = User::find($request->id);
$token = $user->token();
$user = new UserResource($user);
dd($token);
// return response ($user);
}
Also, I'd recommend you to use Route Model Binding. This will make your controller much cleaner since you don't need to look up the model yourself, Laravel will do this automatically for you.

Related

What is the best practice to tell to fronted app which Laravel routes are allowed for user roles? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 days ago.
Improve this question
I have a back-end application in Laravel 9 and another front-end application in React.
In back-end application there are multiple user roles and permissions created and, for each route in routes/api.php file, is added a middleware to specify the permission.
Note: Multiple roles can be assigned to a permission.
Example:
Route::get('countries', [CountriesController::class, 'index'])->middleware( ['permission:view-countries']);
So In this case only users with roles which are assigned to permission view-countries can access the route /api/countries.
Front-end application has buttons or links and requests to Laravel are made when clicking on them. I need to know if logged in user on front-end have access to those requests before making the requests in order to show or not the buttons or links. I'm thinking to send a list of routes to the front-end, after log in, which are available for that user. Maybe another solution?
there is no standard way of doing what you are asking, this solely rely on your setup, data, and environment. like how many permission you have, how many routes will be part of the conditional buttons etc.
The easier approach you can do is simply grab the user role/permission when fetching the user from initial request, you store that user data somehwere inside your front-end app, then check the data for displaying those buttons or not.
If you want to grab all the routes avaible for permission based middleware, you can use Route::getRoutes() and filter them based on the middleware you pass.
here's an example which you can improve
//Get all permission of current user
$userPermissions = $request->user()->permissions;
// format them like the route middleware
$permissionsMiddleware = collect($userPermissions)->map( fn($item) => 'permission:'.$item )->toArray();
//should look like
// ['permission:permission1', 'permission:permission2', 'permission:view-countries']
//Grab all the Routes by route name
$allRoutes = collect( Route::getRoutes()->getRoutesByName() );
$userAllowedRoutes = $allRoutes
// format the data to only have middleware, path and name
->map( fn($route, $key) => [
'middleware' => $route->gatherMiddleware(),
'path' => $route->uri,
'name' => $key
])
// filter to only return routes that has middleware present on $permissionMiddleware
->filter( fn( $route ) => array_intersect( $permissionMiddleware, $route['middleware'] ) )
//remove the collection key
->values();

REST API Security for access only to API [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
My spring boot app almost done and one more problem left. I need to implement security part. I wanna make acces to api only by key that will come with request. in URL string, message body or header.It doesnt meter now. I found a lot of different ways, but they use login:password pair, it doesnt interesting for me. Each message have to contain KEY.
It should look like
URL String (Get method)
https://api.domen.com/news/today?key='somekey'&'some filters'
Body (Post method)
https://api.domen.com/news/today?'some filters'
{
"key": "somekey",
...
}
Is there suggestion how use only key and verify it?
I would include the token on HTTP Authorization header with the Bearer schema (instead that using a parameter), it is a good practise
POST /news/today?p=1 HTTP/1.1
Authorization: Bearer 123456
If you want to rely on JTW (again a standard practise) you need to verify the incoming token, this is an example using jsonwebtoken library
Claims claims = Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary("SECRET"))
.parseClaimsJws(jwt).getBody();
String subject = claims.getBody().getSubject(); // subject in the token
Date date = claims.getBody().getExpiration(); // expiration of the token
This example above assumes that the token (set on the HTTP header) has been signed using the same key "SECRET"
//We will sign our JWT with our ApiKey secret
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("SECRET");
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
//Let's set the JWT Claims
JwtBuilder builder = Jwts.builder().setId(id)
.setIssuedAt(now)
.setSubject("subj")
.setIssuer("issuer")
.signWith(signatureAlgorithm, signingKey);
Here is a good reference https://developer.okta.com/blog/2018/10/31/jwts-with-java

How to make custom authentication on Laravel?

I have a Laravel application, with a login form. I am using subdomains, for example: {{business_subdomain}}.laravel.test. The purpose of my application is create companies in my database, and make registered users login on their attached company and specific domain.
So in my web.php I declared the following:
Route::domain('{business_subdomain}.' . env('APP_URL'))->middleware(['business.subdomain'])->group(function ()
My database contains the following tables:
* Standard tables like users
* Businesses which contains id, name and subdomain
* Business_user which contains business_id and user_id
The business_id (business_user table) has a relationship with id (business table)
The user_id (business_user table) has a relationship with id (users table)
I created a middleware that checks the following:
$business = $request->user()->businesses->where('subdomain', $request->route('business_subdomain'))->first();
So the subdomain value (business table) must be the equal to the URL/route subdomain value, otherwise when you login, you will get an 403 page.
So what I want to achieve: When a user has an account, but is not attached to the right company/business, I want to display the standard authentication error: These credentials do not match our records.
I've tried to use the code in my middleware on the LoginController and override almost every function separately, but it didn't work.
Do I need to override Laravel authentication functions, do I need to create another middleware or use Guards?
The laravel authentication login order (the order the application uses for logging in a user) seems very confusing for me.
Maybe someone can provide me with more information or help me out!
I tried to use the code in my middleware on the LoginController and override almost every function separately, but it didn't work.
Sounds like you might be looking for multi-tenancy. There are a couple different packages available, both for single and multi-database setups.
Here are some very informative slides on the topic, specific to Laravel. And an excellent article for more detail.
We have a similar application with subdomain routing using torzer/awesome-landlord. The tenant package ensures that login will only search for users of the correct tenant.
To set the correct tenant we added a middleware (App is the tenant, in your case it would be Business):
public function handle($request, Closure $next)
{
$subdomain = $this->getSubdomain($request->server('HTTP_HOST'));
if ($subdomain) {
$app = App::getBySlug($subdomain);
abort_if(!$app, 404);
$this->tenantManager->addTenant($app);
} else {
// empty or generic subdomain
// this is OK as long as there is no user
if ($user = $request->user()) {
return $this->redirectToUserAppSubdomain($request, $user);
}
}
return $next($request);
}

How to get data from JWT if didn't have users table in laravel?

I try to implement microservice arhitecture.Because I new in it,can maybe someone can tell me:
- can I use JWT for communication to services,when someone login into one service.Is that secure way or there is something better?
- how do I parse JWT and get user id or some other data from it to have it in other service which didn't have users table?Like is it expiried,user id...
Thank you a loot if someone can help me to send me a direction for it.
I'm partial to the tymon/jwt-auth package for this, which largely uses 'namshi/jose' under the hood. As long as the jwt.secret is the same between each system that may need to use the tokens, you should be able to just call JWTAuth::getPayload($token)->toArray() to decode them.
You do need a user table, but it doesn't have to be the user table already speced out in Laravel. Any Model that implements the Illuminate\Auth\Authenticatable interface, such as by extending the Illuminate\Foundation\Auth\User model will do.
If you want to inject additional data into the token beyond the user table that the login credentials are being validated against, just add an array as the second parameter to the login attempt:
//The key names here are defined by the return values of methods described in the Authenticatable interface.
$credentials = [
'username' => 'your_user',
'password' => 'your_password'
];
$customClaims = [
'someOtherDatapoint' => 'more_data'
];
$token = JWTAuth::attempt($credentials, $customClaims);
You could also go directly to the token-creation without authentication:
$user = app(YourUserModel::class)->first($id);
$token = JWTAuth::fromUser($user, $customClaims);
This is relatively secure, but I'm not sure if it's the best way to communicate encrypted data. You might want to just use the encrypt() and decrypt() helper functions, that are based off the APP_KEY. You could also look at Laravel-Passport, https://laravel.com/docs/5.6/passport, for authentication, which uses OAuth2.

Laravel 5 user role check before

I have some trouble figuring out how to do this properly.
I have Users that can create Articles which can be viewed, edited and deleted. I want to restrict the edit and delete actions if the currently logged in user is not the creator of the Article.
I have already done this using Policies and use Gate within a Form Request, but if i understand correctly FormRequest is only for POST requests. And I currently pass the FormRequest as a parameter to the getEdit() action. That seems wrong.
So how can I make sure the user can neither access nor edit the Article?
If you already defined a Policy you can directly access it using the Gate facade within your controller action like this:
public function getEdit($id)
{
$reference = Reference::findOrFail($id);
if (Gate::denies('owns-reference', $reference))
abort(403);
return view('reference.edit')
->with('reference', $reference);
}
Just make sure to include the Gate on top of your file like this:
use Gate;

Resources