Have you recently tried to access a remote resource or an API call from your Cordova based mobile application and it failed? Don’t worry, this happened to many developers last few months, including myself.
Cordova 4.0 brought a new way of accessing external resources, instead of changing configuration files it is possible do this via an appropriate plugin. By default, everything is blacklisted.
I’m writing this article to show you how easy is to implement this plugin into your Cordova based Android/iOS project.
To demonstrate you how this plugin works we will reuse one of my previous examples were I ws trying to list a content of moviedb database. This example is part of Master Detail Pattern tutorial, more information about provided example can be found there, no point in repeating what’s already written.

Note: If this tutorial was helpful, need further clarification, something is not working or do you have a request for another Ionic post? Furthermore, if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here, again leave me a comment below. I'm here to help you, I expect the same from you. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com, or follow and mention me on twitter (@gajotres). Thanks and have a nice day!

PS. If you want my help, if possible (even if it takes you some time to do that), create a working example I can play with. Use Plunker for AngularJS based questions or jsFiddle for jQuery/jQuery Mobile based questions.


Table of Contents

Click here if you want to see other tutorials, or articles about the Ionic framework (themes, templates, plugins, tutorials)


Before we can start make sure you have everything configured correctly.
You will need to have these:
  • Android Environment (or iOS if your working on a MacOS)
  • nodeJS
  • Ionic
  • Cordova
In case you don’t have a properly configured development environment take a look at this article: Ionic Framework | Installation Guide.

1. Update Ionic & Cordova

Don’t forget to update Ionic and Cordova, older versions may not work with this tutorial:
npm update -g cordova ionic

2. Create a New Project

ionic start IonicWhiteListDemo blank
cd IonicWhiteListDemo
Warning: Since a few of my readers never worked with Ionic CLI. From this point and further, every time I tell you to execute something, do that inside a project folder.
At this point, we need to upgrade IonicWhiteListDemo project with an appropriate platform. Because I’m using Windows we’re going to create an Android application:
ionic platform add android
if you’re a MacOS user, create an iOS application like this:
ionic platform add ios


At this point, you should have everything set up and ready.
Go to IonicWhiteListDemo project directory and open main index.html file, replace everything with these:
<!DOCTYPE html>
<html ng-app="starter">
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">

    <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
    <link href="css/ionic.app.css" rel="stylesheet">

    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>

    <!-- cordova script (this will be a 404 during development) -->
    <script src="cordova.js"></script>

    <!-- your app's js -->
    <script src="js/app.js"></script>
  <!-- The nav bar that will be updated as we navigate -->
  <ion-nav-bar class="bar-positive">
    <ion-nav-back-button class="button-clear">
      <i class="ion-arrow-left-c"></i> Back
  <script id="list.html" type="text/ng-template">
    <ion-view view-title="Search The Movie Database"> 
        <label class="item item-input">
          <i class="icon ion-search placeholder-icon"></i>
          <input type="search" placeholder="Search" ng-model="movie.name" ng-change="searchMovieDB()">
          <div class="list">
            <a ng-repeat="movie in movies" href="#/movie/{{movie.id}}" class="item item-thumbnail-left">
              <img ng-src="https://image.tmdb.org/t/p/w92{{movie.poster_path}}" onerror="this.src = 'https://www.ginesisnatural.com/images/no_image.jpg';">
  <script id="view.html" type="text/ng-template">
    <ion-view view-title="Movie details">   
        <div class="list card">
          <div class="item item-avatar">
            <img src="http://files.softicons.com/download/object-icons/movies-icons-by-pinchodesigns/png/32x32/Movie.png">
          <div class="item item-image">
            <img ng-src="https://image.tmdb.org/t/p/w92{{movie.poster_path}}" width="200px" />
          <a class="item" href="#">
              Average Vote: <strong>{{movie.vote_average}}</strong> (Votes: {{movie.vote_count}})
Now do the same in app.js file and replace everything with these:
var nameApp = angular.module('starter', ['ionic']);

nameApp.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
    if(window.StatusBar) {

nameApp.config(function($stateProvider, $urlRouterProvider) {
    .state('list', {
      url: '/',
      templateUrl: 'list.html',
      controller: 'ListCtrl'
    .state('view', {
      url: '/movie/:movieid',
      templateUrl: 'view.html',
      controller: 'ViewCtrl'

nameApp.factory('Movies', function($http) {
  var cachedData;
  function getData(moviename, callback) {
    var url = 'http://api.themoviedb.org/3/',
      mode = 'search/movie?query=',
      name = '&query=' + encodeURI(moviename),
      key = '&api_key=5fbddf6b517048e25bc3ac1bbeafb919';
    $http.get(url + mode + key + name).success(function(data) {
      cachedData = data.results;
    }).error(function(error) {
		alert("Something went wrong!");
  return {
    list: getData,
    find: function(name, callback) {
      var movie = cachedData.filter(function(entry) {
        return entry.id == name;
nameApp.controller('ListCtrl', function($scope, $http, Movies) {
  $scope.movie = {
    name: 'Batman'
  $scope.searchMovieDB = function() {
    Movies.list($scope.movie.name, function(movies) {
      $scope.movies = movies;
nameApp.controller('ViewCtrl', function($scope, $http, $stateParams, Movies) {
  Movies.find($stateParams.movieid, function(movie) {
    $scope.movie = movie;
This much code should be enough for a skeleton application, just a bare minimum.
Continue Reading

  • Todd Hale

    The warning above says to NOT use the given meta tag for production environments. Is there another, more secure version of the meta tag that should be used? Or does the whitelist plugin lock the app down? What if my app is released on the web, in addition to iOS and Android? Yes, I’m a noob to the CSP meta tag. Thanks!

    • That’s something you will need to discover on your own because only the most loose meta tag can cover all applications. More restrictive ones will work on some application but at the same time will fail on other.

      You don’t need to beleive me but plugin GitHub page offers enough information for you to choose from.

      These are few things I can think off:

      Remove ‘unsafe-inline’ and ‘unsafe-eval’ from default-src.
      If possible lock yourself to a specific domain: content=”default-src ‘self’ foo.com”
      Use only https connections: content=”default-src ‘self’ https:”
      In config.xml do not use this line: it will white list every remote source. Add only specific external URL’s.

      • Todd Hale

        Excellent. Thanks @dragangai:disqus!