I've been hitting wall for a while now with this, simply I can't get it where is the problem. So I've got backend Laravel and front Vue; logging in is alright, I get token but when I get into one of the routes with auth:api I get "message":"Unauthenticated.". I save token on the front, so should I send it with any request to backend or there is other way around it?
LoginController.php
public function login(Request $request)
{
$login = $request->validate([
'email' => 'required',
'password' => 'required',
]);
if(Auth::attempt($login))
{
return response(['message' => 'Invalid login']);
}
$user = User::where('email', $request->email)->first();
$accessToken = $user->createToken('Laravel Password Grant Client')->accessToken;
return response()->json(['user' => $user, 'access_token' => $accessToken]);
}
api.php
Route::namespace('\\')->middleware('auth:api')->group(function(){
Route::resource('budget', BudgetController::class);
});
user.js
const state = {
token: localStorage.getItem('access_token') || null,
isAuthenticated: localStorage.getItem('access_token') !== null
}
const getters = {
isAuthenticated: state => state.isAuthenticated
}
const actions = {
async retrieveToken({commit}, payload){
console.log(payload)
const response = axios.post(url + '/login', payload)
.then(response => {
const token = response.data.access_token
localStorage.setItem('access_token', token)
commit('setToken', token)
})
}
}
const mutations = {
setToken: (token) => state.token = token
}
Alright, so simply in my second module I used token as a header like this:
const state = {
budget: [],
header: {
headers: {
Authorization: `Bearer ${localStorage.getItem("access_token") || null}`,
withCredentials: true,
"Access-Control-Allow-Origin": "*"
},
}
};
const getters = {
allBudget: (state) => state.budget,
};
const actions = {
async fetchBudget({ commit, state }) {
const response = await axios.get(url, state.header);
console.log(state.header);
commit("setBudget", response.data);
},
};
After that I was getting CORS error so i needed to add two directives at the end of the file xampp\apache\conf\httpd.conf
Header Set Access-Control-Allow-Origin *
Header Set Access-Control-Allow-Headers *
Related
I keep getting 404 error when I try to submit the form even though the routes are correctly placed in api.php.Can somebody please help??
const url = "/api/add-feedback";
const token = process.env.MIX_REACT_APP_API_TOKEN;
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [review, setReview] = useState("");
const handleSubmit = async (e) => {
e.preventDefault();
const data = {
name: name,
email: email,
review: review
}
const res = await axios.post(url, data, {
headers: {
Authorization: "Bearer " + token,
},
});
if (res.data.status === 200) {
console.log(res.data.message);
}
}
Here is the route in api.php
Route::post('/add-feedback',[ApiController::class,'feedback']);
Here is the ApiController function
public function feedback(Request $res)
{
$data = $res->validate([
'name'=>'required',
'email'=>'required|email',
'review'=>'required'
]);
Feedback::create($data);
return response()->json([
'status' => 200,
'message' => 'Feedback Added Successfully'
]);
}
This is the error I get:
app.js:3415 POST http://127.0.0.1:8000/api/add-feedback 404 (Not Found)
app.js:3880 Uncaught (in promise) Error: Request failed with status code 404
The error is you're using promises with axios, modify your code to something like this:
axios.post(url, data,{
headers: {
Authorization: "Bearer " + token,
},
})
.then((response) => {
if (res.data.status === 200) {
console.log(res.data.message);
}
}, (error) => {
console.log(error);
});
This will send a post request to your route with the data specified.
I'm having issues with my application, I used php-jwt JSON Web Token Authentication in my angular 9 apps and the token works fine when I'm not redirecting to successful page after login. when redirecting to the dashboard after login the token is set and immediately remove from localStorage. How can I allow token even after redirection to new page? Any help will be highly appreciated.
My auth.service.ts file
// Sign-in
signIn(user: Usermodule) {
return this.http
.post<any>(`${this.endpoint}/signin.php`, user)
.subscribe((res: any) => {
localStorage.setItem('ACCESS_TOKEN', res.jwt);
this.getUserProfile(res.id).subscribe((res) => {
this.router.navigate(['app/dashboard']);
});
});
}
// User profile
getUserProfile(id): Observable<any> {
let api = `${this.endpoint}/user_profile.php`;
return this.http.get(api, { headers: this.headers }).pipe(
map((res: Response) => {
return res || {};
}),
catchError(this.handleError)
);
}
auth.interceptors.ts file
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) {}
intercept(request: HttpRequest<any>, next: HttpHandler) {
const access_Token = this.authService.getToken();
request = request.clone({
setHeaders: {
Authorization: 'Bearer ' + access_Token,
},
});
return next.handle(request);
}
}
app.module.ts file
JwtModule.forRoot({
config: {
tokenGetter: () => {
return localStorage.getItem('ACCESS_TOKEN');
}
// whitelistedDomains: ['localhost'],
// blacklistedRoutes: ['localhost/auth/login']
}
})
],
providers: [
AuthService,
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi:true}
],
bootstrap: [AppComponent]
Once I comment out //this.router.navigate(['app/dashboard']); the token stays in localstorage without been killed and I can even access restricted area when I type the address manually.
I made a chat page where the logged in user should be able to see only his own messages thru single targets. However, every user can see every other user's supposedly self-intended (looped) messages. Every logged in user send his own JWT with :
$this->denyAccessUnlessGranted('ROLE_USER');
$user = $this->getUser();
$userid = $user->getId();
$pass = $user->getPassword();
$token = (new Builder())
// set other appropriate JWT claims, such as an expiration date
->set('mercure', ['subscribe' => ["http://localhost:8000/user/".$userid],'publish' => ["http://localhost:8000/user/".$userid]]) // could also include the security roles, or anything else
->sign(new Sha256(), 'K3y')
->getToken();
return $this->render('chat/index.html.twig', [
'config' => [
'topic' => 'chat',
'publishRoute' => $this->generateUrl('publisher', ['topic' => 'chat'])
], 'token' => $token
]);
The JS on the user chat's page is as so:
<script src="js/eventsource.min.js"></script>
<script>
const {topic, publishRoute} = JSON.parse(document.getElementById('config').textContent);
const subscribeURL = new URL('http://localhost:3000/.well-known/mercure');
subscribeURL.searchParams.append('topic', topic);
const es = new EventSourcePolyfill(subscribeURL, {
headers: {
'Authorization': 'Bearer ' + '{{ token }}',
}
});
let ul = null;
es.onmessage = ({data}) => {
const {username, message} = JSON.parse(data)
if (!username || !message)
throw new Error('Invalid payload')
if (!ul) {
ul = document.createElement('ul');
const messages = document.getElementById('messages');
messages.innerHTML = '';
messages.append(ul);
}
const li = document.createElement('li')
li.append(document.createTextNode(`<${username}> ${message}`))
ul.append(li)
};
document.querySelector('form').onsubmit = function (e) {
e.preventDefault();
fetch(publishRoute, {method: 'POST', body: JSON.stringify({username: this.elements.username.value, message: this.elements.message.value})});
this.elements.message.value = '';
this.elements.message.focus();
}
</script>
The chat page's URL is http://localhost:8000/chat once logged it.
And my Mercure hub's params are as so :
$env:JWT_KEY='K3y'; $env:ADDR='localhost:3000'; $env:ALLOW_ANONYMOUS='0'; $env:CORS_ALLOWED_ORIGINS='http://localhost:8000'; $env:PUBLISH_ALLOWED_ORIGINS='http://localhost:3000'; .\mercure.exe
Please help! I used the JWT's per user, but the security to isolate the updates doesn't work:/
Trying to integrate APIs built in Laravel 5.4 with ionic 2 and struggling handle the error
What I want to do:
Authenticate the login using Laravel Password service ( OAuth2 ).
Once authenticated, it would return the access token.
Access Token is passed in the header in a GET API call to receive the
user details.
I am able to #1 and #2 but got stuck at #3.
Here is my code of login.ts
public login() {
this.showLoading();
this.auth.login(this.loginCredentials).subscribe(allowed => {
if (allowed) {
setTimeout(() => {
this.loading.dismiss();
this.nav.setRoot(HelloIonicPage)
});
} else {
this.showError("Access Denied");
}
},
error => {
this.showError(error);
});
}
auth is a service provider, that has login method.
//Function to get access token
public login(credentials) {
if (credentials.email === null || credentials.password === null) {
return Observable.throw("Please insert credentials");
} else {
return Observable.create(observer => {
var link = 'http://localhost/XXX/public/oauth/token';
var vars = {
password: "XXX",
username: "XXXXXX",
grant_type: 'password',
client_id: "XXXXX",
client_secret: 'XXXXXX',
scope: ''
}
this.http.post(link, vars)
.map(res => res.json())
.subscribe(
data => { let user = this.getUserFromAccessToken(data);
console.log(user);
observer.next(user);
},
err => { observer.error(err.json()); }
() => {
console.log('Completed..');
}
);
});
}
}
//Function to get user from the accessToken
private getUserFromAccessToken(oAuthData) {
let headers = new Headers({ 'Content-Type': 'application/json','Accept': 'application/json','Authorization': 'Bearer ' + oAuthData.access_token });
let options = new RequestOptions({ headers: headers });
let link = 'http://localhost/XXXX/public/api/v1/user';
return this.http.get(link, options)
.map(res => res.json())
.subscribe(
data => this.currentUser = data.user,
err => this.error = err
);
}
currentUser and error are defined as properties of the AuthService class.
How should I ensure that an error is thrown either in case the access token is not returned or user is not returned from the access token.
I am making an app in ionic and the backend is made in Laravel. I am working on a password reset functionality, and I keep getting the above mentioned error, when I am testing endpoints in chrome. This is the code for the contact information function:
sendContactConfirmation: function(contact, reset) {
var defer = $q.defer();
if(reset == 'reset'){
var endpointUrl = $http.post(AppSettings.apiUrl + "/users/reset", { phone: contact });
}
else {
var endpointUrl = $http.post(AppSettings.apiUrl + "/users", { phone: contact });
}
endpointUrl.then(function(result) {
service.set(result.data.user);
defer.resolve(result);
}, function(error) {
defer.reject(error);
});
return defer.promise;
},
And these are the routes in my Laravel back-end:
Route::group(['jwt.auth', ['except' => ['authenticate']], 'prefix' => 'api', 'namespace' => 'Api'], function() {
Route::post('authenticate', 'AuthenticateController#authenticate');
Route::get('authenticate/user', 'AuthenticateController#getAuthenticatedUser');
Route::post('users', 'UsersController#register');
Route::post('users/reset', 'UsersController#resetContact');
Route::put('users/{user}/reset', 'UsersController#resetPassword');
Route::put('users/{user}', 'UsersController#update');
Route::put('users/{user}/activate', 'UsersController#activate');
Route::post('users/{user}/pic', 'UsersController#uploadPicture');
});
And this is the resetContact function:
public function resetContact(Request $request)
{
$this->validate(
$request,
['phone' => 'required|regex:/^[0-9]{8}$/']
);
$user = User::where('phone', $request->get('phone'))->firstOrFail();
if ($user) {
try {
$this->sendValidationCode($user, 'reset');
}
catch (\Exception $e) {
throw new ApiException($e->getMessage(), 500);
}
}
return response()->json([
'user' => $user,
]);
}
Not sure why do I get this 400 Bad request error for this.
When using Laravel JWT make sure you always send the token for all routes under jwt.auth otherwise you will get the error 400 = Token not provided. In ionic make sure your toke is provided on each call to your laravel endpoint to avoid this error.