J'utilise Laravel Passport pour l'authentification, j'ai donc mis mes routes en protection middleware.
Pour être clair, j'ajoute également UsersController.
public function getUser()
{
$users = Auth::user();
return response()->json($users);
}
//
Route::group(['prefix' => 'v1', 'middleware' => 'auth:api'], function () {
/* users */
Route::get('/users', 'Api\UsersController@getUser');
/* fetch */
Route::get('/articles', 'Api\ArticlesController@allArticles');
Route::get('/article/{id}', 'Api\ArticlesController@singleArticle');
});
Bien sûr, je dois me connecter ou je ne vois pas les itinéraires protégés. J'ai fait un AuthController
et à l'intérieur une fonction de connexion au contrôleur.
Contrôleur
public function login(Request $request)
{
$http = new \GuzzleHttp\Client;
try {
$response = $http->post(config('services.passport.login_endpoint'), [
'form_params' => [
'grant_type' => 'password',
'client_id' => config('services.passport.client_id'),
'client_secret' => config('services.passport.client_secret'),
'username' => $request->email,
'password' => $request->password,
]
]);
return $response->getBody();
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
if ($e->getCode() === 400) {
return response()->json('Invalid Request. Please enter a username or a password.', $e->getCode());
}
if ($e->getCode() === 401) {
return response()->json('Your credentials are incorrect. Please try again', $e->getCode());
}
return response()->json('Something went wrong on the server.', $e->getCode());
}
}
Dans le frontend dans ma vuex, j'ai un appel à l'action.
retrieveToken(context, credentials){
return new Promise((resolve, reject) => {
axios.post("api/v1/login", {
email: credentials.username,
password: credentials.password,
})
.then(response => {
const token = response.data.access_token;
localStorage.setItem("access_token", token);
context.commit("retrieveToken", token);
resolve(resolve);
})
.catch(error => {
console.log(error);
reject(response);
})
})
},
Tout va bien. Je stocke le jeton et l'utilise pour la connexion et le supprime pour la déconnexion. Mais au niveau du backend, il manque quelque chose. Parce que même si je me connecte, je ne vois toujours pas les itinéraires protégés. L'authentification de Laravel ne sait pas que l'utilisateur s'est connecté.
Où dois-je mettre le jeton dans l'en-tête? À l'intérieur du contrôleur ou de la méthode de connexion? Ou dois-je faire autre chose?
Si vous utilisez l'authentification par jeton avec laravel passeport, assurez-vous toujours de définir l'en-tête d'authentification (pour tout appel client) Authorization = Bearer your_token
pour les routes protégées, lors de l'appel du client. Je fais un exemple d'authentification simple avec Laravel Passport et Vue.js et je l'ai téléchargé sur github, veuillez le vérifier sur ce lien . Je vous recommande également de lire - ce post
Votre identifiant dans Laravel devrait ressembler à ceci
public function login (Request $request) {
$user = User::where('email', $request->email)->first();
if ($user) {
if (Hash::check($request->password, $user->password)) {
$token = $user->createToken('Laravel Password Grant Client')->accessToken;
$response = ['token' => $token];
return response($response, 200);
} else {
$response = "Password missmatch";
return response($response, 422);
}
} else {
$response = 'User does not exist';
return response($response, 422);
}
mes laravel routes, 'middleware' => ['json.response']
, J'utilise pour forcer json toutes les données
Route::group(['middleware' => ['json.response']], function () {
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
// public routes
Route::post('/login', 'Api\AuthController@login')->name('login.api');
Route::post('/register', 'Api\AuthController@register')->name('register.api');
// private routes
Route::middleware('auth:api')->group(function () {
Route::get('/logout', 'Api\AuthController@logout')->name('logout');
});
});
mon guards
dans config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
puis dans vue vous pouvez utiliser vuex pour stocker le token et les données utilisateur pour le réutiliser store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const debug = process.env.NODE_ENV !== 'production'
export default new Vuex.Store({
strict: debug,
state: {
auth: null,
token: null,
check:false
},
getters: {
auth: state => state.auth,
token: state => state.token,
},
mutations: {
SET_TOKEN(state, token) {
state.token = token
},
FETCH_auth_SUCCESS(state, auth) {
state.auth = auth
state.check = true
},
FETCH_auth_FAILURE(state) {
state.token = null
},
LOGOUT(state) {
state.auth = null
state.token = null
state.check = false
},
UPDATE_auth(state, { auth }) {
state.auth = auth
}
},
actions: {
saveToken({ commit, dispatch }, { token, remember }) {
commit('SET_TOKEN', token)
// if you need store token in cookie (remember me option)
// Cookies.set('token', token, { expires: remember ? 365 : null })
},
async fetchauth({ commit,state }) {
try {
axios.defaults.headers.common.Authorization = `Bearer ${state.token}`;
const { data } = await axios.get('/api/user')
commit('FETCH_auth_SUCCESS', data)
} catch (e) {
// Cookies.remove('token')
commit('FETCH_auth_FAILURE')
}
},
updateauth({ commit }, payload) {
commit('UPDATE_auth', payload)
},
async logout({ commit,state }) {
try {
axios.defaults.headers.common.Authorization = `Bearer ${state.token}`;
await axios.get('/api/logout')
} catch (e) {console.log(e) }
// Cookies.remove('token')
commit('LOGOUT')
},
}
});
Remarque J'ai défini le jeton axios.defaults.headers.common.Authorization = 'Bearer ${state.token}';
sur chaque appel axios (routes protégées), mais vous pouvez le faire globalement une fois.
Méthode de connexion en vue
methods: {
login() {
console.log("Login");
axios
.post("/api/login", {
email: this.form.email,
password: this.form.password
})
.then(res => {
// save token to vuex
this.$store.dispatch("saveToken", { token: res.data.token });
// get user data, store in vuex
this.$store.dispatch("fetchauth");
// redirect
this.$router.Push({path:'/dashboard'});
})
.catch(e => {
console.log(e);
});
}
}
Lorsque vous appelez les routes protégées par 'auth:api'
tout d'abord, vous devez définir le jeton dans l'en-tête pour accéder aux ressources. Dans axios est axios.defaults.headers.common.Authorization = 'Bearer ${state.token}';
.