auth:api middleware not working in live server using laravel - react-native

auth:api middleware not working in live server using laravel
Route::group(['prefix' => 'business_entry_api','middleware' => 'auth:api'], function () {
// function here
}

you ca go with auth('api')->user(). It'll return the authenticated user even if middleware is not specifically used.
use like below on your api file:
public function __construct()
{
$this->middleware(function ($request,Closure $next) {
$this->user = Auth('api')->user();
return $next($request);
});
}

Related

Keycloak Log out from ASP.NET and ASP.NET Core

Currently I am able to login from ASP.NET and ASP.NET Core. However when logout from ASP.NET, my ASP.NET Core app doesn't logout as well.
Here is my ASP.NET logout code:
public ActionResult logout()
{
Request.GetOwinContext().Authentication.SignOut(HttpContext.GetOwinContext().Authentication.GetAuthenticationTypes().Select(o => o.AuthenticationType).ToArray());
return RedirectToAction("About", "Home");
}
And my ASP.NET Core logout:
public IActionResult Logout()
{
return new SignOutResult(new[] { "OpenIdConnect", "Cookies" });
}
Unfortunately, if I logout from the ASP.NET app, my ASP.NET Core app doesn't logout automatically. Is it something wrong with my keycloak setting, or did I miss something in my code?
Go through the https://github.com/dotnet/aspnetcore/blob/4fa5a228cfeb52926b30a2741b99112a64454b36/src/Security/Authentication/OpenIdConnect/src/OpenIdConnectHandler.cs#L312-L315
services.AddAuthentication(...)
.AddCookie("Cookies")
.AddOpenIdConnect("OpenIdConnect", options =>
{
...
options.Events.OnSignedOutCallbackRedirect += context =>
{
context.Response.Redirect(context.Options.SignedOutRedirectUri);
context.HandleResponse();
return Task.CompletedTask;
};
...
});
It is working for me. I used code similar to yours:
public IActionResult Logout()
{
return new SignOutResult(
new[] {
OpenIdConnectDefaults.AuthenticationScheme,
CookieAuthenticationDefaults.AuthenticationScheme
});
}
If you get invalid redirect error from keycloak, then you must also add Valid post logout redirect URIs to your Keycloak client settings. In your case, you have to add your_host/signout-callback-oidc
If you get an invalid or missing id_token_hint parameter, then make sure that tokens are being saved:
.AddOpenIdConnect(options =>
{
options.SaveTokens = true;
});

How to use API call in service in Iconic2

I am calling following function on click of button.
login.ts
public login() {
this.showLoading()
this.http.get('http://laravel.dev/test').map(res => res).subscribe(data => {
console.log(data)
},
error => {
this.showError(error);
});
}
What I want that this API call should be come from service file. As I am new to Ionic 2 That's Why I am unable to get how can I call above API through service and receive it in login.ts.
auth.service.ts
public login(credentials) {
// Here I want to call Above API and return it to the `login.ts`
}
Please help me.
The http.get request is an Observable. You can return the observable from the service and subscribe in the component/page.
auth.service.ts
public login(credentials) {
return this.http.get('http://laravel.dev/test').map(res => res.json())
}
map function returns the data after decoding the json response assuming your http returns json.
login.ts
public login() {
this.showLoading()
this.authService.login(credentials).subscribe(data => {
console.log(data)
},
error => {
this.showError(error);
},
()=>this.dismissLoading());
}
Inject the service through the constructor in your component and subscribe to the login function.

Basic authentication in Lumen

I have already written an API call for check authentication using Laravel. I need to move that controller to Lumen for use it as micro service.
This is my controller in Laravel.
public function byCredantial(Request $request)
{
$user = [
'email' => $request->input('email'),
'password' => $request->input('password')
];
if (Auth::attempt($user)) {
$response = $this->getSuccess(Auth::user()->id);
return response()->json($response, 200);
} else {
$response = $this->getError($user);
return response()->json($response, 401);
}
}
Lumen doc is not provide how to do such authentication. They has not function for check creadential is correct. How can i do this in Lumen. Is this possible?
You can do this in Lumen. Facades are disabled by default (if you want to enable it you can see the instructions in the documentation), but I would not recommend enabling the facades as the add additional overhead to your application. Instead, I would modify your function to call app('auth'). This will return the class that the Auth facade proxies without loading all the other facades.
public function byCredantial(Request $request)
{
$user = [
'email' => $request->input('email'),
'password' => $request->input('password')
];
$auth = app('auth');
if ($auth->attempt($user)) {
$response = $this->getSuccess($auth->user()->id);
return response()->json($response, 200);
} else {
$response = $this->getError($user);
return response()->json($response, 401);
}
}
Also, I would recommend reading the authentication documentation and placing the bulk of this code in the AuthServiceProvider.

How to make JWT cookie authentication in Laravel

I want to have JWT authentication in Laravel >=5.2, using this (Tymon JWT-auth) library but I want to put JWT token into HttpOnly Cookies - to protect JWT token from steal from XSS attack.
I set up Tymon library and... in project: app/Providers/RouteServiceProvider#mapWebRoutes i deactivate execution 'web' middelware group for all requests (which is default laravel behavior - you can see it by php artisan route:list) by remove 'middleware' => 'web' (If I don't do it, i will see CSRF problem with post request).
in routes.php i write:
Route::group(['middleware' =>'api', 'prefix' => '/api/v1', 'namespace' => 'Api\V1'], function () {
Route::post('/login', 'Auth\AuthController#postLogin');
...
Route::get('/projects', 'ProjectsController#getProjects');
}
In may Api\V1\Auth\AuthController#postLogin i generate token and send it back as httpOnly cookie:
...
try
{
$user = User::where('email','=',$credentials['email'])->first();
if ( !($user && Hash::check($credentials['password'], $user->password) ))
{
return response()->json(['error' => 'invalid_credentials'], 401);
}
$customClaims = ['sub' => $user->id, 'role'=> $user->role, 'csrf-token' => str_random(32) ];
$payload = JWTFactory::make($customClaims);
$token = JWTAuth::encode($payload);
} catch(...) {...}
return response()->json($payload->toArray())->withCookie('token', $token, config('jwt.ttl'), "/", null, false, true);
And, yeah here question starts. I would like to do something (may be modifiy laravel Auth class) on each request:
get coookie from request
decode it
check is right (if not trhow 401)
get user from DB
and make that method Auth::user() works every where like in usual way in laravel (so i can use it in each Controller for example)
Any ideas how to do point 4 ?
UPDATE
I also add here protection for CSRF attack - csrf-token is in JWT, and it is also return in body of response for login request (so JS have acces to this csrf-token) (i return only public part of JWT token in login response, whole JWT is return only in cookie, so it is XSS safe) - then front JS must copy csrf-token into header of each request. Then the middelware JWTAuthentiacate (in my answer below) compare csrf-token header with csrf-token field in JWT payload - if they are similar then request pass csrf test.
You can do it simple by creating middleware.
In handle() method just get cookie from request, decode it and login a user using id with this Laravel method:
Auth::loginUsingId($userIdFromToken);
I implement #ƁukaszKuczmaja idea in this way an it works! :) . So i create file in app/Http/Middleware/JWTAuthenticate.php :
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use JWTAuth;
use Tymon\JWTAuth\Token;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Illuminate\Session\TokenMismatchException;
class JWTAuthenticate
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
try {
if(!$request->headers->has('csrf-token')) throw new TokenMismatchException();
$rawToken = $request->cookie('token');
$token = new Token($rawToken);
$payload = JWTAuth::decode($token);
if($payload['csrf-token'] != $request->headers->get('csrf-token')) throw new TokenMismatchException();
Auth::loginUsingId($payload['sub']);
} catch(\Exception $e) {
if( $e instanceof TokenExpiredException) {
// TODO token refresh here
}
return response('Unauthorized.', 401);
}
return $next($request);
}
}
In app\Http\Kernel.php#$routeMiddelware I add line:
'jwt.auth' => \App\Http\Middleware\JWTAuthenticate::class,
My routing file looks like this now:
Route::group(['middleware' =>'api', 'prefix' => '/api/v1', 'namespace' => 'Api\V1'], function () {
Route::post('/login', 'Auth\AuthController#postLogin');
Route::group(['middleware' =>'jwt.auth'], function () {
Route::post('/projects', 'ProjectsController#postProjects');
Route::get('/projects', 'ProjectsController#getProjects');
Route::put('/projects/{project}', 'ProjectsController#putProjects');
Route::delete('/projects/{project}', 'ProjectsController#deleteProjects');
});
});
And for instance in app/Http/Controllers/Api/V1/ProjectsController.php i have:
public function getProjects() {
$uid = Auth::user()->id;
return Project::where('user_id','=',$uid)->get();
}
Actually you can put every route that needs authentication within a route group and add the middleware like this:
Route::group(['middleware' => ['jwt.auth']], function () {
Route::patch('/profile', 'UserController#update');
});
The middleware already does what you wanted so there is no need to write additional logic. Don't use an additional handle method.
Within your i.e. UserController you can then i.e.
$user = \Auth::user();
And i.e. depending what you need...
// assign fields
$user->save();
return 'success'; // or whatever you need
Don't reinvent the wheel and keep things DRY.

Sails JS with Redis for caching

As I said in my previous questions, I am trying to learn how to use sails.js, what I'm trying to do now is to cache the response of an api to redis. I have searched on how to do this, but I can't make it to work. Without caching, I call the api through ajax.
Any thoughts on how I will be able to do it using my controller? How can I call the api using the controller in sails.js and cache the response using redis?
You can use https://github.com/mranney/node_redis
Steps:
Add to package.json
"redis": "^0.12.1"
Run
npm install
Create a service module /api/services/CachedLookup.js
var redis = require("redis"),
client = redis.createClient();
module.exports = {
rcGet: function (key, cb) {
client.get(key, function (err, value) {
return cb(value);
});
},
fetchApi1: function (cb) {
var key = 'KEY'
CachedLookup.rcGet(key, function (cachedValue) {
if (cachedValue)
return cb(cachedValue)
else {//fetch the api and cache the result
var request = require('request');
request.post({
url: URL,
form: {}
}, function (error, response, body) {
if(error) {
//handle error
}
else {
client.set(key, response);
return cb(response)
}
});
}
});
}
}
Inside the controller
CachedLookup.fetchApi1(function (apiResponse) {
res.view({
apiResponse: apiResponse
});
});