Stop sending the access token with the response body in Yii2 - rest

I am developing a rest API using Yii2, the front end is developed by ionic.
the case is that when I have an action which it uses bearer authentication..
it works fine but the access token is returned with the response body which leads to an HttpErrorResponse in the client side:
SyntaxError: Unexpected token y in JSON at position 0 at Json.parse
the response is returned like this so the client is not able to parse the json
y2sSCEXqkUoVY2BjkQZqx8g3W42273Cz{"success":false,"message":"you liked it before"}
this is the behaviour code which uses the bearear authentication
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator'] = [
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
];
// remove authentication filter
$auth = $behaviors['authenticator'];
unset($behaviors['authenticator']);
// add CORS filter
$behaviors['corsFilter'] = [
'class' => CorsCustom::className(),
];
// re-add authentication filter
$behaviors['authenticator'] = $auth;
// avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
$behaviors['authenticator']['except'] = ['options'];
$behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'only' => ['like', 'unlike', 'likes', 'create'],
'authMethods' => [
HttpBearerAuth::className(),
],
];
return $behaviors;
}
I want to stop sending the access token in the body or send it as a json

I think you should remove the echo $token statement from your USER model
public static function findIdentityByAccessToken($token, $type = null)
{
/* echo $token; */
return static::findOne(['auth_key' => $token]);
}

Stop echo the token before the response and you'll get your job DONE!
public static function findIdentityByAccessToken($token, $type = null)
{
/* echo $token; */
return static::findOne(['auth_key' => $token]);
}

Related

Yii2 bug with CORS when not valid access token

I did with yii2 an acess token authorization if the access token is valid it works fine, but if the access token is invalid it returns the following CORS problem
Access to XMLHttpRequest at 'server' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
if the token is expired, the server works fine storing the old token on another table etc, but the client still gets the same CORS problem
I don't understand why it only happens when I try to return a 401 response, but it works when the acces token is valid, any idea?
This is the code I think its relevant
BehaviorsConfig.php
public static function corsFilterConfig($metodos_aceptados)
{
return [
'class' => Cors::className(),
'cors' => [
'Origin' => ['*'],
'Access-Control-Allow-Origin' => ['*'], // Añadido
'Access-Control-Request-Method' => $metodos_aceptados,
'Access-Control-Request-Headers' => ['*'],
'Access-Control-Allow-Credentials' => false,
'Access-Control-Max-Age' => 86400,
],
];
}
public static function authenticatorConfig()
{
return [
'class' => QueryParamAuth::className(),
'except' => ['options'],
'tokenParam' => 'access_token',
];
}
every controller
public function behaviors() {
$behaviors = parent::behaviors();
$behaviors['corsFilter'] = BehaviorsConfig::corsFilterConfig(['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS']);
$behaviors['authenticator'] = BehaviorsConfig::authenticatorConfig();
return $behaviors;
}
and now to check if the token is still valid and not expired I did this function
public function beforeAction($action){
if(AccessService::isExpired()){
throw new HttpException(401, "Sesión expirada, vuelva a conectarse.");
}
if (!parent::beforeAction($action)) {
return false;
}
return true;
}

Slim 3: How to access user information from request headers

I am using Slim 3.1 and able to authenticate correctly i.e. able to generate the token and use it for another POST request. Now I want to parse the request header to extract the user information so I can identify which user have sent the request.
Here is my code to get the token.
$app->post('/login/token', function (Request $request, Response $response,
array $args) {
$input = $request->getParsedBody();
$now = new DateTime();
$future = new DateTime("+10 minutes");
$server = $request->getServerParams();
$jti = (new Base62)->encode(random_bytes(16));
$payload = [
"iat" => $now->getTimeStamp(),
"exp" => $future->getTimeStamp(),
"jti" => $jti,
"sub" => $input['username']
];
$sql = "SELECT * FROM user WHERE User_Name= :username";
$sth = $this->db->prepare($sql);
$sth->bindParam("username", $input['username']);
$sth->execute();
$user = $sth->fetchObject();
// verify email address.
if(!$user) {
return $this->response->withJson(['error' => true, 'message' => 'These credentials do not match our records.']);
}
// verify password.
if (!password_verify($input['password'],$user->User_Password)) {
return $this->response->withJson(['error' => true, 'message' => 'These credentials do not match our records.']);
}
$settings = $this->get('settings'); // get settings array.
//$token = JWT::encode(['User_ID' => $user->User_ID, 'username' => $user->User_Name], $settings['jwt']['secret'], "HS256");
$token = JWT::encode($payload, $settings['jwt']['secret'], "HS256");
return $this->response->withJson(['token' => $token, 'ACL' => $user->User_ACL]);
});
This returns me a token that I send in the following POST request
$app->group('/api', function(\Slim\App $app) {
$app->post('/createuser', function (Request $request, Response $response,
array $args) {
$headerValueArray = $request->getHeader('HTTP_AUTHORIZATION');
return $this->response->withJson(['success' => true, $token]);
});
});
The above POST request gives the following output
{
"success": true,
"0": ["Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MzU4Mjk0OTUsImV4cCI6MTUzNTgzNjY5NSwianRpIjoiMWc5ZFM3dUNLbzl1blRQZzBmYjU2diIsInN1YiI6InN5c2FkbWluIn0.vo3FBPhBkhfA2y7AG-afmjfeEhygIYY7lIaaVNX5i5k"]
}
I need to parse this token to extract the user information to see if its the valid user to perform this operation.In other words, how I can decode the above token.
Any help here will be much appreciated!

How to Retrieve HTTP Status Code with Guzzle?

New to Guzzle/Http.
I have a API rest url login that answer with 401 code if not authorized, or 400 if missing values.
I would get the http status code to check if there is some issues, but cannot have only the code (integer or string).
This is my piece of code, I did use instruction here ( http://docs.guzzlephp.org/en/stable/quickstart.html#exceptions )
namespace controllers;
use GuzzleHttp\Psr7;
use GuzzleHttp\Exception\ClientException;
$client = new \GuzzleHttp\Client();
$url = $this->getBaseDomain().'/api/v1/login';
try {
$res = $client->request('POST', $url, [
'form_params' => [
'username' => 'abc',
'password' => '123'
]
]);
} catch (ClientException $e) {
//echo Psr7\str($e->getRequest());
echo Psr7\str($e->getResponse());
}
You can use the getStatusCode function.
$response = $client->request('GET', $url);
$statusCode = $response->getStatusCode();
Note: If your URL redirects to some other URL then you need to set false value for allow_redirects property to be able to detect initial status code for parent URL.
// On client creation
$client = new GuzzleHttp\Client([
'allow_redirects' => false
]);
// Using with request function
$client->request('GET', '/url/with/redirect', ['allow_redirects' => false]);
If you want to check status code in catch block, then you need to use $exception->getCode()
More about responses
More about allow_redirects
you can also use this code :
$client = new \GuzzleHttp\Client(['base_uri' 'http://...', 'http_errors' => false]);
hope help you

Validation error messages as JSON in Laravel 5.3 REST

My app is creating a new entry via a POST request in an api end point.
Now, if any validation is failed then instead of returning an error json, laravel 5.3 is redirecting the request to home page.
Here is my controller:
public function create( Request $request )
{
$organization = new Organization;
// Validate user input
$this->validate($request, [
'organizationName' => 'required',
'organizationType' => 'required',
'companyStreet' => 'required'
]);
// Add data
$organization->organizationName = $request->input('organizationName');
$organization->organizationType = $request->input('organizationType');
$organization->companyStreet = $request->input('companyStreet');
$organization->save();
return response()->json($organization);
}
If there is no issue with validation then the entity will be successfully added in the database, but if there is issue with validating the request then instead of sending all the error messages as a json response it redirects back to the home page.
How i can set the validate return type to json, so with every request if the validation failed then laravel will send all the error messages as json by default.
You can do your validation as:
$validator = \Validator::make($request->all(), [
'organizationName' => 'required',
'organizationType' => 'required',
'companyStreet' => 'required'
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422)
}
The validation used in the question looks as per the recommendation by laravel. The reason of redirection is that it throws an exception which you can easily catch using the code below. So it's better to use the recommended way of code instead of re-writing framework's code again :)
public function create( Request $request )
{
$organization = new Organization;
// Validate user input
try {
$this->validate($request, [
'organizationName' => 'required',
'organizationType' => 'required',
'companyStreet' => 'required'
]);
} catch (ValidationException $e) {
return response()->json($e->validator->errors(), 422);
}
// Add data
$organization->organizationName = $request->input('organizationName');
$organization->organizationType = $request->input('organizationType');
$organization->companyStreet = $request->input('companyStreet');
$organization->save();
return response()->json($organization, 201);
}

Yii2 AuthClient set return page for Facebook client

I have a form for lead gen, which just get the user information (like name, gender, email) which can be filled out with Facebook. But the problem is, selecting to fill form with FB redirect to index page. How can i set the return page to some other view or action?
public function onAuthSuccess($cliente)
{
// TODO: fb login e retornar dados do perfil para o form
$fb = new Facebook([
'app_id' => MYAPPID,
'app_secret' => MYAPPSECRET
]);
try {
$token = $cliente->getAccessToken()->getToken();
// Returns a `Facebook\FacebookResponse` object
$usuario = $fb->get('/me?fields=email,name,gender,age_range',
$token)->getDecodedBody();
} catch(Exception $e) {
echo 'Error: ' . $e->getMessage();
exit;
}
return ; // actually doesn't matter, it always end redirecting to site/index
}
Auth config:
'auth' => ['class' => yii\authclient\AuthAction::className(),'successCallback' => [$this, 'onAuthSuccess']]
Add successUrl in Auth action config
'successUrl'=>'url'
it is an public property you can override its value in your function also
$this->action->successUrl = "url-with-data";
Note: this is for understanding purpose only, best way to generate dynamic urls would be using urlmanager