{"id":67,"date":"2019-01-13T17:27:41","date_gmt":"2019-01-13T17:27:41","guid":{"rendered":"https:\/\/crosstechit.com\/blog\/?p=67"},"modified":"2019-01-14T19:11:06","modified_gmt":"2019-01-14T19:11:06","slug":"laravel-basic-authentication-with-passport-dingo-api-improvements","status":"publish","type":"post","link":"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/","title":{"rendered":"Laravel Basic Authentication with Passport &#038; Dingo API &#8211; Improvements"},"content":{"rendered":"\n<p>In the last post we have managed to login via Passport and return a response containing the access token. This way we need to store the access token on client side and send it attached to every request in order to access the protected routes. As you&#8217;ve may already heard, storing sensitive data on client side could be a security issue. There are ways to protect user&#8217;s data but we will go for a safer way (in my opinion) and store the access token inside a cookie. This cookie is passed on every request\/response between client and server and cannot be altered by client.<br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Where&#8217;s the start point?<\/h2>\n\n\n\n<p> We&#8217;ll try to implement what Laravel documentation describes here: <a href=\"https:\/\/laravel.com\/docs\/5.7\/passport#consuming-your-api-with-javascript\">https:\/\/laravel.com\/docs\/5.7\/passport#consuming-your-api-with-javascript<\/a><br>Due the fact that I felt it is not even close to want it promises I want to share this article with you to understand better what is happening under the hood, or just save you few hour of investigating what is wrong with that. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Security first<\/h2>\n\n\n\n<p>For some security improvements I highly recommend adding the following link into .env file: <code>SESSION_SECURE_COOKIE=true<\/code>. This will allow cookies to be set only over HTTPS connection. This will protect us from any man-in-the middle attack.<br>Set it <strong>ONLY<\/strong> in production, when you load your website over HTTPS.<\/p>\n\n\n\n<p>And in <code>config\/session.php<\/code> ensure that <code>same_site<\/code> is set to <code>\"strict\"<\/code> in order to disable cross origin requests.<\/p>\n\n\n\n<p>To protect against CSRF we will use Laravel&#8217;s csrf-token, but we&#8217;ll talk about this a bit later.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Generating cookies<\/h2>\n\n\n\n<p>Inside <code>app\\Http\\Kernel.php<\/code> insert following lines:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> 'api' =&gt; [<br>            \\App\\Http\\Middleware\\EncryptCookies::class,<br>             \\Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse::class,<br>            \\Illuminate\\Session\\Middleware\\StartSession::class,<br>            \\Laravel\\Passport\\Http\\Middleware\\CreateFreshApiToken::class,<br>            ...<br>        ], <\/pre>\n\n\n\n<p><strong>CreateFreshApiToken<\/strong>&nbsp;middleware will generate a JWT access token, create a cookie with it + CSRF token of current session + an expiration date and add it to the response.<br><strong>EncryptCookies<\/strong>&nbsp;will ensure that any incoming or outgoing cookies will be encrypted so the client cannot see the actual value of it.<br><strong>AddQueuedCookiesToResponse <\/strong>will attach the cookie to our response.<br><strong>StartSession<\/strong> will give us a session based on the cookie. This way we can access user&#8217;s data from it.<\/p>\n\n\n\n<p>Make sure all 4 classes are inserted above: <code>'throttle:60,1'<\/code> and <code>'bindings'<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Here comes the twist<\/h2>\n\n\n\n<p>If you take a look inside <strong>CreateFreshApiToken<\/strong> class, you will find the following method:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> <br>protected function requestShouldReceiveFreshToken($request)<br>{<br>        return $request-&gt;isMethod('GET') &amp;&amp; $request-&gt;user($this-&gt;guard);<br>} <\/pre>\n\n\n\n<p>Until now I haven&#8217;t find a good reason for checking if the request method is &#8220;GET&#8221; (<strong>Later edit<\/strong>: I&#8217;ve found one. Maybe will discuss it in a further post) We need to give the user a valid cookie as soon as he logs in. And for oblivious reasons the login and register methods should always be a &#8220;POST&#8221;.  So I created a <strong>CustomCreateApiToken<\/strong> class and override the method as follows:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">use Laravel\\Passport\\Http\\Middleware\\CreateFreshApiToken as Middleware;<br><br>class CustomCreateApiToken extends Middleware<br>{<br>   <br>    \/**<br>     * Determine if the request should receive a fresh token.<br>     *<br>     * @param  \\Illuminate\\Http\\Request  $request<br>     * @return bool<br>     *\/<br>    protected function requestShouldReceiveFreshToken($request)<br>    {<br>        return $request-&gt;user($this-&gt;guard);<br>    }<br>}<br><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Routes middleware<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\"> <br>$api-&gt;version('v1', function ($api) {<br>    $api-&gt;group(['middleware' =&gt; 'api'], function ($api) {<br>        $api-&gt;post(\"register\", 'App\\Http\\Controllers\\Api\\V1\\Auth\\RegisterController@register');<br>        $api-&gt;get(\"register\/{token}\", 'App\\Http\\Controllers\\Api\\V1\\Auth\\RegisterController@registerActivate');<br>        $api-&gt;post(\"login\", 'App\\Http\\Controllers\\Api\\V1\\Auth\\LoginController@login');<br>        ...<br>    });<br><br>    \/\/ Protected routes<br>    $api-&gt;group(['middleware' =&gt; 'auth:api'], function ($api) {<br>        $api-&gt;get('profile', 'App\\Http\\Controllers\\Api\\V1\\ProfileController@show');<br>        $api-&gt;get('logout', 'App\\Http\\Controllers\\Api\\V1\\Auth\\LoginController@logout');<br>    });<br>}); <\/pre>\n\n\n\n<p>As you can see above, we added the <strong>login <\/strong>and <strong>register <\/strong>routes in a group protected by <strong>api<\/strong> middleware in order to call <strong>CreateFreshApiToken<\/strong> after the user login.<br>Profile and logout routes are set under <code>auth:api<\/code> to be protected by Passport API authentication.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Some more tweaks<\/h2>\n\n\n\n<p>Cookie&#8217;s lifetime can be set in <code>config\\session.php<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> <br>'lifetime' =&gt; env('SESSION_LIFETIME', 120), \/\/ minutes<\/pre>\n\n\n\n<p>If the cookie expires, our client application should be noticed about that in a nice manner. At this moment Passport returns a JSON like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{\"message\":\"Unauthenticated.\",\"status_code\":500}<\/pre>\n\n\n\n<p>It&#8217;s not the best message you can receive. A 500 error code is usually returned for a server error but in our case there is an Authorization error which is usually reported as 401. So I created a Authenticate class, override the authenticate method and catch that 500 response and forwarded a 401 response code with a custom message:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">use Illuminate\\Auth\\Middleware\\Authenticate as Middleware;<br>use Exception;<br><br>class Authenticate extends Middleware<br>{<br><br>    \/**<br>     * Determine if the user is logged in to any of the given guards.<br>     *<br>     * @param  \\Illuminate\\Http\\Request  $request<br>     * @param  array  $guards<br>     * @return void<br>     *<br>     * @throws \\Illuminate\\Auth\\AuthenticationException<br>     *\/<br>    protected function authenticate($request, array $guards)<br>    {<br>        try {<br>            parent::authenticate($request, $guards);<br>        } catch (Exception $e) {<br>            abort(401, 'Unauthorized action.');<br>        }<br>    } <br>}<\/pre>\n\n\n\n<p>To be sure it is active you shall check the <code>app\\Http\\Kernel.php<\/code> file to have the right route to your class:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> <br>protected $routeMiddleware = [<br>        'auth' =&gt; \\App\\Http\\Middleware\\Authenticate::class,<br>         ...<br>    ]; <\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Final thoughts<\/h1>\n\n\n\n<p>You can craft your own cookie session handling. <br>If you are implementing this in a low risk app you can set a forever cookie. This way, the user will never be logged out. <br>If you are working on something big (eg. a bank software) you can set a low lifetime, let&#8217;s say 15 mins and after this user should login again.<br><\/p>\n\n\n\n<p>You can find the updated code here: <a href=\"https:\/\/github.com\/danielcrt\/laravel5.7-passport-dingo-api-boilerplate\">https:\/\/github.com\/danielcrt\/laravel5.7-passport-dingo-api-boilerplate<\/a><\/p>\n\n\n\n<p>\n\nIf you have any questions or improvements please let us know in comments section.\n\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the last post we have managed to login via Passport and return a response containing the access token. This way we need to store the access token on client side and send it attached to every request in order to access the protected routes. As you&#8217;ve may already heard, storing sensitive data on client [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[2],"tags":[],"class_list":["post-67","post","type-post","status-publish","format-standard","hentry","category-back-end-development"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Laravel Basic Authentication with Passport &amp; Dingo API - Improvements - Crosstech IT | Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Laravel Basic Authentication with Passport &amp; Dingo API - Improvements - Crosstech IT | Blog\" \/>\n<meta property=\"og:description\" content=\"In the last post we have managed to login via Passport and return a response containing the access token. This way we need to store the access token on client side and send it attached to every request in order to access the protected routes. As you&#8217;ve may already heard, storing sensitive data on client [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/\" \/>\n<meta property=\"og:site_name\" content=\"Crosstech IT | Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-01-13T17:27:41+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-01-14T19:11:06+00:00\" \/>\n<meta name=\"author\" content=\"Daniel Isac\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Daniel Isac\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/\"},\"author\":{\"name\":\"Daniel Isac\",\"@id\":\"https:\/\/crosstechit.com\/blog\/#\/schema\/person\/87da6aed97c0aeed77f83359af00d85e\"},\"headline\":\"Laravel Basic Authentication with Passport &#038; Dingo API &#8211; Improvements\",\"datePublished\":\"2019-01-13T17:27:41+00:00\",\"dateModified\":\"2019-01-14T19:11:06+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/\"},\"wordCount\":678,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/crosstechit.com\/blog\/#organization\"},\"articleSection\":[\"Back end development\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/\",\"url\":\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/\",\"name\":\"Laravel Basic Authentication with Passport & Dingo API - Improvements - Crosstech IT | Blog\",\"isPartOf\":{\"@id\":\"https:\/\/crosstechit.com\/blog\/#website\"},\"datePublished\":\"2019-01-13T17:27:41+00:00\",\"dateModified\":\"2019-01-14T19:11:06+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/crosstechit.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Laravel Basic Authentication with Passport &#038; Dingo API &#8211; Improvements\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/crosstechit.com\/blog\/#website\",\"url\":\"https:\/\/crosstechit.com\/blog\/\",\"name\":\"Crosstech IT | Blog\",\"description\":\"Apps. Smart. Fun.\",\"publisher\":{\"@id\":\"https:\/\/crosstechit.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/crosstechit.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/crosstechit.com\/blog\/#organization\",\"name\":\"Crosstech IT | Blog\",\"url\":\"https:\/\/crosstechit.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/crosstechit.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/crosstechit.com\/blog\/wp-content\/uploads\/2019\/01\/cropped-favicon.png\",\"contentUrl\":\"https:\/\/crosstechit.com\/blog\/wp-content\/uploads\/2019\/01\/cropped-favicon.png\",\"width\":190,\"height\":190,\"caption\":\"Crosstech IT | Blog\"},\"image\":{\"@id\":\"https:\/\/crosstechit.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/crosstechit.com\/blog\/#\/schema\/person\/87da6aed97c0aeed77f83359af00d85e\",\"name\":\"Daniel Isac\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/crosstechit.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/382d66c0eb0b506a1e6e5a10ae490d874d790f13b1af6a6f3958c1a7b3f23743?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/382d66c0eb0b506a1e6e5a10ae490d874d790f13b1af6a6f3958c1a7b3f23743?s=96&d=mm&r=g\",\"caption\":\"Daniel Isac\"},\"url\":\"https:\/\/crosstechit.com\/blog\/author\/danielcrt\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Laravel Basic Authentication with Passport & Dingo API - Improvements - Crosstech IT | Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/","og_locale":"en_US","og_type":"article","og_title":"Laravel Basic Authentication with Passport & Dingo API - Improvements - Crosstech IT | Blog","og_description":"In the last post we have managed to login via Passport and return a response containing the access token. This way we need to store the access token on client side and send it attached to every request in order to access the protected routes. As you&#8217;ve may already heard, storing sensitive data on client [&hellip;]","og_url":"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/","og_site_name":"Crosstech IT | Blog","article_published_time":"2019-01-13T17:27:41+00:00","article_modified_time":"2019-01-14T19:11:06+00:00","author":"Daniel Isac","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Daniel Isac","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/#article","isPartOf":{"@id":"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/"},"author":{"name":"Daniel Isac","@id":"https:\/\/crosstechit.com\/blog\/#\/schema\/person\/87da6aed97c0aeed77f83359af00d85e"},"headline":"Laravel Basic Authentication with Passport &#038; Dingo API &#8211; Improvements","datePublished":"2019-01-13T17:27:41+00:00","dateModified":"2019-01-14T19:11:06+00:00","mainEntityOfPage":{"@id":"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/"},"wordCount":678,"commentCount":0,"publisher":{"@id":"https:\/\/crosstechit.com\/blog\/#organization"},"articleSection":["Back end development"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/","url":"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/","name":"Laravel Basic Authentication with Passport & Dingo API - Improvements - Crosstech IT | Blog","isPartOf":{"@id":"https:\/\/crosstechit.com\/blog\/#website"},"datePublished":"2019-01-13T17:27:41+00:00","dateModified":"2019-01-14T19:11:06+00:00","breadcrumb":{"@id":"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/crosstechit.com\/blog\/2019\/01\/13\/laravel-basic-authentication-with-passport-dingo-api-improvements\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/crosstechit.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Laravel Basic Authentication with Passport &#038; Dingo API &#8211; Improvements"}]},{"@type":"WebSite","@id":"https:\/\/crosstechit.com\/blog\/#website","url":"https:\/\/crosstechit.com\/blog\/","name":"Crosstech IT | Blog","description":"Apps. Smart. Fun.","publisher":{"@id":"https:\/\/crosstechit.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/crosstechit.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/crosstechit.com\/blog\/#organization","name":"Crosstech IT | Blog","url":"https:\/\/crosstechit.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/crosstechit.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/crosstechit.com\/blog\/wp-content\/uploads\/2019\/01\/cropped-favicon.png","contentUrl":"https:\/\/crosstechit.com\/blog\/wp-content\/uploads\/2019\/01\/cropped-favicon.png","width":190,"height":190,"caption":"Crosstech IT | Blog"},"image":{"@id":"https:\/\/crosstechit.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/crosstechit.com\/blog\/#\/schema\/person\/87da6aed97c0aeed77f83359af00d85e","name":"Daniel Isac","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/crosstechit.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/382d66c0eb0b506a1e6e5a10ae490d874d790f13b1af6a6f3958c1a7b3f23743?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/382d66c0eb0b506a1e6e5a10ae490d874d790f13b1af6a6f3958c1a7b3f23743?s=96&d=mm&r=g","caption":"Daniel Isac"},"url":"https:\/\/crosstechit.com\/blog\/author\/danielcrt\/"}]}},"_links":{"self":[{"href":"https:\/\/crosstechit.com\/blog\/wp-json\/wp\/v2\/posts\/67","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/crosstechit.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/crosstechit.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/crosstechit.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/crosstechit.com\/blog\/wp-json\/wp\/v2\/comments?post=67"}],"version-history":[{"count":6,"href":"https:\/\/crosstechit.com\/blog\/wp-json\/wp\/v2\/posts\/67\/revisions"}],"predecessor-version":[{"id":77,"href":"https:\/\/crosstechit.com\/blog\/wp-json\/wp\/v2\/posts\/67\/revisions\/77"}],"wp:attachment":[{"href":"https:\/\/crosstechit.com\/blog\/wp-json\/wp\/v2\/media?parent=67"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/crosstechit.com\/blog\/wp-json\/wp\/v2\/categories?post=67"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/crosstechit.com\/blog\/wp-json\/wp\/v2\/tags?post=67"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}