How to fix 401 Unauthorized response WP Rest API - wordpress

Im making a request to another wordpress site on our network as below.
//Send the request to update the submission post
$response = wp_remote_request( $this->urls->assign_url, array(
'headers' => array(
'Content-Type' => 'application/json; charset=utf-8',
'Authentication' => 'Basic '.base64_encode('somename:somepassword')
),
'body' => json_encode($array),
'method' => 'POST',
'data_format' => 'body'
)
);
Im making this request via ajax.
The callback function is being called and sends back data.
Im also logged into the remote site.
Im using a nonce and the user being authorised in the headers is a valid user.
All I keep getting back is:
body: "{"code":"rest_not_logged_in","message":"You are not currently logged in.","data":{"status":401}}"
Ive only just started getting this since I updated the remote wordpress version. It was working fine before that.
Any thoughts.

I believe in order to authenticate the way you want to, you need to use a plugin - the built-in authentication method is not ideal for offsite requests since it is cookie based.
https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/#authentication-plugins

Related

Wordpress get user info from same browser logged into site

I'm trying to use the Wordpress API wp_get_current_user(), however it's always returning the 0 user, with empty data. I am on a fresh install of Wordpress and I have just created my own theme and added an API hook.
I see lots of guides/info on grabbing data using Nonce from a separate client/computer, but I'm just trying to get the $user from the same browser that should be already logged in via the wordpress admin interface. I've verified that my browser has cookies set. My understanding of verification is that wp_get_current_user() should be able to use these cookies to verify my user and return data. .
Just to show I am logged into wordpress
This is my functions.php
located under wp-content/themes/myapi/functions/
add_action('rest_api_init', function () {
register_rest_route( 'api', 'test',array(
'methods' => 'GET',
'callback' => 'logged_in_wp',
));
});
function logged_in_wp($request){
if ( is_user_logged_in() ) {
return new WP_Error( 'me', 'me', array( 'status' => 200 ) );
}
return new WP_Error( 'not-logged in WP', 'not-logged in WP', array( 'status' => 400 ) );
}
?>
I'm using the following URL to access the data
http://localhost:8080/?rest_route=/api/test
I'm expecting it to return a me,me,200, instead, i'm only seeing the not-logged-in 400 error.
so what is the difference between localhost:8080 and localhost:8080?rest_route=/api/test that wordpress cannot figure out that I am logged in?
So, I'm guessing since nobody is answering and based on the readings I've done. What I'm asking for is impossible. It seems it is a security response by wordpress. You will need to authenticate even if the user is logged into Wordpress on the same domain/browser.
What do you use to test your request?
Using postman, you can insert useful parameters which will help you on authentication. Hence if you want to logged in using the WordPress Rest api, you must insert information of the current user properly in the section Authorization (Chose basic authentication and inside, fill the username and the password of an existing account (in this case Admin) and try it again.
Here is what i did for an exemple:
Sample image for the authorization which will soon help to know about the current user login
next using
$user_id = username_exists($username);
$user = get_user_meta($user_id);
$response['code'] = 200;
using "get_user_meta(wp_get_current_user()->ID, 'nickname', true);"
you can now determine the current user been logged.
Here in this sample if you make good use of the above information, you can create a good function "logged_in_wp()".
Here is my result on postman
I hope this will help you by the way

What is the correct format and sequence to acquire the correct token for LinkedIn API V2?

Our LinkedIn APP no longer works with the evolution of V2. I have tried a couple of times and failed to create the correct token. I am seeking help to create the correct authorization link to get the token. Error from the App is currently "Empty oauth2 access token"
I created a new LinkedIn app to replace our old one. I have tried to follow the instructions from LinkedIn and Microsoft but my efforts have produced the following error
My most recent attempt was:
https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=78xaqf0ereiisy&redirect_uri=https://www.gachina.com&state=gachina&scope=r_emailaddress r_liteprofile w_member_social
I received: https://www.gachina.com/?code=AQS65Njp1F9-L-mKSrAJKZeQ-ij2OX7wboTc30-hrfQIwwJ0yfWd4FBqxLl-ZXHmL5HurKud4t9WcGeHB62EfPNcy3ddoqT1LztUHhR59iL-Q8f9WLrX03d9e3OCTmY-3vR8a_4ENeIN0GFpeLy7DKRDmuUNcQ82UwScqhApdtwzEBw-_Y0duYG87Lc1KQ&state=gachina
then I used the format shown here:
https://learn.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow
https://www.linkedin.com/oauth/v2/accessToken?grant_type=authorization_code&code={authorization_code_from_step2_response}&redirect_uri=hhttps%3A%2F%2Fdev.example.com%2Fauth%2Flinkedin%2Fcallback&client_id={your_client_id}&client_secret={your_client_secret}
with
https://www.linkedin.com/oauth/v2/accessToken?grant_type=authorization_code&code=AQS65Njp1F9-L-mKSrAJKZeQ-ij2OX7wboTc30-hrfQIwwJ0yfWd4FBqxLl-ZXHmL5HurKud4t9WcGeHB62EfPNcy3ddoqT1LztUHhR59iL-Q8f9WLrX03d9e3OCTmY-3vR8a_4ENeIN0GFpeLy7DKRDmuUNcQ82UwScqhApdtwzEBw-_Y0duYG87Lc1KQ&redirect_uri=https://www.gachina.com/auth/Linkedin/callback&client_id=78xaqf0ereiisy&client_secret={client_secret}
but I receive the following upon submitting the above link with our {client secret} in place
{"error":"invalid_redirect_uri","error_description":"Unable to retrieve access token: appid/redirect uri/code verifier does not match authorization code. Or authorization code expired. Or external member binding exists"}
I am doing all of this within minutes. So, I do not believe there is an expiration of code.
Can you help identify the error of steps or code to receive a Token?
This will return the access token
$params = array('grant_type' => 'authorization_code',
'client_id' => $this->api_key,
'client_secret' => $this->api_secret,
'code' => $_GET['code'],
'redirect_uri' => base_url().$this->redirect,
);
// Access Token request
$url = 'https://www.linkedin.com/oauth/v2/accessToken?' . http_build_query($params);
$data_len = strlen(http_build_query($params));
// Tell streams to make a POST request
$context = stream_context_create(
array('http' =>
array('method' => 'POST','header'=> 'Content-Length: 0'
)
)
);
// Retrieve access token information
$response = file_get_contents($url, false, $context);
$token = json_decode($response);
return $token->access_token;

Computer Vision API - v1.0 Recognize Handwritten Text returns empty response

I am trying to start using the computer vision API but I keep getting an empty response. My request in php (as exported by Postman) looks like this:
<?php
$request = new HttpRequest();
$request->setUrl('https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/recognizeText');
$request->setMethod(HTTP_METH_POST);
$request->setQueryData(array(
'language' => 'en',
'handwriting' => 'true'
));
$request->setHeaders(array(
'Postman-Token' => '442d04f7-49a0-4262-9d0f-666fe5240cc7',
'Cache-Control' => 'no-cache',
'Content-Type' => 'application/octet-stream',
'Ocp-Apim-Subscription-Key' => 'KEY'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
The above code works fine with the ocr endpoint!
The file is passed as binary using Postman.
Edit: I also tried to copy/paste the code from here: https://learn.microsoft.com/en-gb/azure/cognitive-services/computer-vision/quickstarts/php#ocr-php-example-request and if I change the ocr endpoint to recognizeText I get an empty response as well!
Unlike the other Computer Vision endpoints, RecognizeText is an asynchronous operation. Barring some issue with the image, you will get a 202 response instead of the usual 200 response. 202 responses customarily contain an empty response body. In this particular case you can find the URL where you can query for completion of the task. The documentation is here. The header you're looking for is Operation-Location.

Custom wordpress login with API Rest and angular

is there a way to create a Custom login with the API Rest of Wordpress and angular.
Currently I'm using the WP REST API - OAuth 1.0a Server plugin but I can´t figure out how to do it
Or maybe its posible using the two methods (Basic Authentication and OAuth)?
I would appreciate any help
I have been wrestling with this the past couple weeks. It kind of depends on your use case.
First, don't use Basic Auth. It's insecure and for development only. Not worth the time to set up.
OAuth (I think) is for when you already have a repository of users somewhere, and those users want to give your app approval to access their info, create an account for them, etc. Think of a "Login with Faceook!" button or something, that's OAuth. Could be wrong but I don't think that's what you want.
What I landed on, and what I think you are asking for, was JWT or JSON Web Token Auth. This is best for me because I want users to be able to create new user accounts and login to them completely within the app.
First, install the JWT Authentication for WP-API plugin:
https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/
This will expose a new endpoint for JWT authentication in the REST API. You will ping that endpoint with user credentials, and get a token response. You then store that token somehow (I'm currently using localStorage) and append it to the request headers of every request that requires permissions. De facto you are logged in! See the plugin docs for details. The example code for attaching the request is in AngJS, not Ang2/4, but the concept is the same. Here's an example from a service that posts a comment.
postComment(comment): any {
let headers = new Headers({ 'Authorization': 'Bearer ' + JSON.parse(localStorage.getItem('currentUser')).token});
let options = new RequestOptions({ headers: headers });
return this.http
.post(this._wpBase + "comments", comment, options)
.subscribe((res: Response) => {
res.json();
});
}
There is probably a fancier, global way to do this but I am still figuring it all out. Hope this is helpful!
Paste Following code in your themes function.php file.
Make sure that WP-REST-API plugin Should be installed on wordpress site
add_action( 'rest_api_init', 'register_api_hooks' );
function register_api_hooks() {
register_rest_route(
'custom-plugin', '/login/',
array(
'methods' => 'GET',
'callback' => 'login',
)
);
}
function login($request){
$creds = array();
$creds['user_login'] = $request["username"];
$creds['user_password'] = $request["password"];
$creds['remember'] = true;
$user = wp_signon( $creds, false );
if ( is_wp_error($user) )
echo $user->get_error_message();
return $user;
}
add_action( 'after_setup_theme', 'custom_login' );
Then your API will be created as
http://www.url.com/wp-json/custom-plugin/login?username=xyz&password=xyz
Try it with Postman You will get 200 as a response and user info

Can't make OAuth work in Drupal 6 / Services 3

I'm working on a project and the client requested i use OAuth to protect some custom services I've built. I've got everything working perfectly using no authentication and session authentication, but using OAuth makes the whole thing fall apart. I haven't been able to find any really good step by step tutorials.
Basically I've got the Services 6.x-3.1 and OAuth 6.x-3.0-beta4 modules installed on D6. I created an oauth context using this documentation. Then I setup a dummy user because I only want to create one set of consumer credentials for all of my clients. I assigned the context to the user and to the service. I'm using http://mydomain/oauth/authorized as the callback url.
To test I connect using http://term.ie/oauth/example/client.php. I use the endpoint http://mydomain/oauth/request_token. I add the response tokens to the appropriate fields. Then I change the endpoint to http://mydomain/oauth/authorize. It takes me to a page where I have to click to allow the connection. I'm taken to the http://mydomain/oauth/authorized page where I get a success message.
Now I change the endpoint to http://mydomain/oauth/access_token and I get a response with a new token. According to these instructions, I replace the new access tokens and change the endpoint to http://mydomain/myserviceendpoint. It connects using a GET request and returns
401 Unauthorized: The consumer is not authorized to access this
service.
It feels like I'm missing something. There is only one context in the system and it's assigned to both the consumer and the service. The consumer key and secret are part of the final url along with the access token. I've looked at permissions and I can't find anything out of place. I even changed my service to just return TRUE for the hook_services_access to bypass permissions.
Any ideas?
First you must understand the difference between the two.
first the session authentication takes a user name and password and authenticates. Then it takes the user permissions from drupal so you need to authenticate in each step to go through your application that communicate with your drupal. Anonymous users can get what they want according to your permission in drupal.
While in Aouth authentication you create a user and add token to him and only the user who had the token communicate with the application according to the permission rule you set to him . In case of anonymous users they can't retrieve or get anything. The communication between drupal and the client within the created used with a certain token.
Finally: goto user page and create a user and give him the application name also token and in your application code give the token to application and authenticate with the newly created user.
You must check your permissions to the newly created user.
Check this link
Same problem like you... As there are not really good tutorials, sometimes its hard, so hope that this helps someone.
Solution:
You have to give oauth permisions to your resources in your endpoint definition, in my_module_default_services_endpoint(). Let's say you want to enable resource user via oauth. Normally you would have:
...
$endpoint->resources['user'] = array(
'operations' => array(
'ta_create' => array('enabled' => 1, ),
),
'actions' => array(
'login' => array('enabled' => 1, ),
'logout' => array('enabled' => 1, ),
'ta_register' => array('enabled' => 1, ),
),
);
...
So you have to authorize your resources like this ('user_info' is the permision required to access this resource):
...
$endpoint->resources['user'] = array(
'operations' => array(
'ta_create' => array('enabled' => 1, 'services_oauth' => array('credentials' => 'token', 'authorization' => 'user_info', ), ),
),
'actions' => array(
'login' => array('enabled' => 1, ),
'logout' => array('enabled' => 1, 'services_oauth' => array('credentials' => 'token', 'authorization' => 'user_info', ), ),
'ta_register' => array('enabled' => 1, ),
),
);
...
The ones you enable via 'services_oauth' will be only accessible via oauth. I'm wondering if you can mix oauth access services and normal oauth services.
How did I find the solution:
If you enable services debugging, you will notice the following PHP warning:
Notice: Undefined index: services_oauth en _services_oauth_authenticate_call() (línea 26 de C:/.../services_oauth.inc).
If you go to _services_oauth_authenticate_call() in services_oauth.inc and print the stack trace (thanks to http://php.net/manual/en/function.debug-print-backtrace.php):
ob_start();
debug_print_backtrace();
$trace = ob_get_contents();
ob_end_clean();
watchdog('my_module', 'StackTrace: %st', array('%st' => $trace,), WATCHDOG_DEBUG);
Then you will see that *$method['endpoint']['services_oauth'];* is not set. So you have to set it in my_module_default_services_endpoint()
Your service endpoint is not to be used with the OAuth test client. Once you are authenticated, you pass your OAuth tokens to the service endpoint along with your method.

Resources