I've an issue that cant understand,
I'm trying to send axios post requests using Vuejs to Laravel,
as is they describe :
install the axios package.
add the token to the header (by default is added in bootstrap).
my issue when i send the post request
the first is done but if i will send another one it gives me the
TokenMismatchException
please help me
the code in my vue file
login() {
this.userNotExiste = null;
var app = this
axios.post('/user/login', {email: this.email, password: this.password})
.then(function (response) {
if (response.data.userConnected) {
app.userConnected = response.data.userConnected;
setTimeout(function () {
window.location.href = window.location;
}, 1000);
}
})
.catch(function (error) {
if (error.response) {
if (!_.isEmpty(error.response.data))
if (!_.isEmpty(error.response.data.messages)) {
if (!_.isEmpty(error.response.data.messages.email)) app.loginErrors.email = error.response.data.messages.email[0]
if (!_.isEmpty(error.response.data.messages.password)) app.loginErrors.password = error.response.data.messages.password[0]
}
if (!_.isEmpty(error.response.data.userNotExiste)) app.userNotExiste = error.response.data.userNotExiste
} else if (error.request) {
console.log(error.request)
} else {
console.log('Contact : contact#33sprog.com')
}
})
}
in my laravel section
public function login(Request $request)
{
$validation = Validator::make($request->all(), [
'email' => 'required|email',
'password' => 'required',
], [
'email.email' => 'Entrer adresse email correct',
'email.required' => 'Veuillez saisir une adresse email',
'password.required' => 'Veillez saisir votre mot de passe',
]);
if ($validation->fails()) {
return response()->json([
'messages' => $validation->messages(),
], 400);
}
$user = Auth::attempt(['email' => $request->email, 'password' => $request->password]);
if (!$user) {
return response()->json([
'userNotExiste' => 'Adresse email ou mot de passe incorrecte',
], 400);
}
return response()->json(['userConnected' => 'Vous etes bien connecte'], 200);
}
at my php file
at my bootstrap.js
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
Thanks for helping
Related
I made a google login through socialite in laravel
public function redirectToProvider($provider)
{
$url = Socialite::driver($provider)->stateless()->redirect()->getTargetUrl();
return $url;
//return response()->json(['url' => $url], 200);
}
public function handleProviderCallback($provider)
{
$user = null;
if (Helper::validateProvider($provider) === false) {
return response()->json(['message' => 'The provider is not accepted temporally'], 422);
}
try {
$userProvider = Socialite::driver($provider)->stateless()->user();
} catch(\Exception $e) {
\Log::error($e->getMessage());
return response()->json(["message" => "An error occured while trying to login with {$provider}"], 422);
}
if (empty($userProvider)) {
return response()->json(["message" => "Invalid user provider"], 422);
}
if (empty($userProvider->id)) {
return response()->json(["message" => "Invalid provider id"], 422);
}
if (empty($userProvider->name)) {
return response()->json(["message" => "Invalid provider name"], 422);
}
if (empty($userProvider->email)) {
return response()->json(["message" => "Invalid provider email"], 422);
}
DB::transaction(function () use ($userProvider, $provider, &$user) {
$user = User::firstOrCreate([
'provider_id' => $userProvider->id,
'provider_name' => $provider,
], [
'email' => $userProvider->email,
'email_verified_at' => now(),
]);
});
if (! $user) {
return response()->json(["message" => "Cannot create an account"]);
}
$token = $user->createToken('token')->plainTextToken;
$response = [
'user' => $user,
'token' => $token,
'isAdmin' => $isAdmin
];
return response($response);
}
But now I do not know how I could proceed with these two api and take the data properly in my application de vue
I use vue3 and there I don't have much advantage of books already written
Is there a way I can get data from google?
For example, if I open the 2 apies in the browser, I can log in and my token will be returned
But in view, if I made a call to callback it would be a matter of course because I would send something to google
How can I proceed /
I'm using stateless fromUserToken
and this is the error I'm getting:
"errors": {
"error": "Client error: `GET https://www.googleapis.com/oauth2/v3/userinfo?prettyPrint=false` resulted in a `401 Unauthorized` response:\n{\n \"error\": \"invalid_request\",\n \"error_description\": \"Invalid Credentials\"\n}\n",
"code": 401
}
this is my endpoint that I use, it worked with all the sections I have in
public function authenticate (Request $request, $provider) {
//Validate provider
// Authenticate
$userSocial = null;
try {
if ($provider == 'twitter') {
$userSocial = Socialite::driver('twitter')->userFromTokenAndSecret($request->token, $request->token_secret);
} else {
$accessToken = $request->token;
$userSocial = Socialite::driver($provider)->stateless()->userFromToken($accessToken);
}
} catch (\Exception $e) {
return $this->respondError('Login error',[
'error' => $e->getMessage(),
'code' => $e->getCode()
],401);
}
$user = User::where([
'provider' => $provider,
'provider_id' => $userSocial->id
])->first();
if($user){
$token = $user->createToken('api')->plainTextToken;
return $this->respondWithToken($token, 'Logged in successfully', false);
} else {
$user = User::create([
'name' => $userSocial->getName() ?: 'Apple User',
'email' => $userSocial->getEmail(),
'image' => $userSocial->getAvatar(),
'provider_id' => $userSocial->getId(),
'provider' => $provider,
]);
$token = $user->createToken('api');
return $this->respondWithToken($token, 'Registered successfully', true);
}
}
Any Idea how to solve it?
and this is the code I used
The token that I was getting was jwt token, not access token. so It had problems with decoding it with stateless socialite function.
when requesting for authorization, you should set the response_type and scope url parameter like below:
scope = profile email
response_type = token
I want to get the errors from the server in the client, show them on the page when there's some troubles during login or registration, I think it's ok in the backend, but I don't know why they're not returning.
How to get that error messages from the validator in Vue?
I'm using: vuex, vue-router
My vuex file for login and register
actions: {
async login({ dispatch }, credentials) {
await axios.post('http://127.0.0.1:8000/api/login', credentials)
.then( res => {
if (res.data.success) {
// controllo se il token è buono
return dispatch('attempt', res.data.token)
}
})
.catch( err => {
console.log( err )
})
},
async attempt({ commit, state }, token) {
// blocco in caso ci fosse o meno il token
// se c'è il token
if (token) {
commit('SET_TOKEN', token)
}
// se non c'è
if(!state.token) {
return
}
// /blocco in caso ci fosse o meno il token
// provo a gettare l'user
try {
await axios.get('http://127.0.0.1:8000/api/user')
.then(res => {
commit('SET_USER', res.data)
})
} catch (e) {
commit('SET_TOKEN', null)
commit('SET_USER', null)
}
},
async register({ }, credentials) {
await axios.post('http://127.0.0.1:8000/api/register', credentials)
.then( () => {
})
.catch(err => {
console.log(err)
})
},
logoutAction({ commit }) {
return axios.post('http://127.0.0.1:8000/api/logout')
.then( () => {
commit('SET_TOKEN', null)
commit('SET_USER', null)
})
},
}
My controller
public function register(Request $request) {
$fields = $request->validate(
[
'name' => 'required|string',
'email' => 'required|string|unique:users,email',
'password' => 'required|string|confirmed'
]
);
$user = User::create([
'name' => ucwords($fields['name']),
'email' => $fields['email'],
'password' => bcrypt($fields['password']),
]);
$token = $user->createToken('token')->plainTextToken;
return response()->json(
[
'success' => true,
'user' => $user,
'token' => $token,
'message' => 'Registered successfully'
], 201);
}
public function login(Request $request) {
$fields = $request->all();
$validator = Validator::make($fields, [
'email' => 'required',
'password' => 'required'
]);
$user = User::where('email', $fields['email'])->first();
if($validator->fails()) {
return response()->json([
'message' => 'You must fill in all the fields!',
'errors' => $validator->errors()
], 401);
}
if(!$user || !Hash::check($fields['password'], $user->password)) {
return response()->json([
'message' => 'Invalid credentials.',
], 401);
}
$token = $user->createToken('token')->plainTextToken;
return response()->json(
[
'success' => true,
'user' => $user,
'token' => $token,
'message' => 'Logged in'
], 201);
}
public function logout(Request $request) {
auth()->user()->tokens()->delete();
return response()->json(
[
'message' => 'Logged out.'
]
);
}
Also I want to stop the user if the registration has empty fields, forcing him to stay in the register route, but with these settings down here the user will be redirected to the login page even if no registration fields are been typed in, as soon as I press enter or click 'register'.
p.s.: the 'home' route in which I'm pushing in the user is the page with the login form. So I want that the user will be redirect there only if the register form has been fulfilled.
submitRegistration() {
this.register(this.form)
.then(() => {
this.$router.push({name:'home'})
})
.catch((err) => {
// Ignore the vuex err regarding navigating to the page they are already on.
if (
err.name !== "NavigationDuplicated" &&
!err.message.includes(
"Avoided redundant navigation to current location"
)
) {
// But print any other errors to the console
console.log(err);
}
});
},
How can I use custom error messages in a json response? I'm using Ajax to validate a login form in frontend and I've already manage how to display the Validator errors, but I can't figure out how I can retrieve a custom error message.
This is the controller:
public function LoginValid(Request $request){
$validator = Validator::make($request->all(), [
'email' => ['required', 'string', 'email' ],
'password' => ['required', 'string', 'max:255'],
]);
if($validator->passes()){
$user = User::where('email', $request->email)->first();
if ($user &&
Hash::check($request->password, $user->password)) {
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
return redirect()->intended('dashboard');
}else{
return response()->json('should be any custom message here');
}
}
}else{
return response()->json(['error'=>$validator->errors()->all()]);
}
}
And here's the Ajax:
$(document).ready(function() {
$("#btn-login").click(function(e) {
e.preventDefault();
var _token = $("input[name='_token']").val();
var email = $("input[name='email']").val();
var password = $("input[name='password']").val();
$.ajax({
url: "{{ route('login-valid') }}",
type: 'POST',
data: { _token: _token, email: email, password:password },
success: function(data) {
if ($.isEmptyObject(data.error)) {
window.location.href = 'dashboard';
} else {
printErrorMsg(data.error);
}
}
});
});
function printErrorMsg(msg) {
$(".print-error-msg").find("ul").html('');
$(".print-error-msg").css('display', 'block');
$.each(msg, function(key, value) {
$(".print-error-msg").find("ul").append('<li>' + value + '</li>');
});
}
});
you can customize validation messages in this way. I am using your code for an example.
$validator = Validator::make($request->all(), [
'email' => ['required', 'string', 'email' ],
'password' => ['required', 'string', 'max:255'],
], [
'email.required' => 'email is required',
'email.string' => 'email should be valid',
'email.email' => 'email should be in proper format'
.
.
.
.
and so on
]);
above code will overwrite the laravel default messages.
I am creating JWT API authentication in Laravel with as stated in guide this link:
https://codeburst.io/api-authentication-in-laravel-vue-spa-using-jwt-auth-d8251b3632e0
Everything else is fine but I am having this issue on login:
error":"token_not_provided
Login seem to be going through successfully as I can see in the console or postman, but the token is never being retrieved. This is happening when the app tries to load the user data at api/auth/user end point.
GET http://127.0.0.1:8000/api/auth/user 400 (Bad Request)
this is my login method:
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if ( ! $token = JWTAuth::attempt($credentials)) {
return response([
'status' => 'error',
'error' => 'invalid.credentials',
'msg' => 'Invalid Credentials.'
], 400);
}
return response([
'status' => 'success'
]) ->header('Authorization', $token);
}
Then the user method
public function user(Request $request)
{
$user = User::find(Auth::User()->id);
return response([
'status' => 'success',
'data' => $user
]);
return $user;
}
Authentication Routes:
Route::post('auth/login', 'JWTAuthenticateController#login');
Route::group(['middleware' => 'jwt.auth'], function(){
Route::post('auth/logout', 'JWTAuthenticateController#APIlogout');
Route::get('auth/user', 'JWTAuthenticateController#user');
});
VueJS Login Component:
<script>
export default {
data(){
return {
email: null,
password: null,
error: false
}
},
methods: {
login(){
var app = this
this.$auth.login({
params: {
email: app.email,
password: app.password,
},
success: function () {
console.log('Success')
},
error: function () {
console.log('Something Went wrong!')
},
rememberMe: true,
redirect: {name:'inventories'},
fetchUser: true,
});
},
}
}
</script>
I cannot figure out how to fix this. Just don't tell why the authorization header not being returned:
return response([
'status' => 'success'
]) ->header('Authorization', $token);
Please Assist.