0

I am working on the Azure mobile app and try to push notification to ios, my app can push notification for android but can not for ios. because in the case ios I cannot register the device to notification hub in the client side, I am facing the issue

enter image description here

Here is my client code (ionic 2)

initPushNotification(userId = undefined, deviceToken = undefined, installationId = undefined) {
   const options: PushOptions = {
     android: {
       senderID: 'mysender id',
       forceShow: false,
       sound: true
     },
     ios: {
       alert: 'true',
       badge: false,
       sound: 'true'
     },
     windows: {}
   };
   this.platform.ready().then(() => {
     const pushObject: PushObject = this.push.init(options);

     pushObject.on('registration').subscribe((data: any) => {
       let handle = data.registrationId;

       let templateAndroid = {
         body: { data: { message: "{$(message)}", notificationtype: "{$(notificationtype)}" } },
         tags: [userId]
       };

       let templateiOS = {
         body: { aps: { alert: "{$(message)}", notificationtype: "{$(notificationtype)}" } },
         tags: [userId]
       };

       this.client = new WindowsAzure.MobileServiceClient("http://phattifymobileservice.azurewebsites.net");
       if (!deviceToken || (deviceToken !== handle)) {
         if (this.platform.is('ios')) {
           this.typeDevice = 'ios';
           this.client.push.register('apns', handle, { mytemplate: templateiOS }); -----> the error is here
         } else if (this.platform.is('android')) {
           this.typeDevice = 'android';
           this.client.push.register('gcm', handle, { mytemplate: templateAndroid });
         }
         installationId && this.unregisterPush(deviceToken, installationId);
         this.apiProvider.updateDeviceToken(handle, this.client.push.installationId).subscribe(res => {
           console.log('update device token', res);
         })
       }
       console.log('device token -> ' + data.registrationId);
     });
     let me = this;
     pushObject.on('notification').subscribe(data => {
       if (!data.additionalData.foreground) {
         this.events.publish('push:on', { tabIndex: 1 });
       }
     })
     pushObject.on('error').subscribe(error => console.error('Error with Push plugin', error));
   });
 }

i tried many think for fix the issue cors domain, but it still isn't working here is my back end.

file app.js

 app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');
        res.setHeader('Access-Control-Allow-Headers', 'Origin, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, X-Requested-With, Date, X-Api-Version, X-Response-Time, X-PINGOTHER, X-CSRF-Token,Authorization, Access-Control-Request-Headers, If-Modified-Since, x-zumo-installation-id, x-zumo-version, zumo-api-version');
        res.setHeader('Access-Control-Allow-Methods', 'GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS');
        res.setHeader('Access-Control-Expose-Headers', 'X-Api-Version, X-Request-Id, X-Response-Time');
        res.setHeader('Access-Control-Max-Age', '1000');
        res.setHeader('Access-Control-Allow-Credentials', 'true');
        next();
    });

file push notification

var payload = {
        message: JSON.parse(msg.Content).Content,
        notificationType: config.get("notificationType")
    };


    context.push.send(Id, payload, function (error) {
        if (!error) {
            //notification sent
            console.log(error);
        }
    });

Push notification for Android -----> working well

Push notification for ios-----> error

I don't know why I got this error, please help me out of this error

after tried some test, there are clues

My app is using the socket for the chat function so I need to enable the CORS. I tried to comment the CORS in code and log into Azure portal and set CORS under "API > CORS" of My mobile app then the Client IOS can register to notification hub so i can push notification, but the socket raise up to me 2 errors

  1. cannot use wildcard in access-control-allow-origin when credentials flag is true

  2. failed to load resource: cannot use wildcard in access-control-allow-origin when credentials flag is true so

Update

mobileApp.tables.initialize()
    .then(function () {
    app.use(mobileApp);    // Register the Azure Mobile Apps middleware
    var httpChat = require('http').Server(app);
    var io = require('socket.io')(httpChat);
    io.set('origins', 'http://localhost:8080');
    require('./api/chat/service/Chat.js')(app, io, multer, uniqid, mkdirp);
    require('./api/chat/service/Room.js')(app, io, multer, uniqid, mkdirp);
    httpChat.listen(process.env.PORT || 3000);  // Listen for requests
});
beginerdeveloper
  • 785
  • 4
  • 17
  • 43

1 Answers1

1

According to your description, you are using App Service Push which would expose the below API endpoint(s) for the client to device registration and internally invoke the corresponding Azure Notification Hubs for registration management.

//Create Or Update Installation
PUT https://{your-mobile-app-name}.azurewebsites.net/push/installations/{InstallationId}

//Delete Installation
DELETE https://{your-mobile-app-name}.azurewebsites.net/push/installations/{InstallationId}

For your error response, it's talking about CORS. I would recommend you could try to comment out the related code for CORS settings, then log into Azure portal and set CORS under "API > CORS" of your mobile app to narrow down this issue. Moreover, since Push notification for Android is ok, you could collect the network traces and compare the requests between pushing for Android and iOS to troubleshot this issue by yourself.


UPDATE:

You could follow CORS not allowed when using socket.io and Socket.io + Node.js Cross-Origin Request Blocked to write your code as follows:

io.set('origins', 'http://localhost:8080');

res.header("Access-Control-Allow-Origin", "http://localhost:8080");
res.header('Access-Control-Allow-Credentials', true);

Or you could just leverage cors package to enable CORS.


UPDATE2:

For your issue, I did some test on my side. I found that if you set CORS under "API > CORS", then you would get the following similar error:

Failed to load http://brucemobile.azurewebsites.net/socket.io/?EIO=3&transport=polling&t=MIIOCpK: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. Origin 'http://localhost' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

For your issue, you need to implicitly set it in your code as follows:

app.use(function (req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost');
    next();
});

Note: You do not need to manually set origins for Socket.io, any origins would be allowed by default. Details you could refer to here.

For registering the registration, I did not test the full process, I just sent a get request as follows to check whether the CORS has been effected or not.

http://{your-mobile-app-name}.azurewebsites.net/push/installations/{guid}

TEST:

enter image description here

Moreover, you could follow my testing website: http://brucemobile.azurewebsites.net/index.html, you could save the html to your local side and test it with my mobile app backend.

Backend app.js

// This is a base-level Azure Mobile App SDK.
var express = require('express'),
    azureMobileApps = require('azure-mobile-apps');

// Set up a standard Express app
var app = express();

app.use(function (req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost');
    next();
});

var mobileApp = azureMobileApps({
    // Explicitly enable the Azure Mobile Apps home page
    homePage: true,
    // Explicitly enable swagger support. UI support is enabled by
    // installing the swagger-ui npm module.
    swagger: true,
    // App will use MS_SqliteFilename or MS_TableConnectionString to choose the SQLite or SQL data provider
    data: {
        dynamicSchema: true
    }
});

// Import the files from the tables directory to configure the /tables endpoint
mobileApp.tables.import('./tables');

// Import the files from the api directory to configure the /api endpoint
mobileApp.api.import('./api');

// Initialize the database before listening for incoming requests
// The tables.initialize() method does the initialization asynchronously
// and returns a Promise.
mobileApp.tables.initialize()
    .then(function () {

        app.use(mobileApp);    // Register the Azure Mobile Apps middleware

        var httpServer=require('http').Server(app);
        var io=require('socket.io')(httpServer);
        //io.set('origins', 'abc');
        io.on('connection', function(socket){
          socket.on('user message', function(msg){
            console.log('[client]: ' + msg);
            socket.emit('server message','[server '+new Date().toISOString()+']: '+msg);
          });

          socket.on('disconnect', function(){
            console.log('user disconnected');
          });
        });

        httpServer.listen(process.env.PORT || 3000);   // Listen for requests
    });
Bruce Chen
  • 18,207
  • 2
  • 21
  • 35
  • so what should i set into API > CORS, http:localhost8080 or * – beginerdeveloper Jul 11 '18 at 09:42
  • 1
    You could just set `*` for testing. – Bruce Chen Jul 11 '18 at 09:51
  • it works but, my app is using socket io for chat I need to res.setheader for CORS if I remove my cors in the code the client can register successfully but the socket raise up to me 2 error 1. cannot use wildcard in access-control-allow-origin when credentials flag is true 2. failed to load resource: cannot use wildcard in access-control-allow-origin when credentials flag is true so can you suggest me an other solution – beginerdeveloper Jul 12 '18 at 04:17
  • 1
    Adding `http://localhost:8080` to the allowed origins under "API > CORS" instead of `*` to check whether the push notification and your chat could work as expected or not. – Bruce Chen Jul 12 '18 at 05:42
  • Yes i did it, but my chat isn't woring – beginerdeveloper Jul 12 '18 at 06:10
  • 1
    I updated my answer with some similar issues, you could refer to the updated part. – Bruce Chen Jul 12 '18 at 08:29
  • sorry just want to confirm that, I need to use API > CORS and set * and apply your code your write above or just apply your code – beginerdeveloper Jul 12 '18 at 08:41
  • i just update my question follow your code but still can register i push notification, cuold you see that and let me know what i did wrong – beginerdeveloper Jul 12 '18 at 09:33
  • 1
    For Socket.io, I assume that `io.set('origins', 'http://localhost:8080');` should work...have you checked the similar issue links in my answer? Please provide the detailed request errors of your chat. – Bruce Chen Jul 12 '18 at 09:56
  • Here is the error i got in network `1. cannot use wildcard in access-control-allow-origin when credentials flag is true ` `2. failed to load resource: cannot use wildcard in access-control-allow-origin when credentials flag is true so can you suggest me an other solution` – beginerdeveloper Jul 12 '18 at 09:58
  • If I follow your guide `io.set('origins', 'http://localhost:8080');`, the socket io working well but the client can not register to push notification so can not push notification to iso and the error is the picture I posted before – beginerdeveloper Jul 12 '18 at 10:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/174874/discussion-between-beginerdeveloper-and-bruce-chen). – beginerdeveloper Jul 12 '18 at 10:11
  • 1
    I did some test and updated my answer, you could refer to them. – Bruce Chen Jul 13 '18 at 07:27
  • Could you see my message in chat, i still get the error – beginerdeveloper Jul 13 '18 at 08:30
  • 1
    Have you correctly configured the `Access-Control-Allow-Origin`? `res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');` – Bruce Chen Jul 13 '18 at 08:54
  • Yes i dit `app.use(function (req, res, next) { res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, If-Modified-Since, x-zumo-installation-id, x-zumo-version, zumo-api-version'); res.setHeader('Access-Control-Allow-Methods', 'GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS'); next(); });` – beginerdeveloper Jul 13 '18 at 08:59
  • and i need to add `Access-Control-Allow-Headers` and `Access-Control-Allow-Methods` because the request header need it – beginerdeveloper Jul 13 '18 at 09:00
  • 1
    Make sure you have included all the headers sent from `put/delete https://{your-mobile-app-name}.azurewebsites.net/push/installations/{Installatio‌​nId}` into `Access-Control-Allow-Headers`. – Bruce Chen Jul 13 '18 at 09:35