{"id":49934,"date":"2025-07-03T07:44:42","date_gmt":"2025-07-03T07:44:42","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=49934"},"modified":"2025-07-03T07:45:30","modified_gmt":"2025-07-03T07:45:30","slug":"artisan-tutorials-php-artisan-passport","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/artisan-tutorials-php-artisan-passport\/","title":{"rendered":"artisan Tutorials: php artisan passport"},"content":{"rendered":"\n<p>When you run <code>php artisan passport:install<\/code>, Laravel attempts to do the following:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generate encryption keys (<code>oauth-public.key<\/code> and <code>oauth-private.key<\/code>).<\/li>\n\n\n\n<li>Publish Passport\u2019s migrations if not already present.<\/li>\n\n\n\n<li>Run those migrations (if you choose \u201cyes\u201d).<\/li>\n\n\n\n<li>Create the default OAuth clients (Personal and Password).<\/li>\n<\/ol>\n\n\n\n<p>Running <code>php artisan passport:install<\/code> is a <strong>crucial setup step<\/strong> when using Laravel Passport for API authentication. Here&#8217;s a full explanation of <strong>why it&#8217;s needed<\/strong> and what it does:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u2705 Why Run <code>php artisan passport:install<\/code>?<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd27 1. <strong>Generates Encryption Keys<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Laravel Passport uses <strong>encryption<\/strong> to securely issue and validate access tokens.<\/li>\n\n\n\n<li><code>passport:install<\/code> generates:\n<ul class=\"wp-block-list\">\n<li>A <strong>private key<\/strong>: used to sign access tokens.<\/li>\n\n\n\n<li>A <strong>public key<\/strong>: used to verify the tokens on future requests.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>\ud83d\udcc1 These keys are stored in:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">storage\/oauth-<span class=\"hljs-keyword\">private<\/span>.key\nstorage\/oauth-<span class=\"hljs-keyword\">public<\/span>.key\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\ud83d\udd10 These keys are essential for the security of your API tokens.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udfab 2. <strong>Creates OAuth Clients<\/strong><\/h3>\n\n\n\n<p>It automatically creates two <strong>default OAuth2 clients<\/strong> in the <code>oauth_clients<\/code> table:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">a. <strong>Personal Access Client<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Used when issuing tokens via <code>$user->createToken('token-name')<\/code>.<\/li>\n\n\n\n<li>Good for first-party apps or backend-only workflows.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">b. <strong>Password Grant Client<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Used for <strong>username\/password login<\/strong> via the <code>\/oauth\/token<\/code> route.<\/li>\n\n\n\n<li>Commonly used in mobile apps and SPAs (single-page apps).<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>These clients have a unique <strong>Client ID and Client Secret<\/strong>, which are used to obtain tokens programmatically.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd0d What Happens Behind the Scenes?<\/h2>\n\n\n\n<p>When you run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">php<\/span> <span class=\"hljs-selector-tag\">artisan<\/span> <span class=\"hljs-selector-tag\">passport<\/span><span class=\"hljs-selector-pseudo\">:install<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Laravel does the following:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generates <code>oauth-public.key<\/code> and <code>oauth-private.key<\/code>.<\/li>\n\n\n\n<li>Creates one <strong>Personal Access Client<\/strong>.<\/li>\n\n\n\n<li>Creates one <strong>Password Grant Client<\/strong>.<\/li>\n\n\n\n<li>Stores all client data in the <code>oauth_clients<\/code> table.<\/li>\n\n\n\n<li>Outputs the client IDs and secrets in the console.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udccc When Should You Run It?<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 When setting up Laravel Passport for the first time.<\/li>\n\n\n\n<li>\ud83d\udd01 When you accidentally delete the keys or clients.<\/li>\n\n\n\n<li>\ud83d\udee0\ufe0f When migrating environments (you might need to re-run with <code>--force<\/code>).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u26a0\ufe0f Tip:<\/h2>\n\n\n\n<p>If you <strong>already have keys and clients<\/strong>, and re-running the command causes issues, use the <code>--force<\/code> flag <strong>only if you&#8217;re resetting the environment<\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">php<\/span> <span class=\"hljs-selector-tag\">artisan<\/span> <span class=\"hljs-selector-tag\">passport<\/span><span class=\"hljs-selector-pseudo\">:install<\/span> <span class=\"hljs-selector-tag\">--force<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u26a0\ufe0f Be careful: this will overwrite existing keys and may invalidate current tokens.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u2705 Summary<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Action<\/th><th>Purpose<\/th><\/tr><\/thead><tbody><tr><td>Generate OAuth keys<\/td><td>Sign and verify secure access tokens<\/td><\/tr><tr><td>Create Personal Access Client<\/td><td>Issue tokens using <code>createToken()<\/code> method<\/td><\/tr><tr><td>Create Password Grant Client<\/td><td>Enable login via <code>\/oauth\/token<\/code><\/td><\/tr><tr><td>Store keys and clients<\/td><td>In <code>storage\/<\/code> and <code>oauth_clients<\/code> table<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>Here\u2019s a clear explanation of the <strong>difference between a Personal Access Client and a Password Grant Client<\/strong> in Laravel Passport:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd11 1. <strong>Personal Access Client<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Purpose:<\/h4>\n\n\n\n<p>Used when <strong>users authenticate via a token directly<\/strong>, usually through <strong>first-party apps<\/strong> (like your own web or mobile app). Ideal for issuing <strong>long-lived personal tokens<\/strong>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccc How it works:<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The user logs in through a traditional session (browser or API).<\/li>\n\n\n\n<li>The server generates a <strong>personal access token<\/strong> for the user using the <code>createToken()<\/code> method: <code>$token = $user->createToken('Token Name')->accessToken;<\/code><\/li>\n\n\n\n<li>No client credentials (ID\/secret) are required on the frontend.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd10 Use Case:<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Admin panels<\/li>\n\n\n\n<li>First-party web or mobile apps<\/li>\n\n\n\n<li>API testing via Postman<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd04 Token Flow:<\/h4>\n\n\n\n<p>User logs in \u2192 backend creates personal token \u2192 returns to frontend.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd10 2. <strong>Password Grant Client<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">\u2705 Purpose:<\/h4>\n\n\n\n<p>Used when you want the <strong>user to provide email\/password<\/strong> via API and obtain an access token <strong>programmatically<\/strong>. Often used by <strong>mobile apps or single-page apps<\/strong> (SPA).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udccc How it works:<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The client app sends a request to the <code>\/oauth\/token<\/code> endpoint: <code>POST \/oauth\/token Content-Type: application\/json { \"grant_type\": \"password\", \"client_id\": \"8\", \"client_secret\": \"your-password-client-secret\", \"username\": \"user@example.com\", \"password\": \"secret\", \"scope\": \"*\" }<\/code><\/li>\n\n\n\n<li>If valid, Passport issues an access token.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd10 Use Case:<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Mobile apps logging in users<\/li>\n\n\n\n<li>SPAs with direct login forms<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udd04 Token Flow:<\/h4>\n\n\n\n<p>Frontend (mobile\/web) sends user credentials + client credentials \u2192 gets token from <code>\/oauth\/token<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 Summary Table<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Feature<\/th><th>Personal Access Client<\/th><th>Password Grant Client<\/th><\/tr><\/thead><tbody><tr><td>Authentication<\/td><td>Server-side only<\/td><td>User credentials via API<\/td><\/tr><tr><td>Use Case<\/td><td>First-party web\/mobile<\/td><td>Mobile apps \/ SPAs<\/td><\/tr><tr><td>Client ID\/Secret Needed?<\/td><td>\u274c No<\/td><td>\u2705 Yes<\/td><\/tr><tr><td>Example Method<\/td><td><code>$user-&gt;createToken()<\/code><\/td><td><code>\/oauth\/token<\/code> endpoint with credentials<\/td><\/tr><tr><td>User Interaction<\/td><td>Already logged in via session<\/td><td>Login via email\/password in the app<\/td><\/tr><tr><td>Security Consideration<\/td><td>Tokens created securely server-side<\/td><td>Password passed through API (use HTTPS)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When you run php artisan passport:install, Laravel attempts to do the following: Running php artisan passport:install is a crucial setup step when using Laravel Passport for API authentication. Here&#8217;s a&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-49934","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49934","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=49934"}],"version-history":[{"count":2,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49934\/revisions"}],"predecessor-version":[{"id":49936,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49934\/revisions\/49936"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=49934"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=49934"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=49934"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}