Cors nginx and setCookie with JWT token - php

I have project divided into frontend and backend. Backend is available on mydomain.com/api and I need to develop frontend project which cooperate with backend on mydomaion.com/api.
First problem was CORS - It`s ok. I allowed CORS.
But now I am facing to second problem. When I sign-in in frontend, backend set BEARER token.
setcookie('BEARER', $token, 0, '/', '', false, true);
I expect when I send next request to API, cookie BEARER header automatically attached. Unfortunatelly no headers attached and therefore I get response 401 Unauthorized because I am not logged in.
I think that problem is domain. Frontend running on my local PC mydomain.test and API running on mydomain.com.
I think I need something like this:
setcookie('BEARER', $token, 0, '/', '*', false, true);
But this is not working too.
Solve somebody same problem?

I dont know what are you using in your backend, but i think your problem is on your CORS config. Normally you need to allow the origin you are using, headers and credentials. In ASP.NET CORE it would look something like this:
builder.WithOrigins("http://localhost:8080")
.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed(origin => true)
.AllowCredentials();
And since you are using jwt token you need to add it:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
//your jwt options config
})
)

Related

Laravel API (Sanctum) + nuxt auth - weird cookies behaviour, I don't get it

Perhaps what I am looking at is normal and ok but I am not sure. I would love some explanation.
So I have SPA in NuxtJS (separate app) and API in Laravel 8. I have managed to authenticate my SPA with Sanctum and my Laravel API is giving me back data from restricted endpoints. I am using Nuxt Auth to facilitate the whole process.
THE PROBLEM
I've noticed strange behavior. Any request (not just login) pops the xsrf cookie in the browser. I don't understand that, I don't know why. I don't think it's right. Response headers are setting these cookies one is session and one is for xsrf but I have more. I do keep the encrypted vuex store in local storage but these are cookies so I have no clue what that might be.
The second part of the problem, the cookies are changing each time I request something from API. So does that mean if the cookie session has changed the session has been refreshed now and it has new TTL? Should they not remain the same?
Third part I am getting some weird encrypted cookies which I cannot account for. Is this sanctum?
These are my other settings:
/etc/hosts
127.0.0.1 publisher.com #frontend
127.0.0.1 api.publisher.com #backend
nuxt.config.js
auth: {
strategies: {
laravelSanctum: {
provider: 'laravel/sanctum',
url: 'http://api.publisher.com:8080',
endpoints: {
login: { url: '/login', method: 'post' },
// logout: { url: '/api/v1/logout', method: 'post' },
user: { url: '/api/v1/user', method: 'get' }
}
},
},
},
sanctumm.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1,local:3000,publisher.com:3000',
Sanctum::currentApplicationUrlWithPort()
))),
session.php
'domain' => env('SESSION_DOMAIN', '.publisher.com'),
My biggest concerns are that I do not understand why the cookies are refreshed with each request to my API.
Apart from that, I can log in, I am just struggling to understand what is happening.
Can someone shed some light on what is up?
P.S UPDATE I think the extra cookies might be due to session driver set to cookie it's gone since I changed it to file but the rest of the problems remains.

I m getting Unauthenticated. on laravel sanctum api

so I created the login it worked well but when I want to fetch user posts it returns Unauthenticated even tho I sent the token and used the xsrf cookies but still the same problem
axios call
axios.defaults.withCredentials = true;
axios.get('/sanctum/csrf-cookie').then(response => {
axios.get('/api/posts/20',{headers:{Authorization: `Bearer ${localStorage.getItem('userToken')}`}}).then(res=>{
console.log(res);
})
api route
Route::post('login',"UserController#index");
Route::get('posts/{id}', 'PostController#index')->middleware('auth:sanctum');
please help me guys keep in mind I tried everything out there but nothing works
I had problem in domain as TEFO said I launched the backend on virtual host + adding configuration to cors.php solved the problem

Settings a Cookie by POSTing to a RESTful Magento controller

I am building an application which will eventually reside on the same domain where another application resides; both of which are written in PHP. One is a Laravel application and the other a Magento 1.9 store.
To authenticate the user, the Laravel application requires that a certain cookie be set by the Magento store's response, subsequently retrieved and parsed, all before authentication may continue.
My current strategy is a POST to a custom controller which delivers multiple Set-Cookie headers from the Magento store.
The one I need is something like:
Set-Cookie: auth_token=TheValueWeNeedToContinueAuthenticating; domain='.mydomain'; ...
The server I am testing on is an in-house staging environment. The server's VHost is set to Laravel's public directory, as usual.
The Magento store is on a different server however the TLD is the same .mydomain
I have verified the response in Postman, I am indeed returning the cookie with the correct Set-Cookie in place, however it is not visible in my Laravel application as the other cookies from Magento, are. The other cookies were verified within the response as I dumped Guzzle's CookieJar and still received all but the cookie I am looking for.
I am using PHP's Guzzle HTTP Library to post from a Laravel 5.6 app using PHP 7.1
The Magento1.9 store unfortunately uses PHP/5.6.35
When I dump the HTTP response I am getting the cookies which would normally receive had I actually visited any page within the store.
What else could I check to ensure I am taking to right approach to receiving this cookie? Https is the transmission protocol, and the content-type is x-www-form-urlencoded if that will assist an answer in any way.
Thank you.
UPDATE 1.0 - I was able to get a clean error reading from the request being sent.
{"status":"error","message":"invalid request"}
Here is my Guzzle Post request
$jar = new \GuzzleHttp\Cookie\CookieJar;
// Logging my error output -- I can share this if I must
$debug_file = fopen('../storage/logs/debug.txt', 'a');
try {
$payload = 'Knock, knock';
$url = '/api/for/post';
$client = new Client([
'base_uri'=> 'https://mySubdomain.myDomain.com',
'debug' => $debug_file,
'cookies' => $jar,
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
]
]);
$request = new \GuzzleHttp\Psr7\Request('POST', $url, [], $payload);
$rsp = $client->send($request);
dd($rsp->getBody()->read(1024));
$response->getBody()->read(1024) returns the error message

Add cookie to wordpress wp-json api call

I am developing an app for iPhone that makes use of a Wordpress site as a backend. I am also making changes to the site and have created basic endpoints for servicing the app using the Wordpress wp-json restful api. I have installed the JSON API, JSON API Auth, and JSON API User plugins and support user authentication. I manage to login a user and get a session token while doing so, a cookie. How do I make the subsequent calls authenticated, i.e. how do I add the cookie as a required parameter to an existing endpoint?
For instance, I have this code that retrieves the latest menu for the week:
function get_latest_menu ( $params ){
$post = get_posts( array(
'category' => 69,
'posts_per_page' => 1,
'offset' => 0
) );
if( empty( $post ) ){
return null;
}
return $post[0]->post_content;
}
// Register the rest route here.
add_action( 'rest_api_init', function () {
register_rest_route( 'weeks-menu/v1', 'latest-menu',array(
'methods' => 'GET',
'callback' => 'get_latest_menu'
) );
} );
Where and how should I add the cookie parameter in the call so that it would become authenticated? Please provide specific code if possible.
This might seem quite basic but I have no real php/Wordpress knowledge
nor the time to acquire it. Thank you.
Not sure how much help this will be after the fact but recently for school I ran into a similar issue while developing a mobile application using Ionic. The things I had to do were:
Enable Authentication headers in the HTAccess file for wordpress (it usually fails if you do not do this, the docs for the JWT explain exactly what to add and it worked for me).
I used post man to test it but the first thing you do is get the token for the username / password.
Every subsequent call you add an authorization flag in the header in the form Authorization: Bearer <token> where is your token you had for the user. I had a package with Ionic that can force the token from my storage which worked every time I made a call.
Additionally, you can add a new check to verify if the token is valid but there are a few plugins that force any rest end point to be authenticated which ends up sending an unauthorized flag which you can check in your code.
My recommendation if your still unclear download and use postman and use it to verify if everything is set up correctly. Once you get that sorted everything else starts making more sense.

Authenticate with Wordpress cookie through API from a subdomain

I want to access the current logged in Wordpress user in a separate Laravel installation.
Wordpress is running as website.com and I've got a subdomain with tool.website.com with the Laravel application (on another server but same domain).
I'm using the Native Wordpress API and created an authentication route.
The issue:
When I access the /authenticate route directly, the user ID is returned and works correctly. But when I access the route through tool.website.com false is returned..
Things I've got working:
I've created an API request which returns the user id in an API call:
add_action( 'rest_api_init', function () {
register_rest_route( '/authenticate', array(
'methods' => 'GET',
'callback' => 'authenticate',
) );
} );
The function looks like this:
$user_id = wp_validate_auth_cookie( $_COOKIE[LOGGED_IN_COOKIE], 'logged_in' );
The WP cookie is available on both the sub / main domain. I can see they are identical and toplevel.
define('COOKIE_DOMAIN', '.website.dev');
Things I've tried:
Using wp_get_current_user() to retrieve the user, this seems to need a nonce. I experimented hours and hours with the nonce approach on many different ways, but I could not get this to work (false or 0 was returned). I understand this is due to restrictions of using a nonce from outside of Wordpress.
Using the default native API approach to get the user, also needs the nonce.
Reading the https://developer.wordpress.org/rest-api/ manual, git repository & several articles / comments online.
Thinking about the OAuth approach, but I do not want users to login again as they are already logged in when they reach the tool.
Sending stuff like posts etc works without problems, so the API connection is not the problem.
I'm wondering if my approach is in the right direction. Hopefully someone can give me some guidance.
I found the following workaround:
- tool.website.com
Send the Cookies from tool.website.com to the API as post data.
$cookie_array = $_COOKIE;
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($cookie_array)
)
);
$context = stream_context_create($options);
$data = file_get_contents(self::BASE_URL . "authenticate", false, $context);
- website.com
Retrieve the cookie from Post data, and use the standard LOGGED_IN_COOKIE constant in Wordpress to select the correct one (this can be refactored to sending the correct cookie at once).
// We retrieve the cookie (which is sadly not available through the API call alone)
$the_cookie = $request->get_body_params();
// As the cookie lives at domain level, we can use the same Cookie key in the WP API and other subdomains of this domain
// The cookie key remains the same
$user_id = wp_validate_auth_cookie( $the_cookie[LOGGED_IN_COOKIE], 'logged_in' );
This solution seems steady; hopefully it will help someone. If there are other solutions, please add them in this topic; as I'm sure there must be different ways achieving this.

Categories