I'm trying to use the Auth Client Extension in Yii2 (http://www.yiiframework.com/doc-2.0/ext-authclient-index.html). I've copied the Twitter Auth Client class that came with YiiFramework and made my own Tumblr version. Twitter works fine, but when I use my Tumblr version, I get an error on the screen after the "Is it alright for this application to access some of your data and make posts to your account? You are logged in as *********." (Tumblr oauth page)
There error is: Request failed with code: 401, message: oauth_signature does not match expected value
Here is my Tumblr auth client code:
namespace yii\authclient\clients;
use yii\authclient\OAuth1;
/**
*
* Example application configuration:
*
* ~~~
* 'components' => [
* 'authClientCollection' => [
* 'class' => 'yii\authclient\Collection',
* 'clients' => [
* 'tumblr' => [
* 'class' => 'yii\authclient\clients\Tumblr',
* 'consumerKey' => 'tumblr_consumer_key',
* 'consumerSecret' => 'tumblr_consumer_secret',
* ],
* ],
* ]
* ...
* ]
* ~~~
*
*/
class Tumblr extends OAuth1
{
/**
* #inheritdoc
*/
public $authUrl = 'https://www.tumblr.com/oauth/authorize';
/**
* #inheritdoc
*/
public $requestTokenUrl = 'https://www.tumblr.com/oauth/request_token';
/**
* #inheritdoc
*/
public $requestTokenMethod = 'POST';
/**
* #inheritdoc
*/
public $accessTokenUrl = 'https://www.tumblr.com/oauth/access_token';
/**
* #inheritdoc
*/
public $accessTokenMethod = 'GET';
/**
* #inheritdoc
*/
public $apiBaseUrl = 'http://api.tumblr.com/v2';
/**
* #inheritdoc
*/
protected function initUserAttributes()
{
return $this->api('/user/info', 'GET');
}
/**
* #inheritdoc
*/
protected function defaultName()
{
return 'tumblr';
}
/**
* #inheritdoc
*/
protected function defaultTitle()
{
return 'Tumblr';
}
}
You might want to try out Hybridauth's version. I have used the Google and Facebook version in Yii2 and it works fine.
For the current version of yii - you have to extend yii Oauth1 class using the following code to be able to use your class.
<?php
namespace your_vendor\authclient;
use yii\authclient\OAuthToken;
use yii\base\Exception;
use Yii;
class OAuth1 extends \yii\authclient\OAuth1
{
public function fetchAccessToken(OAuthToken $requestToken = null, $oauthVerifier = null, array $params = [])
{
if (!is_object($requestToken)) {
$requestToken = $this->getState('requestToken');
if (!is_object($requestToken)) {
throw new Exception('Request token is required to fetch access token!');
}
}
$defaultParams = [
'oauth_consumer_key' => $this->consumerKey,
'oauth_token' => $requestToken->getToken()
];
if ($oauthVerifier === null) {
if (isset($_REQUEST['oauth_verifier'])) {
$oauthVerifier = $_REQUEST['oauth_verifier'];
}
}
if (!empty($oauthVerifier)) {
$defaultParams['oauth_verifier'] = $oauthVerifier;
}
$response = $this->sendSignedRequest($this->accessTokenMethod, $this->accessTokenUrl, array_merge($defaultParams, $params));
$this->removeState('requestToken');
$token = $this->createToken([
'params' => $response
]);
$this->setAccessToken($token);
return $token;
}
protected function composeSignatureKey() {
$signatureKeyParts = [
$this->consumerSecret
];
if (is_null($accessToken = $this->getState('requestToken'))) {
$accessToken = $this->getAccessToken();
}
if (is_object($accessToken)) {
$signatureKeyParts[] = $accessToken->getTokenSecret();
} else {
$signatureKeyParts[] = '';
}
$signatureKeyParts = array_map('rawurlencode', $signatureKeyParts);
return implode('&', $signatureKeyParts);
}
}
Related
I am new to laravel, I am trying to generate oauth token by extending Laravel Passport AccessTokenController class, and I always getting this error "message": "Call to a member function respondToAccessTokenRequest() on null",
here is my class
class B2BTokenController extends \Laravel\Passport\Http\Controllers\AccessTokenController
{
function issueB2BToken(ServerRequestInterface $request)
{
$req = $request->withParsedBody([
"grant_type" => "client_credentials",
"client_id" => $request->getHeaderLine('X-CLIENT-KEY'),
"client_secret" => $request->getHeaderLine('X-SIGNATURE'),
]);
$response = parent::issueToken($req);
return $response->getContent();
}
}
and here is \Laravel\Passport\Http\Controllers\AccessTokenController class
class AccessTokenController
{
use HandlesOAuthErrors;
/**
* The authorization server.
*
* #var \League\OAuth2\Server\AuthorizationServer
*/
protected $server;
/**
* The token repository instance.
*
* #var \Laravel\Passport\TokenRepository
*/
protected $tokens;
/**
* Create a new controller instance.
*
* #param \League\OAuth2\Server\AuthorizationServer $server
* #param \Laravel\Passport\TokenRepository $tokens
* #return void
*/
public function __construct(AuthorizationServer $server,
TokenRepository $tokens)
{
$this->server = $server;
$this->tokens = $tokens;
}
/**
* Authorize a client to access the user's account.
*
* #param \Psr\Http\Message\ServerRequestInterface $request
* #return \Illuminate\Http\Response
*/
public function issueToken(ServerRequestInterface $request)
{
return $this->withErrorHandling(function () use ($request) {
return $this->convertResponse(
$this->server->respondToAccessTokenRequest($request, new Psr7Response)
);
});
}
}
Thank you for your help
That's because you are overwriting the __construct method!
Check that and it will work
I try to create restful api using Code Igniter 4 on Apache2. If I open http://<my-ip:port>, it shows welcome message. Then I created Account.php controller to get account list from database.
<?php namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\API\ResponseTrait;
use App\Models\AccountModel;
class Account extends ResourceController
{
use ResponseTrait;
public function index()
{
$model = new AccountModel();
$data = $model->findAll();
return $this->respond($data, 200);
}
public function show($id = null)
{
$model = new AccountModel();
$data = $model->getWhere(['account_id' => $id])->getResult();
if($data){
return $this->respond($data);
}else{
return $this->failNotFound('No Data Found with id '.$id);
}
}
}
AccountModel.php
<?php namespace App\Models;
use CodeIgniter\Model;
class AccountModel extends Model
{
protected $table = 'account';
protected $primaryKey = 'id';
protected $allowedFields = ['account_id','name'];
}
I set Cors and Filters.
and this is my routes
<?php
namespace Config;
$routes = Services::routes();
if (file_exists(SYSTEMPATH . 'Config/Routes.php')) {
require SYSTEMPATH . 'Config/Routes.php';
}
$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
$routes->setAutoRoute(true);
//$routes->get('/','Home::index');
$routes->resource('account');
if (file_exists(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}
http://my-ip:port shows welcome message. But if I open http://<my-ip:port/account> using postman I got error
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<hr>
<address>Apache/2.4.46 (Ubuntu) Server at <my-ip> Port 80</address>
</body></html>
and I set Account as a default controller $routes->setDefaultController('Account'); I got list of account if I open http://<my-ip:port>. Do I miss some set up? I want to get account list if I open http://<my-ip:port/account> and others.
Is it works if tried http://<my-ip:port/index.php/account? if yes, you have to config your apache to hide index.php from URL.
visit following link for more infos. => more infos
look at my code best way using restful ctl ci4
first routs
<?php
/*
* Core Auth routes file.
*/
$routes->group('api', ['namespace' => 'Modules\Auth\Controllers'], function ($routes) {
$routes->resource('group', ['filter' => 'authJwt']);
$routes->resource('permission', ['filter' => 'authJwt']);
$routes->resource('groupPermission', ['filter' => 'authJwt']);
$routes->resource('userPermission', ['filter' => 'authJwt']);
$routes->group('auth', function ($routes) {
$routes->post('signin-jwt', 'Auth::signInJwt', ['filter' => 'isSignIn']);
$routes->post('signin', 'Auth::signIn', ['filter' => 'isSignIn']);
$routes->get('signout', 'Auth::signOut', ['filter' => 'authJwt']);
$routes->get('is-signin', 'Auth::isSignIn',['filter' => 'authJwt']);
$routes->post('signup', 'Auth::signUp', ['filter' => 'isSignIn']);
$routes->post('forgot', 'Auth::forgot', ['filter' => 'isSignIn']);
$routes->post('reset-password-email', 'Auth::resetPasswordViaEmail', ['filter' => 'isSignIn']);
$routes->post('reset-password-sms', 'Auth::resetPasswordViaSms', ['filter' => 'isSignIn']);
$routes->post('activate-account-email', 'Auth::activateAccountViaEmail', ['filter' => 'isSignIn']);
$routes->post('send-activate-email', 'Auth::sendActivateCodeViaEmail', ['filter' => 'isSignIn']);
$routes->post('activate-account-sms', 'Auth::activateAccountViaSms', ['filter' => 'isSignIn']);
$routes->post('send-activate-sms', 'Auth::sendActivateCodeViaSms', ['filter' => 'isSignIn']);
});
});
sencond api ctl
<?php
namespace Modules\Shared\Controllers;
/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*
* #package CodeIgniter
*/
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\RESTful\ResourceController;
use Modules\Auth\Config\Services;
use Myth\Auth\AuthTrait;
use Psr\Log\LoggerInterface;
use Modules\Shared\Interfaces\UrlAggregationInterface;
use Modules\Shared\Libraries\UrlAggregation;
class ApiController extends ResourceController
{
use AuthTrait;
protected $format = "";
public object $userObject;
public UrlAggregationInterface $urlAggregation;
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* #var array
*/
protected $helpers = [
'cookie',
'url',
'from',
'filesystem',
'text',
'shared'
];
/**
* Constructor.
*
* #param RequestInterface $request
* #param ResponseInterface $response
* #param LoggerInterface $logger
*/
/**
* #var string
* Holds the session instance
*/
protected $session;
public function __construct()
{
$this->userObject = (object)[];
}
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
$this->urlAggregation = new UrlAggregation($request);
$requestWithUser = Services::requestWithUser();
$this->userObject = $requestWithUser->getUser();
}
}
thrid ctl
<?php namespace Modules\Auth\Controllers;
use Modules\Auth\Config\Services;
use Modules\Auth\Entities\GroupEntity;
use CodeIgniter\HTTP\ResponseInterface;
use Modules\Shared\Controllers\ApiController;
class Group extends ApiController
{
/**
* index function
* #method : GET
*/
public function index()
{
$groupEntity = new GroupEntity();
$this->urlAggregation->dataMap($groupEntity->getDataMap());
$groupService = Services::groupService();
$findAllData = $groupService->index($this->urlAggregation);
return $this->respond([
'data' => $findAllData['data'],
'pager' => $findAllData['pager']
], ResponseInterface::HTTP_OK, lang('Shared.api.receive'));
}
/**
* show function
* #method : GET with params ID
*/
public function show($id = null)
{
$groupService = Services::groupService();
$findOneData = $groupService->show($id);
return $this->respond([
'data' => $findOneData['data'],
'pager' => $findOneData['pager']
], ResponseInterface::HTTP_OK, lang('Shared.api.receive'));
}
public function create()
{
$rules = [
'name' => 'required|min_length[3]|max_length[255]|is_unique[auth_groups.name]',
'description' => 'required|min_length[3]|max_length[255]',
];
if (!$this->validate($rules)) {
return $this->respond([
'error' => $this->validator->getErrors(),
], ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Shared.api.validation'));
}
$groupEntity = new GroupEntity((array)$this->request->getVar());
$groupService = Services::groupService();
$groupService->create($groupEntity);
return $this->respond([
'data' => ''
], ResponseInterface::HTTP_CREATED, lang('Shared.api.save'));
}
/**
* update function
* #method : PUT or PATCH
*/
public function update($id = null)
{
//get request from Vue Js
//get request from Vue Js
$json = $this->request->getJSON();
if (!isset($id)) {
$id = $json->id;
}
$rules = [
'name' => 'if_exist|required|min_length[3]|max_length[255]',
'description' => 'required|min_length[3]|max_length[255]',
];
if (!$this->validate($rules)) {
return $this->respond([
'error' => $this->validator->getErrors(),
], ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Shared.api.validation'));
}
$groupEntity = new GroupEntity((array)$this->request->getVar());
$groupService = Services::groupService();
$groupService->update($id, $groupEntity);
return $this->respond([
], ResponseInterface::HTTP_OK, lang('Shared.api.update'));
}
/**
* edit function
* #method : DELETE with params ID
*/
public function delete($id = null)
{
$groupService = Services::groupService();
$groupService->delete($id);
return $this->respond([
], ResponseInterface::HTTP_OK, lang('Shared.api.remove'));
}
}
entitiy
forth service
<?php namespace Modules\Auth\Config;
use CodeIgniter\HTTP\UserAgent;
use Config\App;
use Config\Services as AppServices;
use Config\Services as BaseService;
use Modules\Auth\Libraries\RequestWithUser;
use Modules\Auth\Services\AuthService;
use Modules\Auth\Services\GroupsPermissionService;
use Modules\Auth\Services\PermissionService;
use Modules\Auth\Services\RoleRouteService;
use Modules\Auth\Services\GroupService;
use Modules\Auth\Services\UsersPermissionService;
class Services extends BaseService
{
//--------------------------------------------------------------------
/**
* The Request class models an HTTP request.
*
* #param App|null $config
* #param boolean $getShared
*
* #return RequestWithUser
*/
public static function requestWithUser(App $config = null, bool $getShared = true)
{
if ($getShared) {
return static::getSharedInstance('requestWithUser', $config);
}
$config = $config ?? config('App');;
return new RequestWithUser(
$config,
AppServices::uri(),
'php://input',
new UserAgent()
);
}
//--------------------------------------------------------------------
public static function roleRoute($getShared = true)
{
if ($getShared) {
return static::getSharedInstance('roleRoute');
}
return new RoleRouteService();
}
//--------------------------------------------------------------------
public static function authService($getShared = false)
{
if (!$getShared) {
return new AuthService();
}
return static::getSharedInstance('authService');
}
//--------------------------------------------------------------------
public static function groupService($getShared = false)
{
if (!$getShared) {
return new GroupService();
}
return static::getSharedInstance('groupService');
}
//--------------------------------------------------------------------
public static function permissionService($getShared = false)
{
if (!$getShared) {
return new PermissionService();
}
return static::getSharedInstance('permissionService');
}
//--------------------------------------------------------------------
public static function groupsPermissionService($getShared = false)
{
if (!$getShared) {
return new GroupsPermissionService();
}
return static::getSharedInstance('groupsPermissionService');
}
//--------------------------------------------------------------------
public static function userPermissionService($getShared = false)
{
if (!$getShared) {
return new UsersPermissionService();
}
return static::getSharedInstance('usersPermissionService');
}
//--------------------------------------------------------------------
}
<?php namespace Modules\Auth\Entities;
use \CodeIgniter\Entity;
use CodeIgniter\I18n\Time;
class GroupEntity extends Entity
{
protected $id;
protected $name;
protected $description;
//check type of data
// protected $casts = ['
// is_flag' => 'boolean'];
protected $attributes = [
'id' => null,
'name' => null,
'description' => null,
];
protected $datamap = [
];
protected $dates = [];
protected $casts = [];
protected $permissions = [];
protected $roles = [];
}
model
<?php namespace Myth\Auth\Authorization;
use CodeIgniter\Model;
use Modules\Auth\Entities\GroupEntity;
use Modules\Shared\Models\Aggregation;
class GroupModel extends Aggregation
{
protected $table = 'auth_groups';
protected $primaryKey = 'id';
protected $returnType = GroupEntity::class;
protected $allowedFields = [
'name', 'description'
];
protected $useTimestamps = false;
protected $validationRules = [
'name' => 'required|max_length[255]|is_unique[auth_groups.name,name,{name}]',
'description' => 'max_length[255]',
];
protected $validationMessages = [];
protected $skipValidation = false;
//--------------------------------------------------------------------
// Users
//--------------------------------------------------------------------
/**
* Adds a single user to a single group.
*
* #param int $userId
* #param int $groupId
*
* #return bool
*/
public function addUserToGroup(int $userId, int $groupId)
{
cache()->delete("{$groupId}_users");
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
$data = [
'user_id' => (int) $userId,
'group_id' => (int) $groupId
];
return (bool) $this->db->table('auth_groups_users')->insert($data);
}
/**
* Removes a single user from a single group.
*
* #param int $userId
* #param int|string $groupId
*
* #return bool
*/
public function removeUserFromGroup(int $userId, $groupId)
{
cache()->delete("{$groupId}_users");
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
return $this->db->table('auth_groups_users')
->where([
'user_id' => $userId,
'group_id' => (int) $groupId
])->delete();
}
/**
* Removes a single user from all groups.
*
* #param int $userId
*
* #return bool
*/
public function removeUserFromAllGroups(int $userId)
{
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
return $this->db->table('auth_groups_users')
->where('user_id', (int)$userId)
->delete();
}
/**
* Returns an array of all groups that a user is a member of.
*
* #param int $userId
*
* #return array
*/
public function getGroupsForUser(int $userId)
{
if (null === $found = cache("{$userId}_groups"))
{
$found = $this->builder()
->select('auth_groups_users.*, auth_groups.name, auth_groups.description')
->join('auth_groups_users', 'auth_groups_users.group_id = auth_groups.id', 'left')
->where('user_id', $userId)
->get()->getResultArray();
cache()->save("{$userId}_groups", $found, 300);
}
return $found;
}
/**
* Returns an array of all users that are members of a group.
*
* #param int $groupId
*
* #return array
*/
public function getUsersForGroup(int $groupId)
{
if (null === $found = cache("{$groupId}_users"))
{
$found = $this->builder()
->select('auth_groups_users.*, users.*')
->join('auth_groups_users', 'auth_groups_users.group_id = auth_groups.id', 'left')
->join('users', 'auth_groups_users.user_id = users.id', 'left')
->where('auth_groups.id', $groupId)
->get()->getResultArray();
cache()->save("{$groupId}_users", $found, 300);
}
return $found;
}
//--------------------------------------------------------------------
// Permissions
//--------------------------------------------------------------------
/**
* Gets all permissions for a group in a way that can be
* easily used to check against:
*
* [
* id => name,
* id => name
* ]
*
* #param int $groupId
*
* #return array
*/
public function getPermissionsForGroup(int $groupId): array
{
$permissionModel = model(PermissionModel::class);
$fromGroup = $permissionModel
->select('auth_permissions.*')
->join('auth_groups_permissions', 'auth_groups_permissions.permission_id = auth_permissions.id', 'inner')
->where('group_id', $groupId)
->findAll();
$found = [];
foreach ($fromGroup as $permission)
{
$found[$permission['id']] = $permission;
}
return $found;
}
/**
* Add a single permission to a single group, by IDs.
*
* #param int $permissionId
* #param int $groupId
*
* #return mixed
*/
public function addPermissionToGroup(int $permissionId, int $groupId)
{
$data = [
'permission_id' => (int)$permissionId,
'group_id' => (int)$groupId
];
return $this->db->table('auth_groups_permissions')->insert($data);
}
//--------------------------------------------------------------------
/**
* Removes a single permission from a single group.
*
* #param int $permissionId
* #param int $groupId
*
* #return mixed
*/
public function removePermissionFromGroup(int $permissionId, int $groupId)
{
return $this->db->table('auth_groups_permissions')
->where([
'permission_id' => $permissionId,
'group_id' => $groupId
])->delete();
}
//--------------------------------------------------------------------
/**
* Removes a single permission from all groups.
*
* #param int $permissionId
*
* #return mixed
*/
public function removePermissionFromAllGroups(int $permissionId)
{
return $this->db->table('auth_groups_permissions')
->where('permission_id', $permissionId)
->delete();
}
}
I created a simple wrapper around shopify's REST api (private application using basic auth) like this using Guzzle:
<?php
namespace App\Services;
use stdClass;
use Exception;
use GuzzleHttp\Client as GuzzleClient;
/**
* Class ShopifyService
* #package App\Services
*/
class ShopifyService
{
/**
* #var array $config
*/
private $config = [];
/**
* #var GuzzleClient$guzzleClient
*/
private $guzzleClient;
/**
* ShopifyService constructor.
*/
public function __construct()
{
$this->config = config('shopify');
}
/**
* #return ShopifyService
*/
public function Retail(): ShopifyService
{
return $this->initGuzzleClient(__FUNCTION__);
}
/**
* #return ShopifyService
*/
public function Trade(): ShopifyService
{
return $this->initGuzzleClient(__FUNCTION__);
}
/**
* #param string $uri
* #return stdClass
* #throws \GuzzleHttp\Exception\GuzzleException
* #throws Exception
*/
public function Get(string $uri): stdClass
{
$this->checkIfGuzzleClientInitiated();;
$result = $this->guzzleClient->request('GET', $uri);
return \GuzzleHttp\json_decode($result->getBody());
}
/**
* #throws Exception
*/
private function checkIfGuzzleClientInitiated(): void
{
if (!$this->guzzleClient) {
throw new Exception('Guzzle Client Not Initiated');
}
}
/**
* #param string $storeName
* #return ShopifyService
*/
private function initGuzzleClient(string $storeName): ShopifyService
{
if (!$this->guzzleClient) {
$this->guzzleClient = new GuzzleClient([
'base_url' => $this->config[$storeName]['baseUrl'],
'auth' => [
$this->config[$storeName]['username'],
$this->config[$storeName]['password'],
],
'timeout' => 30,
]);
}
return $this;
}
}
Where the config/shopify.php looks like this:
<?php
use Constants\System;
return [
System::STORE_RETAIL => [
'baseUrl' => env('SHOPIFY_API_RETAIL_BASE_URL'),
'username' => env('SHOPIFY_API_RETAIL_USERNAME'),
'password' => env('SHOPIFY_API_RETAIL_PASSWORD'),
],
System::STORE_TRADE => [
'baseUrl' => env('SHOPIFY_API_TRADE_BASE_URL'),
'username' => env('SHOPIFY_API_TRADE_USERNAME'),
'password' => env('SHOPIFY_API_TRADE_PASSWORD'),
],
];
When I use the service like this:
$retailShopifySerice = app()->make(\App\Services\ShopifyService::class);
dd($retailShopifySerice->Retail()->Get('/products/1234567890.json'));
I get the following error:
GuzzleHttp\Exception\RequestException
cURL error 3: (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)
As you can see, I am making a simple guzzle http client with default option (for base uri + basic auth) and making subsequent GET request.
This should work in theory, but I can't figure out why it's throwing this error?
I've already verified the config is correct (i.e. it has the values I expect) and tried clearing all the laravel cache also.
Any ideas what might be wrong here?
I could not get the base_url option to work with Guzzle\Client for some reason, so I solved it in a different way:
<?php
namespace App\Services;
use Exception;
use App\DTOs\ShopifyResult;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\GuzzleException;
/**
* Class ShopifyService
* #package App\Services
*/
class ShopifyService
{
const REQUEST_TYPE_GET = 'GET';
const REQUEST_TYPE_POST = 'POST';
const REQUEST_TIMEOUT = 30;
/**
* #var array $shopifyConfig
*/
private $shopifyConfig = [];
/**
* ShopifyService constructor.
*/
public function __construct()
{
$this->shopifyConfig = config('shopify');
}
/**
* #param string $storeName
* #param string $requestUri
* #return ShopifyResult
* #throws GuzzleException
*/
public function Get(string $storeName, string $requestUri): ShopifyResult
{
return $this->guzzleRequest(
self::REQUEST_TYPE_GET,
$storeName,
$requestUri
);
}
/**
* #param string $storeName
* #param string $requestUri
* #param array $requestPayload
* #return ShopifyResult
* #throws GuzzleException
*/
public function Post(string $storeName, string $requestUri, array $requestPayload = []): ShopifyResult
{
return $this->guzzleRequest(
self::REQUEST_TYPE_POST,
$storeName,
$requestUri,
$requestPayload
);
}
/**
* #param string $requestType
* #param string $storeName
* #param $requestUri
* #param array $requestPayload
* #return ShopifyResult
* #throws GuzzleException
* #throws Exception
*/
private function guzzleRequest(string $requestType, string $storeName, $requestUri, array $requestPayload = []): ShopifyResult
{
$this->validateShopifyConfig($storeName);
$guzzleClient = new GuzzleClient();
$requestOptions = [
'auth' => [
$this->shopifyConfig[$storeName]['username'],
$this->shopifyConfig[$storeName]['password']
],
'timeout' => self::REQUEST_TIMEOUT,
];
if (count($requestPayload)) {
$requestOptions['json'] = $requestPayload;
}
$response = $guzzleClient->request(
$requestType,
$this->shopifyConfig[$storeName]['baseUrl'] . $requestUri,
$requestOptions
);
list ($usedApiCall, $totalApiCallAllowed) = explode(
'/',
$response->getHeader('X-Shopify-Shop-Api-Call-Limit')[0]
);
$shopifyResult = new ShopifyResult(
$response->getStatusCode(),
$response->getReasonPhrase(),
((int) $totalApiCallAllowed - (int) $usedApiCall),
\GuzzleHttp\json_decode($response->getBody()->getContents())
);
$guzzleClient = null;
unset($guzzleClient);
return $shopifyResult;
}
/**
* #param string $storeName
* #throws Exception
*/
private function validateShopifyConfig(string $storeName): void
{
if (!array_key_exists($storeName, $this->shopifyConfig)) {
throw new Exception("Invalid shopify store {$storeName}");
}
foreach (['baseUrl', 'username', 'password'] as $configFieldName) {
if (!array_key_exists($configFieldName, $this->shopifyConfig[$storeName])) {
throw new Exception("Shopify config missing {$configFieldName} for store {$storeName}");
}
}
}
}
I am getting error while making custom authentication for my laravel 5.2 however this code works fine on my laravel 5.1 My config/auth.php file
'providers' => [
'users' => [
'driver' => 'custom',
'model' => App\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
My CustomUserProvider.php (Auth/CustomUserProvider) file
<?php namespace App\Auth;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
class CustomUserProvider implements UserProvider {
protected $model;
public function __construct(UserContract $model)
{
$this->model = $model;
}
public function retrieveById($identifier)
{
}
public function retrieveByToken($identifier, $token)
{
}
public function updateRememberToken(UserContract $user, $token)
{
}
public function retrieveByCredentials(array $credentials)
{
}
public function validateCredentials(UserContract $user, array $credentials)
{
}
}
My CustomAuthProvider.php file
<?php namespace App\Providers;
use App\User;
use Auth;
use App\Auth\CustomUserProvider;
use Illuminate\Support\ServiceProvider;
class CustomAuthProvider extends ServiceProvider {
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
$this->app['auth']->extend('custom',function()
{
return new CustomUserProvider();
});
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
Now this works fine in laravel 5.1 in 5.2 i am getting error like
InvalidArgumentException in CreatesUserProviders.php line 40:
Authentication user provider [custom] is not defined.
The only point is to use
$this->app['auth']->provider(...
instead of
$this->app['auth']->extend(...
The last one is used in 5.1, the first one should be used in 5.2.
app/Models/User.php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable {
protected $connection='conn';
protected $table='users-custom';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'login', 'passwd'
];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = [
'passwd',
];
public function getAuthPassword(){
//your passwor field name
return $this->passwd;
}
public $timestamps = false;
}
create app/Auth/CustomUserProvider.php
namespace App\Auth;
use Illuminate\Support\Str;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Contracts\Auth\UserProvider;
/**
* Description of CustomUserProvider
*
*/
class CustomUserProvider implements UserProvider {
/**
* The hasher implementation.
*
* #var \Illuminate\Contracts\Hashing\Hasher
*/
protected $hasher;
/**
* The Eloquent user model.
*
* #var string
*/
protected $model;
/**
* Create a new database user provider.
*
* #param \Illuminate\Contracts\Hashing\Hasher $hasher
* #param string $model class name of model
* #return void
*/
public function __construct($model) {
$this->model = $model;
}
/**
* Retrieve a user by their unique identifier.
*
* #param mixed $identifier
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveById($identifier) {
return $this->createModel()->newQuery()->find($identifier);
}
/**
* Retrieve a user by their unique identifier and "remember me" token.
*
* #param mixed $identifier
* #param string $token
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByToken($identifier, $token) {
$model = $this->createModel();
return $model->newQuery()
->where($model->getAuthIdentifierName(), $identifier)
->where($model->getRememberTokenName(), $token)
->first();
}
/**
* Update the "remember me" token for the given user in storage.
*
* #param \Illuminate\Contracts\Auth\Authenticatable $user
* #param string $token
* #return void
*/
public function updateRememberToken(UserContract $user, $token) {
$user->setRememberToken($token);
$user->save();
}
/**
* Retrieve a user by the given credentials.
*
* #param array $credentials
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByCredentials(array $credentials) {
// First we will add each credential element to the query as a where clause.
// Then we can execute the query and, if we found a user, return it in a
// Eloquent User "model" that will be utilized by the Guard instances.
$query = $this->createModel()->newQuery();
foreach ($credentials as $key => $value) {
if (!Str::contains($key, 'password')) {
$query->where($key, $value);
}
}
return $query->first();
}
/**
* Validate a user against the given credentials.
*
* #param \Illuminate\Contracts\Auth\Authenticatable $user
* #param array $credentials
* #return bool
*/
public function validateCredentials(UserContract $user, array $credentials) {
//your method auth
$plain = $credentials['password'];
return md5($plain)==md5($user->getAuthPassword());
}
/**
* Create a new instance of the model.
*
* #return \Illuminate\Database\Eloquent\Model
*/
public function createModel() {
$class = '\\' . ltrim($this->model, '\\');
return new $class;
}
/**
* Gets the hasher implementation.
*
* #return \Illuminate\Contracts\Hashing\Hasher
*/
public function getHasher() {
return $this->hasher;
}
/**
* Sets the hasher implementation.
*
* #param \Illuminate\Contracts\Hashing\Hasher $hasher
* #return $this
*/
public function setHasher(HasherContract $hasher) {
$this->hasher = $hasher;
return $this;
}
/**
* Gets the name of the Eloquent user model.
*
* #return string
*/
public function getModel() {
return $this->model;
}
/**
* Sets the name of the Eloquent user model.
*
* #param string $model
* #return $this
*/
public function setModel($model) {
$this->model = $model;
return $this;
}
}
in config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users_office',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'users_office' => [
'driver' => 'customUser',
'model' => App\Models\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
in \vendor\laravel\framework\src\Illuminate\AuthCreatesUserProviders.php
public function createUserProvider($provider)
{
$config = $this->app['config']['auth.providers.'.$provider];
if (isset($this->customProviderCreators[$config['driver']])) {
return call_user_func(
$this->customProviderCreators[$config['driver']], $this->app, $config
);
}
switch ($config['driver']) {
case 'database':
return $this->createDatabaseProvider($config);
case 'eloquent':
return $this->createEloquentProvider($config);
case 'customUser':
return $this->createCustomUserProvider($config);
default:
throw new InvalidArgumentException("Authentication user provider [{$config['driver']}] is not defined.");
}
}
protected function createCustomUserProvider($config){
return new \App\Auth\CustomUserProvider($config['model']);
}
add App\Providers\CustomUserAuthProvider.php
namespace App\Providers;
use Auth;
use App\Models\User;
use App\Auth\CustomUserProvider;
use Illuminate\Support\ServiceProvider;
/**
* Description of CustomAuthProvider
*
*/
class CustomUserAuthProvider extends ServiceProvider {
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
Auth::extend('customUser', function($app) {
// Return an instance of Illuminate\Contracts\Auth\UserProvider...
return new CustomUserProvider(new User);
});
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
Try by replacing the boot function as below:
public function boot()
{
Auth::provider('custom', function($app, array $config) {
// Return an instance of Illuminate\Contracts\Auth\UserProvider...
return new CustomUserProvider($app['custom.connection']);
});
}
Replace the boot function as below:
public function boot()
{
Auth::provider('customUser', function($app, array $config) {
return new CustomUserProvider($config['model']);
});
}
I have server login to my site. I use for API Restler 3 with OAuth2.
Server.php:
<?php
namespace Auth;
use Luracast\Restler\iAuthenticate;
use OAuth2\GrantType\UserCredentials;
use OAuth2\Storage\Pdo;
use OAuth2\Server as OAuth2Server;
use OAuth2\GrantType\AuthorizationCode;
use OAuth2\GrantType\ClientCredentials;
use OAuth2\Request;
use OAuth2\Response;
/**
* Class Server
*
* #package OAuth2
*
*/
class Server implements iAuthenticate
{
private $host = DB_HOST;
private $dbName = DB_NAME;
private $user = DB_LOGIN;
private $pass = DB_PASS;
/**
* #var OAuth2Server
*/
protected static $server;
/**
* #var Pdo
*/
protected static $storage;
/**
* #var Request
*/
protected static $request;
public function __construct()
{
$dns = "mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=utf8";
static::$storage = new PDO(
array('dsn' => $dns, 'username' => $this->user, 'password' => $this->pass)
);
$grantTypes = array(
'authorization_code' => new AuthorizationCode(static::$storage),
'user_credentials' => new UserCredentials(static::$storage),
);
static::$request = Request::createFromGlobals();
static::$server = new OAuth2Server(
static::$storage,
array('enforce_state' => true, 'allow_implicit' => true),
$grantTypes
);
$grantType = new ClientCredentials(static::$storage);
static::$server->addGrantType($grantType);
}
/**
* Stage 2: User response is captured here
*
* Success or failure is communicated back to the Client using the redirect
* url provided by the client
*
* On success authorization code is sent along
*
*
* #param bool $authorize
*
* #return \OAuth2\Response
*
* #format JsonFormat,UploadFormat
*/
public function postAuthorize($authorize = false)
{
static::$server->handleAuthorizeRequest(
static::$request,
new Response(),
(bool)$authorize
)->send();
exit;
}
/**
* Stage 3: Client directly calls this api to exchange access token
*
* It can then use this access token to make calls to protected api
*
* #format JsonFormat,UploadFormat
* #access public
* #url POST apiMobile/grand
* #url GET apiMobile/rer
*/
public function postGrant()
{
static::$server->handleTokenRequest(static::$request)->send();
exit;
}
/**
* Access verification method.
*
* API access will be denied when this method returns false
*
* #return boolean true when api access is allowed; false otherwise
*/
public function __isAllowed()
{
$token = static::$server->getAccessTokenData(Request::createFromGlobals());
global $idClient;
$idClient = $token['client_id'];
return self::$server->verifyResourceRequest(static::$request);
}
public function __getWWWAuthenticateString()
{
return 'auth string';
}
}
?>
And init.php:
<?php
use Luracast\Restler\Restler;
class ApiMode
{
private $class = '';
private $function = '';
public function __construct($controller = DEFAULT_CONTROLLER, $function = DEFAULT_FUNCTION)
{
$this->class = $controller;
$this->function = $function;
$controllerClass = ucfirst($this->class).CONTROLLER_TERMINAL;
$controllerPatch = CONTROLLER_DIR.'/'.$controllerClass.'.php';
require_once $controllerPatch;
require_once EXTERN_DIR.'/OAuth2/Autoloader.php';
OAuth2\Autoloader::register();
require_once EXTERN_DIR.'/vendor/restler.php';
require_once CLASS_DIR.'/Server.php';
$r = new Restler();
$r->addAuthenticationClass('Auth\\Server', '');
$r->setSupportedFormats('JsonFormat', 'XmlFormat');//,
$r->addAPIClass($controllerClass,'');
$r->setOverridingFormats('JsonFormat');
$r->setOverridingFormats('UploadFormat');
$r->handle();
}
}
?>
I use only Stage 3 - postGrand to get access token.
From web browser on http://mypage/apiMobile/rer.json (GET is for test from my web browser if GET work, POST work well) get:
local server Windows (this is OK):
{"error":"invalid_request","error_description":"The request method must be POST when requesting an access token","error_uri":"http:\/\/tools.ietf.org\/html\/rfc6749#section-3.2"}
web server (use https) Linux PHP 5.5.21 (fail):
{
"error": {
"code": 404,
"message": "Not Found"
},
"debug": {
"source": "Routes.php:438 at route stage",
"stages": {
"success": [
"get"
],
"failure": [
"route",
"negotiate",
"message"
]
}
}
}
On web server and local work all from API (address: mypage/apiMobile/myApi.json from controller):
$r->addAPIClass($controllerClass,'');
Main problem is with access to OAuth2 (I need access from http://mypage/apiMobile/rer.json). Any idea or tutorial?
Thanks.