Authenticating Firebase and Angular with Auth0: Part 2

This article was originally published on the Auth0.com blog, and is republished here with permission.

In this two-part tutorial series, we’ll learn how to build an application that secures a Node back end and an Angular front end with Auth0 authentication. Our server and app will also authenticate a Firebase Cloud Firestore database with custom tokens so that users can leave realtime comments in a secure manner after logging in with Auth0. The Angular application code can be found at the angular-firebase GitHub repo and the Node API can be found in the firebase-auth0-nodeserver repo.

The first part of our tutorial, Authenticating Firebase and Angular with Auth0: Part 1, covered:

  • intro and setup for Auth0 and Firebase
  • implementing a secure Node API that mints custom Firebase tokens and provides data for our app
  • Angular application architecture with modules and lazy loading
  • Angular authentication with Auth0 with service and route guard
  • shared Angular components and API service.

Authenticating Firebase and Angular with Auth0: Part 2

Part 2 of our tutorial will cover:

  1. Displaying Dogs: Async and NgIfElse
  2. Dog Details with Route Parameters
  3. Comment Model Class
  4. Firebase Cloud Firestore and Rules
  5. Comments Component
  6. Comment Form Component
  7. Realtime Comments
  8. Conclusion

Our completed app will look something like this:

Let’s pick up right where we left off at the end of Authenticating Firebase and Angular with Auth0: Part 1.

Displaying Dogs: Async and NgIfElse

Let’s implement the home page of our app — the dogs listing. We created the scaffolding for this component when we set up our Angular app’s architecture.

Important Note: Make sure your Node.js API is running. If you need a refresher on the API, refer to How to Authenticate Firebase and Angular with Auth0: Part 1 – Node API.

Dogs Component Class

Open the dogs.component.ts class file now and implement this code:

// src/app/dogs/dogs/dogs.component.ts
import { Component, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { ApiService } from '../../core/api.service';
import { Dog } from './../../core/dog';
import { Observable } from 'rxjs/Observable';
import { tap, catchError } from 'rxjs/operators';

@Component({
  selector: 'app-dogs',
  templateUrl: './dogs.component.html'
})
export class DogsComponent implements OnInit {
  pageTitle = 'Popular Dogs';
  dogsList$: Observable;
  loading = true;
  error: boolean;

  constructor(
    private title: Title,
    private api: ApiService
  ) {
    this.dogsList$ = api.getDogs$().pipe(
      tap(val => this._onNext(val)),
      catchError((err, caught) => this._onError(err, caught))
    );
  }

  ngOnInit() {
    this.title.setTitle(this.pageTitle);
  }

  private _onNext(val: Dog[]) {
    this.loading = false;
  }

  private _onError(err, caught): Observable {
    this.loading = false;
    this.error = true;
    return Observable.throw('An error occurred fetching dogs data.');
  }

}

After our imports, we’ll set up some local properties:

  • pageTitle: to set our page’s

    and </code></li> <li><code>dogsList$</code>: the observable returned by our API HTTP request to fetch the dogs listing data</li> <li><code>loading</code>: to show a loading icon while the API request is being made</li> <li><code>error</code>: to display an error if something goes wrong fetching data from the API.</li> </ul> <p>We’re going to be using the declarative <a href="https://angular.io/api/common/AsyncPipe">async pipe</a> to respond to the <code>dogsList$</code> observable returned by our API <code>GET</code> request. With the async pipe, we don’t need to subscribe or unsubscribe in our <code>DogsComponent</code> class: the subscription process will be managed automatically! We just need to set up our observable.</p> <p>We’ll make <code>Title</code> and <code>ApiService</code> available to our class by passing them to the constructor, and then set up our <code>dogsList$</code> observable. We’ll use RxJS operators <code>tap</code> (previously known as the <code>do</code> operator) and <code>catchError</code> to call handler functions. The <code>tap</code> operator executes side effects but does not affect the emitted data, so it’s ideal for setting other properties. The <code>_onNext()</code> function will set <code>loading</code> to <code>false</code> (since data has been successfully emitted). The <code>_onError()</code> function will set <code>loading</code> and <code>error</code> appropriately and throw an error. As mentioned before, we don’t need to <em>subscribe</em> or <em>unsubscribe</em> from the <code>dogsList$</code> observable because the async pipe (which we’ll add in the template) will handle that for us.</p> <p>On initialization of our component, we’ll use <a href="https://angular.io/guide/lifecycle-hooks#oninit"><code>ngOnInit()</code> to spy on the OnInit lifecycle hook</a> to <a href="https://angular.io/guide/set-document-title">set the document <code><title></code></a>.</p> <p>That’s it for our Dogs component class!</p> <h3 id="dogscomponenttemplate">Dogs Component Template</h3> <p>Let’s move on to the template at <code>dogs.component.html</code>:</p> <pre><code class="markup language-markup"><!-- src/app/dogs/dogs/dogs.component.html --> <h1 class="text-center">{{ pageTitle }}</h1> <ng-template #noDogs> <app-loading *ngIf="loading"></app-loading> <app-error *ngIf="error"></app-error> </ng-template> <div *ngIf="dogsList$ | async as dogsList; else noDogs"> <p class="lead"> These were the top <a href="http://www.akc.org/content/news/articles/the-labrador-retriever-wins-top-breed-for-the-26th-year-in-a-row/">10 most popular dog breeds in the United States in 2016</a>, ranked by the American Kennel Club (AKC). </p> <div class="row mb-3"> <div *ngFor="let dog of dogsList" class="col-xs-12 col-sm-6 col-md-4"> <div class="card my-2"> <img class="card-img-top" [src]="dog.image" [alt]="dog.breed"> <div class="card-body"> <h5 class="card-title">#{{ dog.rank }}: {{ dog.breed }}</h5> <p class="text-right mb-0"> <a class="btn btn-primary" [routerLink]="['/dog', dog.rank]">Learn more</a> </p> </div> </div> </div> </div> </div> <app-comments></app-comments> </code></pre> <p>There are a couple things in this template that we’ll take a closer look at:</p> <pre><code class="markup language-markup">... <ng-template #noDogs> <app-loading *ngIf="loading"></app-loading> <app-error *ngIf="error"></app-error> </ng-template> <div *ngIf="dogsList$ | async as dogsList; else noDogs"> ... <div *ngFor="let dog of dogsList" ...> ... </code></pre> <p>This code does some very useful things declaratively. Let’s explore.</p> <p>First we have an <a href="https://angular.io/guide/structural-directives#the-ng-template"><code><ng-template></code> element</a> with a <a href="https://angular.io/guide/template-syntax#template-reference-variables--var-">template reference variable</a> (<code>#noDogs</code>). The <code><ng-template></code> element is never rendered directly. It’s intended to be used with structural directives (such as NgIf). In this case, we’ve created an embedded view with <code><ng-template #noDogs></code> which contains both the loading and error components. Each of these components will render based on a condition. The <code>noDogs</code> embedded view itself will not render unless instructed to.</p> <p>So how (and when) do we tell this view to render?</p> <p>The next <code></p> <div *ngIf="...</code> is actually an <a href="https://angular.io/api/common/NgIf">NgIfElse</a> using the <a href="https://angular.io/guide/structural-directives#the-asterisk--prefix">asterisk prefix as syntactic sugar</a>. We’re also using the async pipe with our <code>dogsList$</code> observable and setting a variable so we can reference the stream’s emitted values in our template (<code>as dogsList</code>). If something goes wrong with the <code>dogsList$</code> observable, we have an <code>else noDogs</code> statement that tells the template to render the <code><ng-template #noDogs></code> view. This would be true before the data has been successfully fetched from the API, or if an error was thrown by the observable.</p> <p>If <code>dogsList$ | async</code> has successfully emitted a value, the div will render and we can iterate over our <code>dogsList</code> value (which is expected to be an array of <code>Dog</code>s, as specified in our component class) using the <a href="https://angular.io/api/common/NgForOf">NgForOf (<code>*ngFor</code>) structural directive</a> to display each dog’s information.</p> <p>As you can see in the remaining HTML, each dog will be displayed with a picture, rank, breed, and a link to their individual detail page, which we’ll create next.</p> <p>View the Dogs component in the browser by navigating to your app’s homepage at <a href="http://localhost:4200/">http://localhost:4200</a>. The Angular app should make a request to the API to fetch the list of dogs and display them!</p> <p><em>Note: We’ve also included the <code><app-comments></code> component. Since we’ve generated this component but haven’t implemented its functionality yet, it should show up in the UI as text that says “Comments works!”</em></p> <p>To test error handling, you can stop the API server (<code>Ctrl+c</code> in the server’s command prompt or terminal). Then try reloading the page. The error component should display since the API cannot be reached, and we should see the appropriate errors in the browser console:</p> <p><img src="https://i0.wp.com/dab1nmslvvntp.cloudfront.net/wp-content/uploads/2018/03/1522282286dogs-error-1024x380.jpg?resize=1024%2C380&ssl=1" alt="Angular app with Node.js API showing data error" data-recalc-dims="1"></p> <p><em>Continue reading %<a rel="nofollow" href="https://www.sitepoint.com/authenticating-firebase-angular-auth0-2/">Authenticating Firebase and Angular with Auth0: Part 2</a>%</em></p> </div> <p class="wpematico_credit"><small>Powered by <a href="http://www.wpematico.com" target="_blank">WPeMatico</a></small></p> <div class="sharedaddy sd-sharing-enabled"><div class="robots-nocontent sd-block sd-social sd-social-icon sd-sharing"><h3 class="sd-title">Share this:</h3><div class="sd-content"><ul><li class="share-twitter"><a rel="nofollow noopener noreferrer" data-shared="sharing-twitter-30513" class="share-twitter sd-button share-icon no-text" href="http://geektechnews.tk/2018/05/23/authenticating-firebase-and-angular-with-auth0-part-2/?share=twitter" target="_blank" title="Click to share on Twitter"><span></span><span class="sharing-screen-reader-text">Click to share on Twitter (Opens in new window)</span></a></li><li class="share-facebook"><a rel="nofollow noopener noreferrer" data-shared="sharing-facebook-30513" class="share-facebook sd-button share-icon no-text" href="http://geektechnews.tk/2018/05/23/authenticating-firebase-and-angular-with-auth0-part-2/?share=facebook" target="_blank" title="Click to share on Facebook"><span></span><span class="sharing-screen-reader-text">Click to share on Facebook (Opens in new window)</span></a></li><li class="share-google-plus-1"><a rel="nofollow noopener noreferrer" data-shared="sharing-google-30513" class="share-google-plus-1 sd-button share-icon no-text" href="http://geektechnews.tk/2018/05/23/authenticating-firebase-and-angular-with-auth0-part-2/?share=google-plus-1" target="_blank" title="Click to share on Google+"><span></span><span class="sharing-screen-reader-text">Click to share on Google+ (Opens in new window)</span></a></li><li class="share-end"></li></ul></div></div></div><div class='sharedaddy sd-block sd-like jetpack-likes-widget-wrapper jetpack-likes-widget-unloaded' id='like-post-wrapper-133988126-30513-5c0e6e76b5f6d' data-src='https://widgets.wp.com/likes/#blog_id=133988126&post_id=30513&origin=geektechnews.tk&obj_id=133988126-30513-5c0e6e76b5f6d' data-name='like-post-frame-133988126-30513-5c0e6e76b5f6d'><h3 class="sd-title">Like this:</h3><div class='likes-widget-placeholder post-likes-widget-placeholder' style='height: 55px;'><span class='button'><span>Like</span></span> <span class="loading">Loading...</span></div><span class='sd-text-color'></span><a class='sd-link-color'></a></div> <div id='jp-relatedposts' class='jp-relatedposts' > <h3 class="jp-relatedposts-headline"><em>Related</em></h3> </div><div class='code-block code-block-5' style='margin: 8px 0; clear: both;'> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- Newssites --> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9575595058630905" data-ad-slot="4409875077" data-ad-format="auto"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script></div> </div><div id="ai_widget-3" class="mh-widget mh-posts-2 ai_widget"><div class='code-block code-block-1' style='margin: 8px 0; clear: both;'> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- Newssites --> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9575595058630905" data-ad-slot="4409875077" data-ad-format="auto"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script></div> </div></article><nav class="mh-post-nav mh-row mh-clearfix" itemscope="itemscope" itemtype="http://schema.org/SiteNavigationElement"> <div class="mh-col-1-2 mh-post-nav-item mh-post-nav-prev"> <a href="http://geektechnews.tk/2018/05/23/a-designers-guide-to-kpis-and-vanity-metrics/" rel="prev"><img width="80" height="60" src="https://i0.wp.com/geektechnews.tk/wp-content/uploads/2018/05/1512957218image1.png?resize=80%2C60" class="attachment-mh-magazine-lite-small size-mh-magazine-lite-small wp-post-image" alt="" srcset="https://i0.wp.com/geektechnews.tk/wp-content/uploads/2018/05/1512957218image1.png?resize=80%2C60 80w, https://i0.wp.com/geektechnews.tk/wp-content/uploads/2018/05/1512957218image1.png?zoom=2&resize=80%2C60 160w, https://i0.wp.com/geektechnews.tk/wp-content/uploads/2018/05/1512957218image1.png?zoom=3&resize=80%2C60 240w" sizes="(max-width: 80px) 100vw, 80px" data-attachment-id="30512" data-permalink="http://geektechnews.tk/2018/05/23/a-designers-guide-to-kpis-and-vanity-metrics/1512957218image1/" data-orig-file="https://i0.wp.com/geektechnews.tk/wp-content/uploads/2018/05/1512957218image1.png?fit=295%2C554" data-orig-size="295,554" data-comments-opened="1" data-image-meta="{"aperture":"0","credit":"","camera":"","caption":"","created_timestamp":"0","copyright":"","focal_length":"0","iso":"0","shutter_speed":"0","title":"","orientation":"0"}" data-image-title="1512957218image1" data-image-description="" data-medium-file="https://i0.wp.com/geektechnews.tk/wp-content/uploads/2018/05/1512957218image1.png?fit=160%2C300" data-large-file="https://i0.wp.com/geektechnews.tk/wp-content/uploads/2018/05/1512957218image1.png?fit=295%2C554" /><span>Previous</span><p>A Designer’s Guide to KPIs and Vanity Metrics</p></a></div> <div class="mh-col-1-2 mh-post-nav-item mh-post-nav-next"> <a href="http://geektechnews.tk/2018/05/23/f8p1t3mlegc/" rel="next"><img width="80" height="60" src="https://i1.wp.com/geektechnews.tk/wp-content/uploads/2017/12/Screen_Shot_2017_12_07_at_9.38.52_PM.0.png?resize=80%2C60" class="attachment-mh-magazine-lite-small size-mh-magazine-lite-small wp-post-image" alt="" srcset="https://i1.wp.com/geektechnews.tk/wp-content/uploads/2017/12/Screen_Shot_2017_12_07_at_9.38.52_PM.0.png?resize=678%2C509 678w, https://i1.wp.com/geektechnews.tk/wp-content/uploads/2017/12/Screen_Shot_2017_12_07_at_9.38.52_PM.0.png?resize=326%2C245 326w, https://i1.wp.com/geektechnews.tk/wp-content/uploads/2017/12/Screen_Shot_2017_12_07_at_9.38.52_PM.0.png?resize=80%2C60 80w, https://i1.wp.com/geektechnews.tk/wp-content/uploads/2017/12/Screen_Shot_2017_12_07_at_9.38.52_PM.0.png?zoom=2&resize=80%2C60 160w, https://i1.wp.com/geektechnews.tk/wp-content/uploads/2017/12/Screen_Shot_2017_12_07_at_9.38.52_PM.0.png?zoom=3&resize=80%2C60 240w" sizes="(max-width: 80px) 100vw, 80px" data-attachment-id="15794" data-permalink="http://geektechnews.tk/screen_shot_2017_12_07_at_9-38-52_pm-0/" data-orig-file="https://i1.wp.com/geektechnews.tk/wp-content/uploads/2017/12/Screen_Shot_2017_12_07_at_9.38.52_PM.0.png?fit=1310%2C873" data-orig-size="1310,873" data-comments-opened="1" data-image-meta="{"aperture":"0","credit":"","camera":"","caption":"","created_timestamp":"0","copyright":"","focal_length":"0","iso":"0","shutter_speed":"0","title":"","orientation":"0"}" data-image-title="Screen_Shot_2017_12_07_at_9.38.52_PM.0" data-image-description="" data-medium-file="https://i1.wp.com/geektechnews.tk/wp-content/uploads/2017/12/Screen_Shot_2017_12_07_at_9.38.52_PM.0.png?fit=300%2C200" data-large-file="https://i1.wp.com/geektechnews.tk/wp-content/uploads/2017/12/Screen_Shot_2017_12_07_at_9.38.52_PM.0.png?fit=1024%2C682" /><span>Next</span><p>Zuckerberg didn’t make any friends in Europe today</p></a></div> </nav> </div> <aside class="mh-widget-col-1 mh-sidebar" itemscope="itemscope" itemtype="http://schema.org/WPSideBar"><div id="search-2" class="mh-widget widget_search"><form role="search" method="get" class="search-form" action="http://geektechnews.tk/"> <label> <span class="screen-reader-text">Search for:</span> <input type="search" class="search-field" placeholder="Search …" value="" name="s" /> </label> <input type="submit" class="search-submit" value="Search" /> </form></div><div id="top-posts-2" class="mh-widget widget_top-posts"><h4 class="mh-widget-title"><span class="mh-widget-title-inner">Trending</span></h4><ul> <li> <a href="http://geektechnews.tk/2018/01/12/detective-pikachu-pokemon-game-amiibo-nintendo-3ds/" class="bump-view" data-bump-view="tp"> Pikachu is a gun-shooting detective now, and his game is coming to the US </a> </li> <li> <a href="http://geektechnews.tk/2018/12/09/google-pixel-3-xl-deal-discount-sale/" class="bump-view" data-bump-view="tp"> You have another chance to save on the Pixel 3 and Pixel 3 XL </a> </li> <li> <a href="http://geektechnews.tk/2018/12/09/amazon-kindle-paperwhite-audible-bluetooth-headphones-bundle-audiobook/" class="bump-view" data-bump-view="tp"> Amazon is selling a Kindle Paperwhite and Audible bundle </a> </li> <li> <a href="http://geektechnews.tk/2018/12/09/qqefzwkuddw/" class="bump-view" data-bump-view="tp"> Why you need a supercomputer to build a house </a> </li> <li> <a href="http://geektechnews.tk/2018/12/09/3teqrvtbsu8/" class="bump-view" data-bump-view="tp"> Awaken offers meditations focused on healing from systems of oppression </a> </li> <li> <a href="http://geektechnews.tk/2018/12/09/ai-now-algorithmic-accountability-2018-report-facebook-microsoft-google/" class="bump-view" data-bump-view="tp"> When algorithms go wrong we need more power to fight back, say AI researchers </a> </li> <li> <a href="http://geektechnews.tk/2018/12/09/fbi-investigating-fake-net-neutrality-comments-fcc-new-york-washington-dc-massachusetts/" class="bump-view" data-bump-view="tp"> The FBI is now investigating fake anti-net neutrality comments </a> </li> <li> <a href="http://geektechnews.tk/2018/12/09/amazon-echo-fire-tv-smart-home-devices-holiday-discount-sale/" class="bump-view" data-bump-view="tp"> Amazon is discounting Echo, Fire TV, and smart home devices once again for the holidays </a> </li> <li> <a href="http://geektechnews.tk/2018/12/09/optimizing-kubernetes-resource-allocation-production/" class="bump-view" data-bump-view="tp"> Optimizing Kubernetes resource allocation in production </a> </li> <li> <a href="http://geektechnews.tk/2018/12/09/apple-airpod-case-crochet-diy/" class="bump-view" data-bump-view="tp"> These crocheted AirPods cases make me want to buy AirPods </a> </li> </ul></div><div id="custom_html-2" class="widget_text mh-widget widget_custom_html"><div class="textwidget custom-html-widget"><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- Newssites --> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9575595058630905" data-ad-slot="4409875077" data-ad-format="auto"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script></div></div> <div id="recent-posts-2" class="mh-widget widget_recent_entries"> <h4 class="mh-widget-title"><span class="mh-widget-title-inner">The Latest:</span></h4> <ul> <li> <a href="http://geektechnews.tk/2018/12/10/my-open-source-story/">When Linux required installation parties</a> </li> <li> <a href="http://geektechnews.tk/2018/12/10/deep-learning-inference/">How to build deep learning inference through Knative serverless framework</a> </li> <li> <a href="http://geektechnews.tk/2018/12/10/how-get-started-ai/">How to get started in AI</a> </li> <li> <a href="http://geektechnews.tk/2018/12/10/linux-toy-snake/">Snake your way across your Linux terminal</a> </li> <li> <a href="http://geektechnews.tk/2018/12/10/update-ubuntu/">How to Update Ubuntu Linux [Beginner’s Tip]</a> </li> <li> <a href="http://geektechnews.tk/2018/12/10/chromium-microsoft-browser-chrome-extensions-xbox-one/">Microsoft reveals more Edge details, including Chrome Extension support</a> </li> <li> <a href="http://geektechnews.tk/2018/12/10/48-megapixel-camera-phone-xiaomi-honor-release-date/">The 48-megapixel phones are coming</a> </li> <li> <a href="http://geektechnews.tk/2018/12/10/y4q0mlb0qw4/">Google has acquired one of India’s most popular train tracking apps</a> </li> </ul> </div><div id="ai_widget-4" class="mh-widget ai_widget"><div class='code-block code-block-1' style='margin: 8px 0; clear: both;'> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- Newssites --> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9575595058630905" data-ad-slot="4409875077" data-ad-format="auto"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script></div> </div><div id="internet_defense_league_widget-2" class="mh-widget widget_internet_defense_league_widget"><p><a href="https://internetdefenseleague.org/"><img src="https://i2.wp.com/internetdefenseleague.org/images/badges/final/shield_badge.png?ssl=1" alt="Member of The Internet Defense League" style="max-width: 100%; height: auto;" /></a></p></div><div id="ai_widget-7" class="mh-widget ai_widget"><div class='code-block code-block-4' style='margin: 8px 0; clear: both;'> <div class="alignleft"> <script type="text/javascript"> amzn_assoc_ad_type = "banner"; amzn_assoc_marketplace = "amazon"; amzn_assoc_region = "US"; amzn_assoc_placement = "assoc_banner_placement_default"; amzn_assoc_campaigns = "electronics"; amzn_assoc_banner_type = "rotating"; amzn_assoc_p = "12"; amzn_assoc_width = "300"; amzn_assoc_height = "250"; amzn_assoc_tracking_id = "shafshif-20"; amzn_assoc_linkid = "0e306357436eebd476f1f23d71505945"; </script> <script src="//z-na.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&Operation=GetScript&ID=OneJS&WS=1"></script> </div></div> </div></aside></div> <div class="mh-copyright-wrap"> <div class="mh-container mh-container-inner mh-clearfix"> <p class="mh-copyright">Copyright © 2018 | WordPress Theme by <a href="https://www.mhthemes.com/" rel="nofollow">MH Themes</a></p> </div> </div> </div><!-- .mh-container-outer --> <div id="JwaGjCfqLLZH" class="GHZuHstmwHwm" style="background:#dddddd;max-width:720px;z-index:9999999; "></div> <script type="text/javascript">/* <![CDATA[ */var anOptions ={"anOptionChoice":"2","anOptionStats":"2","anOptionAdsSelectors":"","anOptionCookie":"1","anOptionCookieLife":"30","anPageRedirect":"","anPermalink":"undefined","anOptionModalEffect":"fadeAndPop","anOptionModalspeed":"350","anOptionModalclose":true,"anOptionModalOverlay":"rgba( 0,0,0,0.8 )","anAlternativeActivation":false,"anAlternativeElement":"","anAlternativeText":"<p><strong>AdBlock detected!<\/strong><\/p>\n<p>Please add <a title=\"http:\/\/themeisle.com\/\" href=\"themeisle.com\" target=\"_blank\">www.themeisle.com<\/a> to your adblocking whitelist or disable your adblocking software.<\/p>\n","anAlternativeClone":"2","anAlternativeProperties":"","anOptionModalShowAfter":0,"anPageMD5":"","anSiteID":0,"modalHTML":"<div class=\"GHZuHstmwHwm-default\">\n\t<h1 style=\"\">Adblocker detected! Please consider reading this notice.<\/h1>\n\t<p>We've detected that you are using AdBlock Plus or some other adblocking software which is preventing the page from fully loading.<\/p>\n<p>We don't have any banner, Flash, animation, obnoxious sound, or popup ad. We do not implement these annoying types of ads!<\/p>\n<p>We need money to operate the site, and almost all of it comes from our online advertising.<\/p>\n<p><strong>Please add <a title=\"Geek Tech News\" href=\"http:\/\/geektechnews.tk\" target=\"_blank\">geektechnews.tk<\/a> to your ad blocking whitelist or disable your adblocking software.<strong><\/p>\n<\/div>\n<a class=\"close-modal close-GHZuHstmwHwm\">×<\/a>"}/* ]]> */</script><div id="adsense" class="an-sponsored" style="position:absolute; z-index:-1; height:1px; width:1px; visibility: hidden; top: -1px; left: 0;"><img class="an-advert-banner" alt="sponsored" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"></div> <script type="text/javascript"> window.WPCOM_sharing_counts = {"http:\/\/geektechnews.tk\/2018\/05\/23\/authenticating-firebase-and-angular-with-auth0-part-2\/":30513}; </script> <script type="text/javascript"> window._idl = {}; _idl.campaign = ""; _idl.variant = "banner"; (function() { var idl = document.createElement('script'); idl.type = 'text/javascript'; idl.async = true; idl.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'members.internetdefenseleague.org/include/?url=' + (_idl.url || '') + '&campaign=' + (_idl.campaign || '') + '&variant=' + (_idl.variant || 'banner'); document.getElementsByTagName('body')[0].appendChild(idl); })(); </script> <script type='text/javascript' src='http://geektechnews.tk/wp-content/plugins/jetpack/_inc/build/photon/photon.min.js?ver=20130122'></script> <script type='text/javascript' src='https://s0.wp.com/wp-content/js/devicepx-jetpack.js?ver=201850'></script> <script type='text/javascript' src='http://geektechnews.tk/wp-content/plugins/jetpack/_inc/build/widgets/eu-cookie-law/eu-cookie-law.min.js?ver=20180522'></script> <script type='text/javascript'> /* <![CDATA[ */ var jpfbembed = {"appid":"249643311490","locale":"en_US"}; /* ]]> */ </script> <script type='text/javascript' src='http://geektechnews.tk/wp-content/plugins/jetpack/_inc/build/facebook-embed.min.js'></script> <script type='text/javascript'> /* <![CDATA[ */ var ajax_object = {"nonce":"8a7e935ddb","ajaxurl":"http:\/\/geektechnews.tk\/wp-admin\/admin-ajax.php"}; /* ]]> */ </script> <script type='text/javascript' src='http://geektechnews.tk/wp-content/uploads/EcnjQTDhNkZa/HQRdynqbnLsz.js?ver=2.2.3'></script> <script type='text/javascript' src='http://geektechnews.tk/wp-includes/js/wp-embed.min.js?ver=4.9.8'></script> <script type='text/javascript' src='http://geektechnews.tk/wp-content/plugins/jetpack/_inc/build/postmessage.min.js?ver=6.7'></script> <script type='text/javascript' src='http://geektechnews.tk/wp-content/plugins/jetpack/_inc/build/jquery.jetpack-resize.min.js?ver=6.7'></script> <script type='text/javascript' src='http://geektechnews.tk/wp-content/plugins/jetpack/_inc/build/likes/queuehandler.min.js?ver=6.7'></script> <script type='text/javascript'> /* <![CDATA[ */ var sharing_js_options = {"lang":"en","counts":"1","is_stats_active":"1"}; /* ]]> */ </script> <script type='text/javascript' src='http://geektechnews.tk/wp-content/plugins/jetpack/_inc/build/sharedaddy/sharing.min.js?ver=6.7'></script> <script type='text/javascript'> var windowOpen; jQuery( document.body ).on( 'click', 'a.share-twitter', function() { // If there's another sharing window open, close it. if ( 'undefined' !== typeof windowOpen ) { windowOpen.close(); } windowOpen = window.open( jQuery( this ).attr( 'href' ), 'wpcomtwitter', 'menubar=1,resizable=1,width=600,height=350' ); return false; }); var windowOpen; jQuery( document.body ).on( 'click', 'a.share-facebook', function() { // If there's another sharing window open, close it. if ( 'undefined' !== typeof windowOpen ) { windowOpen.close(); } windowOpen = window.open( jQuery( this ).attr( 'href' ), 'wpcomfacebook', 'menubar=1,resizable=1,width=600,height=400' ); return false; }); var windowOpen; jQuery( document.body ).on( 'click', 'a.share-google-plus-1', function() { // If there's another sharing window open, close it. if ( 'undefined' !== typeof windowOpen ) { windowOpen.close(); } windowOpen = window.open( jQuery( this ).attr( 'href' ), 'wpcomgoogle-plus-1', 'menubar=1,resizable=1,width=480,height=550' ); return false; }); </script> <iframe src='https://widgets.wp.com/likes/master.html?ver=201850#ver=201850' scrolling='no' id='likes-master' name='likes-master' style='display:none;'></iframe> <div id='likes-other-gravatars'><div class="likes-text"><span>%d</span> bloggers like this:</div><ul class="wpl-avatars sd-like-gravatars"></ul></div> <script type='text/javascript' src='https://stats.wp.com/e-201850.js' async='async' defer='defer'></script> <script type='text/javascript'> _stq = window._stq || []; _stq.push([ 'view', {v:'ext',j:'1:6.7',blog:'133988126',post:'30513',tz:'0',srv:'geektechnews.tk'} ]); _stq.push([ 'clickTrackerInit', '133988126', '30513' ]); </script> </body> </html>