Laravel 5.8 API + WordPress integration - wordpress

I am building an APP with Laravel and all functions from User model must provide through API and show them in WP.
They need to "connect with MyApp(login)" and use the same credentials like in Laravel. I made login API and it returns token, expiration date, but when I need to access user object and return it, it says "message": "Unauthenticated."
This is my code:
LOGIN
public function login(Request $request){
$request->validate([
'email' => 'required|string|email',
'password' => 'required|string',
]);
$credentials = request(['email', 'password']);
if (!Auth::attempt($credentials)) {
return response()->json([
'message' => 'Unauthorized'
], 401);
}
$user = $request->user();
$tokenResult = $user->createToken('Personal Access Token ' . str_random(10));
$token = $tokenResult->token;
if ($request->remember_me) {
$token->expires_at = Carbon::now()->addWeeks(10);
}
$token->save();
return response()->json([
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse(
$tokenResult->token->expires_at)
->toDateTimeString(),
]);
}
Auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
]
],
Api.php
Route::post('/login', 'Api\AuthController#login')->name('login.api');
Route::middleware('auth:api')->get('/user', function (Request $request){return $request->user();});
// Route::post('/register', 'Api\AuthController#register')->name('register.api');
Route::middleware('auth:api')->group(function () {
Route::get('/logout', 'Api\AuthController#logout')->name('logout');
});
Also i have this in both .htaccess
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
I need to fetch user object and retrieve informations by calling model function ex. $user->allClients.

Related

How to authenticate for remote access to protected data in LearnDash via the Wordpress REST API?

I am developing a mobile app (in Flutter) that needs to access course data of the user from a Wordpress LearnDash LMS environment. The Wordpress site is accessible via the standard REST API through the https://<site>/wp-json/ldlms/v1/ path.
But whenever I try to access e.g. <...>/ldlms/v1/sfwd-courses/<id>/steps, the result is a 401 (Unauthorized) status.
From the Wordpress documentation I learned it uses cookie authentication. But adding the wordpress_logged_in_<hash> cookie to the request header does not seem to make a difference.
Where can I find the missing authentication details required to access this information?
I just built my REST API; so I may be of some help. The example below will:
Register a custom rest api endpoint
Localize server-side variables on first load (endpoint, user object, etc)
Append the NONCE to all rest requests avoiding the hash BS
Rest API Authentication Reference
functions.php
add_action('rest_api_init', 'register_custom_fields');
function register_custom_fields(){
register_rest_route(
'app', '/login/',
[ 'methods' => 'POST', 'callback' => 'asset_login' ]
);
}
function asset_login(){
$user = wp_signon($_POST);
if (is_wp_error($user)){
return [ 'result' => 'fail', 'error' => $user->get_error_message() ];
} else {
return [ 'result' => 'success', 'user' => [ 'ID' => $user->data->ID, 'name' => $user->data->display_name ] ];
}
}
add_action('init','stage_script');
function stage_script(){
wp_enqueue_script('asset-library', trailingslashit(get_stylesheet_directory_uri()) . 'js/asset-library.js', ['jquery']);
$assetUser = null;
if (is_user_logged_in()){
$user = wp_get_current_user();
$assetUser = [
'ID' => $user->data->ID,
'name' => $user->data->display_name,
'nickname' => $user->data->user_nicename,
'email' => $user->data->user_email,
'allcaps' => $user->allcaps
];
}
wp_localize_script( 'your-app', 'App', [
'user' => $assetUser,
'api_endpoint' => esc_url_raw( rest_url() ),
'api_version' => 'wp/v2/',
'nonce' => wp_create_nonce( 'wp_rest' )
]);
}
script.js
// The Login Controller
let AppUser = {
loggedIn: false,
login: function(data){
$.ajax( {
url: App.api_endpoint + 'your-app/login',
method: 'POST',
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', App.nonce );
},
data: data,
success: function(response){
/* ... parse response ... */
},
error: function(response){
/* ... parse response ... */
}
});
}
};
// The API Controller
let QueryController = {
Objects: [],
getObjects: async function(){
let q = {};
/* ... build query stuff extracted */
try {
const response = await $.ajax( {
url: App.api_endpoint + App.api_version + 'post_object',
method: 'GET',
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', App.nonce );
},
data: q
});
this.Objects = response;
return response;
} catch(e) {
console.log('Error: ', e);
}
}
};

Integrating wordpress and laravel login

I am developing three area for my website.. using WordPress (Front Page), XenForo (Forum), and Laravel (Member Area) ... i already succeed integrating my laravel and XenForo, so when XenForo user login to Member Area my function will check if the user already exist (If XenForo user exist then laravel will create the user in database using XenForo user data, if not exist then login failed)
Now i want to do the same for WordPress .. when user login to member area the function will check if WordPress user is exist or not .. if exist then new user will be created using wordpress user data (name, email, password, and token if possible) if not exist then login failed, but how do i do this? unlike XenForo .. i can't find WordPress API documentation for getting user data
Edit 1 :
This is my login function
public function login_post(Request $request){
// XENFORO API AUTH START
$http = Http::withHeaders([
'XF-Api-Key' => 'SECRET'
])->asForm()->post('http://forum.mywebsite.com/api/auth', [
'login' => $request->email,
'password' => $request->password
]);
if(isset($http['errors'])){
return redirect('login')->with('error', 'Username and Password Error');
}
$name = $http['user']['username'];
$email = $http['user']['email'];
$password = $request->password;
$is_admin = $http['user']['is_admin'];
$user_id = $http['user']['user_id'];
// XENFORO API AUTH END
// WordPress API AUTH START
$client = new \GuzzleHttp\Client([
// Base URI is used with relative requests
'base_uri' => 'http://mywebsite.com/',
'headers' => ['Content-Type' => 'application/json', "Accept" => "application/json", 'Authorization' => 'Basic ' . base64_encode( 'ADMIN' . ':' . 'PASSWORD' ),],
]);
$response = $client->get('users/', [
'query' => [
'email' => $request->email,
]
]);
return json_decode($response->getBody());
// WordPress API AUTH END
if (Auth::attempt(['email' => $email, 'password' => $password])) {
# code...
if(Auth::user()->role == 0){
return redirect('dashboard');
}
return redirect('login');
} else {
$newUser = new User;
$newUser->name = $name ;
$newUser->email = $email;
$newUser->password = bcrypt($password);
$newUser->role = $is_admin;
$newUser->save();
auth()->login($newUser, true);
return redirect('dashboard');
}
}
Edit 2 :
$client = new \GuzzleHttp\Client([
// Base URI is used with relative requests
'base_uri' => 'http://mywebsite.com/wp-json/wp/v2/',
'headers' => ['Content-Type' => 'application/json', "Accept" => "application/json", 'Authorization' => 'Basic ' . base64_encode( 'ADMIN' . ':' . 'PASSWORD' ),],
]);
$response = $client->get('users/', [
'query' => [
'email' => $request->email,
]
]);
$response = json_decode($response->getBody());
$name = $response['username'];
$email = $response['email'];
$password = $request->password;
$is_admin = $response['role'];
$user_id = $response['id'];
The Response :
array:3 [▼
0 => {#287 ▼
+"id": 1
+"name": "Admin"
+"url": "http://www.mywebsite.com"
+"description": ""
+"link": "http://mywebsite.com/author/admin/"
+"slug": "admin"
+"avatar_urls": {#285 ▶}
+"meta": []
+"_links": {#281 ▶}
}
1 => {#274 ▼
+"id": 2
+"name": "Prima"
+"url": ""
+"description": ""
+"link": "http://mywebsite.com/author/prima/"
+"slug": "prima"
+"avatar_urls": {#272 ▶}
+"meta": []
+"_links": {#279 ▶}
}
2 => {#288 ▼
+"id": 3
+"name": "TEST ER"
+"url": ""
+"description": ""
+"link": "http://mywebsite.com/author/testing/"
+"slug": "testing"
+"avatar_urls": {#289 ▶}
+"meta": []
+"_links": {#291 ▶}
}
]
WordPress doesn't provide API to check user exists or not, however you can check this by using List Users API.
Here is what I have done in Laravel:
$client = new \GuzzleHttp\Client([
// Base URI is used with relative requests
'base_uri' => 'http://www.example.com',
'headers' => ['Content-Type' => 'application/json', "Accept" => "application/json"],
]);
$response = $client->get('users/', [
'query' => [
'search' => 'example#email.com',
]
]);
return json_decode($response->getBody());
With Authorization:
Install this https://github.com/WP-API/Basic-Auth plugin and update headers, $username & $password refers to WP admin credentials.
$client = new \GuzzleHttp\Client([
// Base URI is used with relative requests
'base_uri' => 'http://www.example.com',
'headers' => ['Content-Type' => 'application/json', "Accept" => "application/json", 'Authorization' => 'Basic ' . base64_encode( $username . ':' . $password ),],
]);

Cakephp 3 - Query Fixture in IntegrationTestTrait

I am having issues querying a loaded Fixture in my TestCase for an IntegrationTestTrait. I want to verify that a record already exist inside of a Fixture, then insert a duplicate record and verify that there is still only 1 record in the database.
During my test case initialization, I set the session variable for authentication.
public function setUp() {
parent::setUp();
$this->loadFixtures(
'Students', 'Users');
// Configure Authentication
$this->session([
'Auth' => [
'User' => [
'id' => 21896,
'institution_id' => 1,
'student_id' => null,
'contact_id' => 91,
'email' => 'AuthenticatedEmail#school.edu',
'role' => 'DSP',
'is_admin' => false
]
]
]);
// Load Tables
$this->Students = TableRegistry::getTableLocator()->get('Students');
}
In my Test Case, I check to see if the Database contains a record, then submit a POST request then test to see if the record did not insert.
public function testAddStudentSuccess() {
$data = [
'institution_id' => 1,
'contact_id' => null,
'id_number' => '200XYZ',
'last_name' => 'Trimor',
'first_name' => 'Paul',
'email' => '1_test#email.com'
];
// Test Pre-condition
$query = $this->Students->find('all')->where([
'id_number' => $data['id_number']
]);
$this->assertEquals(1, $query->count());
$this->post('students/add', $data);
// Test Post-condition
$this->assertResponseSuccess();
$query = $this->Students->find('all')->where([
'id_number' => $data['id_number']
]);
$this->assertEquals(1, $query->count());
}
However, when I run the Test Case, I get the following error:
Notice Error: Undefined variable: _SESSION in/var/www/html/samusg/src/Model/Table/StudentsTable.php, line 206]
A couple things:
The last assertion works! After $this->post('students/add', $data) is submitted, the $query is populated with data.
The first assertion does not work. I debug the Fixture before the $this->post() is called and it returns empty.
In the Test Table, there is a test for $_SESSION variable, which is what line 206 referring to.
Long Story short: The Fixture is not populated with data during the start of the Test Case, but once the integration runs then the Fixture magically contains all the data. I get $_SESSION errors, but I already set the session in the setUp(), so I'm lost.
I greatly appreciate any help. Thank you
I was able to by pass this message by setting the $_SESSION super global directly on my Test:
public function setUp() {
parent::setUp();
$this->loadFixtures(
'Students', 'Users');
// Configure Authentication
$this->session([
'Auth' => [
'User' => [
'id' => 21896,
'institution_id' => 1,
'student_id' => null,
'contact_id' => 91,
'email' => 'AuthenticatedEmail#school.edu',
'role' => 'DSP',
'is_admin' => false
]
]
]);
$_SESSION = [
'Auth' => [
'User' => [
'id' => 21896,
'institution_id' => 1,
'student_id' => null,
'contact_id' => 91,
'email' => 'AuthenticatedEmail#school.edu',
'role' => 'DSP',
'is_admin' => false
]
]
];

How to integrate PowerBI in symfony4

I want to integrate an Advanced statistics in my project symfony 4
so i decide to use PowerBI ( if you have an alternative please let me know),
my question is how to integrate it in my local project symfony4 and in relation with my database MySQL
Untill now , there no Symfony bundle for power bi , but instead you can use :
the adevait/power-bi
In case you don't find options you are looking for , you can using the native power bi rest api
You need to create an account and manage it by creating your dataset etc ...
Requirement :
GuzzleHttp
The point here is to create for example a service that manage calling the api :
example for authentication :
try {
/** #var GuzzleHttp\Client $client **/
$response = $client->post(
'https://login.windows.net/<tenant-id>/oauth2/token',
[
"headers" => [
"Accept" => "application/json"
],
'form_params' => [
'resource' => 'https://analysis.windows.net/powerbi/api',
'client_id' => $this->clientId,
'client_secret' => $this->secret,
'grant_type' => 'password',
'username' => $this->username,
'password' => $this->password,
'scope' => 'openid',
]
]
);
$body = json_decode($response->getBody()->getContents(), true);
return $body['access_token'];
} catch (ClientException $e) {
return ['error' => $e->getMessage()];
}
At this point , you need the token to call other endpoint , so you need to inject the returned token in the header of any request you send like :
try {
/** #var GuzzleHttp\Client $client **/
$client->post(
https://api.powerbi.com/v1.0/myorg/groups/<group-id>/datasets/<dataset-id>/tables/<table-name>/rows,
[
'headers' => [
"Accept" => "application/json",
"Authorization" => sprintf("Bearer %s", $token),
],
'json' => $data
]
);
return true;
} catch (ClientException $e) {
return false;
}
Hope that help you .

ZF3 development of RestAPI: handling Post request for

I am new to Zf3, and developing Email Restful API.
having difficulties in handling request. I can't get POST parameters.i think there is some problem in module.config.php > 'router'
Questions
1 How can I get POST variables from request.
2 I found it when I request page (using Postman)
- if I passes ID, controller call get($id) method
- if I POST variables controller calls Create($data) function.
--is this always the case ? and is it good to write zendEmail code inside create($data) method
.
bwsmail controller
(create function)
public function create($data)
{
echo $this->getRequest()->getPost('id', "no value");
// Output
// this returns no value
echo $this->getRequest();
// Output
//POST http://localhost:8080/bwsmail/mail?id=123456789 HTTP/1.1
//Cookie: PHPSESSID=p5i7o8lm2ed0iocdhkc8jvos01
//Cache-Control: no-cache
//Postman-Token: ccaf5b37-02a2-4537-bf3f-c1dc419d8ceb
//User-Agent: PostmanRuntime/7.6.1
//Accept: */*
//Host: localhost:8080
//Accept-Encoding: gzip, deflate
//Content-Length: 0
//Connection: keep-alive
$response = $this->getResponseWithHeader()->setContent( __METHOD__.' create new item of data :<b>'.'</b>');
return $response;
}
module.config.php (route)
'bwsmail' => [
'type' => Literal::class,
'options' => [
'route' => '/bwsmail',
'defaults' => [
'controller' => Controller\BwsMailController::class,
]
],
'may_terminate' => true,
'child_routes' => [
'mail' => [
'type' => 'segment',
'options' => [
'route' => '/mail[/:id]',
'constraints'=>
[
'id' => '[0-9a-zA-Z]+',
],
'defaults' => [
'controller' => Controller\BwsMailController::class,
]
],
],
],
],
if BwsMailController extends AbstractController or AbstractRestfulController you can simply: $this->params()->fromRoute() or ->fromQuery() if you're using a get string. For example:
$routeParamId = $this->params()->fromRoute('id', null);
This gets the parameter id as it is defined in the route configuration. If it's not set, it will default to null.
If you have a GET url, something like: site.com/mail?id=123, then you do:
$getParamId = $this->params()->fromQuery('id', null); // sets '123' in var
More options are available, have a good read of the routing documentation.

Resources