How to send cookie token using axios? - laravel

Here's my code for generating token that will response as a cookie.
public function authenticate(Request $request)
{
// grab credentials from the request
$credentials = ['email'=>$request->header('email'),'password'=>$request->header('password')];
try {
// attempt to verify the credentials and create a token for the user
if (! $token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'invalid_credentials'], 401);
}
} catch (JWTException $e) {
// something went wrong whilst attempting to encode the token
return response()->json(['error' => 'could_not_create_token'], 500);
}
return response($token)->cookie(
'token',$token, 60
);
}
And I'm using axios to process it. Here's my code:
axios({
method: 'post',
url: 'http://test.dev/authenticate',
headers : {
'email':'test#gmail.com',
'password':'secret'
},
json:true,
})
axios({
method: 'get',
url: 'http://test.dev/api/users',
json:true,
withCredentials: true
});
Now, I'm having a problem on how to send the token to retrieve users list. I've tried to add withCredentials: true but no luck.
I got a response error token_not_provided.
Questions:
How to get the value of the cookie token from response?
How to send the token using axios with Authorization Bearer {token}?
Thank you In Advance.

You need to add the token to your axios header:
headers: {
'Authorization' : 'Bearer ' + token
}
Make sure you store your token once you receive it back from your initial authorization.

It's necessary to set in your requests header:
withCredentials: true
Then it will allow your, then set the cookie in the 'Authorization' parameter as our friend said in the other answer:
headers: {
Authorization' : 'Bearer ' + CookieToken,
}

Related

Laravel Sanctum XHR request returns me a 401 - "Unauthenticated."

I am trying out Laravel Sanctum and unfortunately I have a problem and hope you can help me.
I have several blade pages that I call up via the web route. For example '/', 'about-us' and /dashboard. The dashboard is only visible to users who are logged in.
web.php
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth'])->name('dashboard');
In the dashboard, I have a tab where the logged-in user can view all other users. Here I send a get fetch call to the api route with Vanilla JS.
api.php
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
My JS in the blade file looks like this:
async function send(method, url = "/api/users") {
const rawResponse = await fetch(url, {
method: method,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
}, 2000);
const content = await rawResponse.json();
return content;
}
Problem: But I get a 401 here Object { message: "Unauthenticated." }. Why and what do I have to do to make it work?
My thinking so far.
As I understand it, Laravel sets a laravel_session and an XSRF-token cookie when it is called. If I fire the request against the webroute, laravel recognises me as the user. But if i fire the same request against the laravel api route i am not logged in for laravel. So I have to provide something in my request. I had tried to include the XSRF token in the request header. Like that:
const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
// ...
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-TOKEN': token
},
But that didn't work either.
Note: I have not configured anything else in Laravel to sanctum. I only ran the migration (personal_access_token). But the table is always empty.
My Kernel.php file:
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],

Infinite loop HTTP client Laravel

I'm recreating some requests that are now written in plain cURL to Laravel's HTTP client. But for some reason it gets in an infinite loop when I try to call a method based on the request response.
This is the call, I have the tokens stored, and when valid everything runs fine. When request returns 401 and want to call the function that creates new tokens and after that retry the original call.
Call:
public function call($path, $methold = null, $payload = null) {
if (empty($this->token)) {
$this->auth_new();
}
$response = Http::withOptions([
'debug' => false
])->withHeaders([
'X-Csrf-Token' => str_replace('csrf_token=', '', Crypt::decryptString($this->token->csrf_token)),
'Cookie' => $cookies,
"Accept" => "*/*",
])->get($url);
if ($response->status() == 401) {
$this->auth_new();
return $this->call_new($path);
} else {
return $response;
}
}
And the auth_new:
public function auth_new() {
$data = json_encode($payload);
$response = Http::withHeaders([
'Content-Type' => 'application/json; charset=UTF-8',
'Connection' => 'keep-alive'
])
->post($this->controller->controller_url . '/api/login', $payload);
$this->token = (response stuff goes here)
}
In cURL it all is working. So when I make a request and it returns a 401, I call the auth function, it stores the new token variables and I return the call.
When I remove the return $this->auth_new() from the call function, it generates new tokens and when I refire the call, I get a valid response. So token wise everything is working. It is just when it returns a 401 and when I want to retry te call automatically it fails with the HTTP client from laravel.

flutter error Authorization with jwt token

I use flutter for mobile developement application and laravel for api developement,In postman it works perfectly but I found error Authorization in Flutter.
error is return this message:
{ message : "Unauthenticated" }
code flutter:
_getToken() async {
SharedPreferences _prefs = await SharedPreferences.getInstance();
token = jsonDecode(_prefs.getString('token'));
}
_setHeaders() => {
'Content-type' : 'application/json',
'Accept' : 'application/json',
'Authorization' : 'Bearer $_getToken()'
};
and this is code middlware laravel:
public function handle($request, Closure $next, ...$guards)
{
if ($jwt = $request->cookie('jwt')) {
$request->headers->set('Authorization', 'Bearer ' . $jwt);
}
$this->authenticate($request, $guards);
return $next($request);
}
how to resolve this error and thanks.
You don't return the token value from the _getToken() function. Therefor here you don't add the token to the headers: 'Authorization' : 'Bearer $_getToken()'
Your _getToken() should return something. Here is the example.
String _getToken(){
return 'token';
}
If using back your function still can works. Use token instead of using _getToken() because your function doesn't return anything.
'Authorization' : 'Bearer $token'

React-Native fetch post to lumen/laravel returns MethodNotAllowed(405) but postman works

I know this questions have been asked before but non of the answers worked for me.
I am working with React Native and sending API's to Lumen-Backend and i realised that all POST request to LUMEN returns 405 error. Tested it with Postman and it works very fine.
Tried using fetch and axios but they all return 405 errors. Find codes Bellow
Postman request working image
FETCH CALL
const BASE_URL = 'http://192.168.43.232/2019/betbank_api/public/api/';
const url = '/app/auth/login/'
const endPoint = BASE_URL.concat(url);
const data ={ email: 'okeke', password:'passs' }
async function postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
headers: {
'Content-Type': 'application/text'
},
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
return await response.text(); // parses JSON response into native JavaScript objects
}
postData(endPoint, { email: 'okeke', password:'passs' })
.then((data) => {
console.log(data); // JSON data parsed by `response.json()` call
alert(data)
});
Also tried implementing the same thing using AXIOS
but ir returns same 405 error. Find Axios code bellow
axios.post(endPoint, data, {
headers: {
'Accept': 'application/json;charset=utf-8',
'Content-Type': 'application/json;charset=utf-8',
}
}).then( (response)=>{
console.log(JSON.stringify(response.data))
alert(JSON.stringify(response.data))
}
).catch( (error)=>{
console.log(error)
alert(error)
})
Find the Lumen Route - API bellow
$router->group(['prefix' => 'api'], function () use ($router) {
$router->post('/app/auth/login', 'AppUserController#postLogin');
});
FInd the method postLogin Bellow
class AppUserController extends Controller
{
protected $jwt;
public function __construct(JWTAuth $jwt)
{
$this->jwt = $jwt;
}
public function postLogin(Request $request)
{
$email = $request->input('email');
$this->validate($request, [
'email' => 'required|email|max:255',
'password' => 'required',
]);
try {
if (! $token = $this->jwt->attempt($request->only('email', 'password'))) {
return response()->json(['status'=>'error','data'=> 'Invalid username and passowrd'], 401);
}
} catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
return response()->json(['token_expired'], 500);
} catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
return response()->json(['token_invalid'], 500);
} catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
return response()->json(['token_absent' => $e->getMessage()], 500);
}
return response()->json(compact('token'));
}
}
Everythings seems in order but somehow, neither fetch or axios would work when i use the POST method.
But if i change it to GET method, the error stops but the issue would now be how to get the data's been posted from the APP.
QUESTION
Why would all Post request from my App (React Native) be returning 405 from Lumen/Laravel

Protect laravel api service with Okta and JWT

Trying to put together a solution to protecting a Laravel 5.4 api using OKTA and JWT. I have an SPA that logs into my application via OKTA and retrieves an access_token and id_token. It also passes this to API calls in the header using 'Authorization': Bearer ${accessToken} but now i am struggling to find a solution to verify this access token with OKTA within the Laravel backend. been looking at tymon/jwt-auth but cant workout how to add a custom solution to verifiy the token but i would assume it can be done using okta/jwt-verifier does anyone have any samples/guide? also looked at laravel/socialite and socialiteproviders/okta but that seems more about a traditional backend login rather than an SPA
Our okta/jwt-verifier library should be able to help you out here. You will have to create a custom middleware solution to capture and authorize the request based on the bearer token. Once you have that middleware set up, inside of the verifier library, you can run the following to verify the accessToken.
$jwtVerifier = (new \Okta\JwtVerifier\JwtVerifierBuilder())
->setAudience('api://default')
->setClientId('{clientId}')
->setIssuer('https://{yourOktaDomain}.com/oauth2/default')
->build();
$jwt = $jwtVerifier->verify($jwt);
By changing the client id and your okta domain above, you should be able to pass in the accessToken to the verify method. If you do not get any exceptions, you can assume that the jwt is valid and approve the request.
See the github repo readme for information about what you have access to once you verify the validity of the JWT
For those finding this post. In the SPA make sure you also define the issuer, this should be a useful start...
//react login
this.oktaAuth = new OktaAuth({
url: props.config.oktaUrl
,clientId:props.config.clientId
,redirectUri:props.config.redirectUri
,issuer: props.config.issuer
});
this.oktaAuth.signIn({
username: this.state.username,
password: this.state.password
})
.then((response) => {
if (response.status === 'SUCCESS') {
this.setState({
sessionToken: response.sessionToken
});
this.oktaAuth.token.getWithoutPrompt({
responseType: ['id_token', 'token']
,scopes: ['openid', 'email', 'profile']
,sessionToken: response.sessionToken
})
.then((tokenOrTokens) => {
this.setState({
tokenOrTokens: tokenOrTokens
});
window.localStorage.setItem('access_token', tokenOrTokens[1].accessToken);
})
.catch(function(err) {
console.log('err', err);
});
}
})
//api call
const accessToken = window.localStorage.getItem('access_token') || null;
const config = {
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Bearer ${accessToken}`
},
};
fetch(url, config)
.then((response) => {
...
//laravel api route
Route::group(['prefix' => 'restricted', 'middleware' => ['okta.validate']], function() {
Route::get('/getprotecteddata', 'MyController#getProtectedData');
});
//laravel kernel.php
protected $routeMiddleware = [
...
'okta.validate' => \App\Http\Middleware\ValidateOKTAToken::class,
];
//laravel middleware
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class ValidateOKTAToken
{
public function handle($request, Closure $next)
{
$token = $this->parseAuthHeader($request);
$jwt = $this->validate($token);
\Log::info("ValidateOKTAToken jwt=" . json_encode($jwt->toJson()));
return $next($request);
}
protected function validate($token) {
$oktaClientId = env('OKTA_CLIENTID');
$oktaIssuer = env('OKTA_ISSUER');
$oktaAudience = env('OKTA_AUDIENCE');
$jwtVerifier = (new \Okta\JwtVerifier\JwtVerifierBuilder())
->setAudience($oktaAudience)
->setClientId($oktaClientId)
->setIssuer($oktaIssuer)
->build();
$jwt = $jwtVerifier->verify($token);
return $jwt;
}
protected function parseAuthHeader(Request $request, $header = 'authorization', $method = 'bearer')
{
$header = $request->headers->get($header);
if (! starts_with(strtolower($header), $method)) {
return false;
}
return trim(str_ireplace($method, '', $header));
}
}

Resources