Here are my fresh notes on Laravel Passport. Even thought this is an already established project I took some time to document my trials getting it up and working with Laradock. Hopefully I get around to adding some text and make this easier to read.
The target here is to create an api authentication endpoint with laravel passport.
Here’s the shortlist of the steps
Create a new project
Since the last post the laravel
command is no longer working in the laradock client.
Which is no wonder since if you run commands in a docker container you shouldn’t expect them there after reboot :)
To fix this we:
- check that
laradock/workspace/Dockerfile
has the linecomposer global require "laravel/installer"
- to enable this then, just set the
laradock/.env
WORKSPACE_INSTALL_LARAVEL_INSTALLER=true
then dodc build workspace
and reboot - finally ssh back inside and check by doing
laravel new api-auth
Setup the new project in bitbucket
I am doing this from the host
cd /path/to/api-auth
git init
git remote add origin git@bitbucket.org:lpgfmk/api-auth.git
git add -A
git commit -m "- initial commit"
git push -u origin master
You may follow along with the api-auth project here.
Setup the project locally
Config .env
DB_HOST=mysql
DB_DATABASE=api_auth
DB_USERNAME=default
DB_PASSWORD=secret
Config DB
- Setup credentials
Start from the default sql config by doing
cp
laradock/mysql/docker-entrypointinitdb.d/createdb.sql.example
laradock/mysql/docker-entrypointinitdb.d/createdb-api_auth.sql
- Update
createdb-api_auth.sql
content withCREATE DATABASE IF NOT EXISTS `api_auth` COLLATE 'utf8_general_ci' ; CREATE USER 'api_auth'@'%' IDENTIFIED WITH mysql_native_password BY 'secret'; GRANT ALL ON `api_auth`.* TO 'api_auth'@'%' ;
- To run these changes do
winpty docker-compose exec mysql bash mysql -u root -proot < /docker-entrypoint-initdb.d/createdb-api_auth.sql
Config webserver
- Start from the default config by doing
cp laradock/nginx/sites/laravel.conf.example laradock/nginx/sites/api_auth.conf
-
Replace
laravel
withapi-auth
in the file -
Reboot nginx:
dc build nginx && dc down && fmk-lara-up
- Create local DNS
In your host’s windows config add 127.0.0.1 api-auth.local
- Test by opening
http://api-auth.local
in browser
Code work
Scaffolding done, getting ready to install the project proper.
Project setup
- ignore .idea and IntelliJ setup
- setup initial db structure by doing
php artisan migrate
composer require laravel/passport
php artisan migrate
- add the api trait to the
User.php
model - add routes
- update the
config/auth.php
file with the passport driver
Install vue
- run vendor publish
- run npm build
- errors
- npm run cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js –progress –hide-modules –config=node_modules/laravel-mix/setup/webpack.conf ig.js
- error npm ERR! missing script: cross-env
- do
npm install --global cross-env
- npm run dev: still missing
- npm install: ok
- npm run dev: ok
npm install axios
Create a Oauth client from cli
php artisan passport:client
Create a Oauth client as user
- scaffold auth
php artisan make:auth
- make the view
api-auth.blade.php
and add a route for it (api-auth
)
@extends('layouts.app')
@section('content')
<div id="app">
<passport-clients></passport-clients>
<passport-authorized-clients></passport-authorized-clients>
<passport-personal-access-tokens></passport-personal-access-tokens>
</div>
@endsection
- register a new user in the app
- go to
/api-auth
andCreate new client
(client id5
, client secretcHfCmLgWXttLNiV2TNVGeH9r7slrCA9DyiFr7EBg
)
Use a personal access token to authorize your calls
- do
php artisan passport:client --personal
- go to
/api-auth
andCreate new token
- use this token in postman to access the api
Authorize your application with oauth
Create a new application api-client. I won’t include the steps for this
since they’re the same as for api-auth
.
There are some extra things to check you include in this app
- guzzle
composer require "guzzlehttp/guzzle:~5.3"
- ext-json
"ext-json": "*"
Then update routes/web.php
with
Route::get('/redirect', function () {
$query = http_build_query([
'client_id' => '5',
'redirect_uri' => 'http://api-client.local/callback',
'response_type' => 'code',
'scope' => '',
]);
return redirect('http://api-auth.local/oauth/authorize?'.$query);
});
Route::get('/callback', function (Request $request) {
$http = new GuzzleHttp\Client;
$response = $http->post('http://api-auth.local/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => '5',
'client_secret' => 'cHfCmLgWXttLNiV2TNVGeH9r7slrCA9DyiFr7EBg',
'redirect_uri' => 'http://api-client.local/callback',
'code' => $request->code,
],
]);
return json_decode((string) $response->getBody(), true);
});
Now access the http://api-client.local
app in an incognito browser.
Notice you are redirected and you need to login with the credentials from http://api-auth.local
.
So try and authorize the thing.
… anticlimactic error No method can handle the form_params config key
- fix this by going to
composer.json
and setguzzlehttp/guzzle : ~6.0
- then do a
composer update
… anticlimactic error #2 cURL error 7: Failed to connect to api-auth.local port 80: Connection refused (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)
- find the fix here
- change
docker-compose.yml
inlaradock
at thephp-fpm:
section add
extra_hosts:
- "dockerhost:${DOCKER_HOST_IP}"
- "api_auth.local:${DOCKER_HOST_IP}"
- "api_client.local:${DOCKER_HOST_IP}"
- do
docker-compose build --no-cache php-fpm workspace
thendc down && fmk-lara-up
- still no go… actually because typo… (even though I also tested in the
workspace
section) - change
docker-compose.yml
inlaradock
at thephp-fpm:
section add
extra_hosts:
- "dockerhost:${DOCKER_HOST_IP}"
- "api-auth.local:${DOCKER_HOST_IP}"
- "api-client.local:${DOCKER_HOST_IP}"
- no more error but token expired so just redo the login, click authorize, get the response which is an array like: {“token_type”:”Bearer”,”expires_in”:31622400,”access_token”:””,”refresh_token”:””}
- now you may also view your authorized applications by reloading the view
Authorize internal application api calls
- First do
npm run dev
- Then add to the
ExampleComponent.vue
import axios from 'axios'
export default {
ready() {
console.log('Component mounted.')
axios.get("/api/user")
.then(response => {
console.log(response.data);
});
}
}
- notice you get
GET http://api-auth.local/api/user 401 (Unauthorized)
- open
Http\Kernel.php
and in theweb
middlewareGroups add\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class
- reload the page and notice the call going through by magic