2017-02-28 4 views
0

Kurz gesagt: Ich habe einen Federated Identity Pool, der Rollen für nicht authentifizierten und authentifizierten Zugriff hat. Ich habe keine Probleme mit nicht authentifiziertem Zugriff. Aber wenn es um authentifizierten Zugriff geht, meldet sich der Benutzer gut an, aber meine Rolle für die authentifizierten Benutzer wird nicht wirklich angewendet.MQTT-Verbindung für über Cognito Identity Pool authentifizierte Benutzer

Ich habe einen S3-Bucket mit einfachen index.html und index.js Dateien, die über MQTT kommunizieren.

Beide Richtlinien für authentifizierte und nicht authentifizierte Benutzer sehen jetzt genau gleich aus und sind ziemlich freizügig (natürlich ist es nicht der Weg für die Produktion, aber ich versuche nur, es in irgendeiner Weise funktionieren zu lassen) . So sehen beide Richtlinien wie folgt:

{ 
    "Version": "2012-10-17", 
    "Statement": [ 
     { 
      "Effect": "Allow", 
      "Action": "*", 
      "Resource": "*" 
     } 
    ] 
} 

Und in index.js kann ich MQTT Verbindung als nicht authentifizierter Benutzer herstellen, wie folgt:

var region = 'eu-west-1'; 
AWS.config.credentials = new AWS.CognitoIdentityCredentials({ 
    IdentityPoolId: 'my-identity-pool-id', 
}); 
AWS.config.credentials.clearCachedId(); 
AWS.config.credentials.get(function(err) { 
    console.log('accessKeyId:', AWS.config.credentials.accessKeyId); 
    if(err) { 
    console.log(err); 
    return; 
    } 
    var requestUrl = SigV4Utils.getSignedUrl(
    'wss', 
    'data.iot.' + region + '.amazonaws.com', 
    '/mqtt', 
    'iotdevicegateway', 
    region, 
    AWS.config.credentials.accessKeyId, 
    AWS.config.credentials.secretAccessKey, 
    AWS.config.credentials.sessionToken 
); 

    initClient(requestUrl); 
}); 

initClient() stellt nur MQTT Verbindung mittels Paho:

function initClient(requestUrl) { 
    var clientId = String(Math.random()).replace('.', ''); 
    var rpcId = "smart_heater_" + String(Math.random()).replace('.', ''); 
    var client = new Paho.MQTT.Client(requestUrl, clientId); 
    var connectOptions = { 
    onSuccess: function() { 
     console.log('connected'); 
     // Now I can call client.subscribe(...) or client.send(...) 
    }, 
    useSSL: true, 
    timeout: 3, 
    mqttVersion: 4, 
    onFailure: function (err) { 
     console.error('connect failed', err); 
    } 
    }; 
    client.connect(connectOptions); 

    client.onMessageArrived = function (message) { 
    console.log("msg arrived: " + message); 
    }; 
} 

und es funktioniert gut: connected wird auf der Konsole ausgegeben, und ich kann tatsächlich senden/abonnieren.

Jetzt versuche ich das gleiche für authentifizierte Benutzer zu tun. Dazu habe ich den Cognito User Pool hinzugefügt, dort einen Benutzer angelegt, eine "App" erstellt, meinen Identity Pool um den Authentifizierungsanbieter "Cognito" erweitert (mit entsprechender User Pool ID und App Client ID) und die Authentifizierung selbst funktioniert einwandfrei: Benutzer wird angemeldet-Code sieht wie folgt aus:.

var region = 'eu-west-1'; 
var poolData = { 
    UserPoolId: 'eu-west-1_XXXXXXXXX', 
    ClientId: 'ZZZZZZZZZZZZZZZZZZZZZZZZZ', 
}; 
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData); 

var authenticationData = { 
    Username: 'myusername', 
    Password: 'mypassword', 
}; 
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData); 
var userData = { 
    Username: 'myusername', 
    Pool: userPool 
}; 
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData); 
cognitoUser.authenticateUser(authenticationDetails, { 
    onSuccess: function (result) { 
    console.log('result:', result); 
    console.log('access token: ' + result.getAccessToken().getJwtToken()); 

    var myUserPoolId = 'eu-west-1_XXXXXXXXX'; 
    console.log('You are now logged in.'); 

    // Add the User's Id Token to the Cognito credentials login map. 
    var logins = {}; 
    logins['cognito-idp.' + region + '.amazonaws.com/' + myUserPoolId] = result.getIdToken().getJwtToken(); 

    AWS.config.credentials.params.Logins = logins; 
    // finally, expire the credentials so we refresh on the next request 
    AWS.config.credentials.expired = true; 

    //call refresh method in order to authenticate user and get new temp credentials 
    AWS.config.credentials.refresh((error) => { 
     if (error) { 
     console.error(error); 
     } else { 
     console.log('Successfully logged!'); 
     console.log('accessKeyId:', AWS.config.credentials.accessKeyId); 

     var requestUrl = SigV4Utils.getSignedUrl(
      'wss', 
      'data.iot.' + region + '.amazonaws.com', 
      '/mqtt', 
      'iotdevicegateway', 
      region, 
      AWS.config.credentials.accessKeyId, 
      AWS.config.credentials.secretAccessKey, 
      AWS.config.credentials.sessionToken 
     ); 

     initClient(requestUrl); 
     } 
    }); 
    }, 

    onFailure: function (err) { 
    alert(err); 
    }, 

    newPasswordRequired: function(userAttributes, requiredAttributes) { 
    // User was signed up by an admin and must provide new 
    // password and required attributes, if any, to complete 
    // authentication. 

    // the api doesn't accept this field back 
    delete userAttributes.email_verified; 

    var newPassword = prompt('Enter new password ', ''); 
    // Get these details and call 
    cognitoUser.completeNewPasswordChallenge(newPassword, userAttributes, this); 
    }, 
}); 

der Logging-Teil nicht trivial war Arbeit zu bekommen, aber jetzt ist es funktioniert gut: in der Konsole, ich sehe:

You are now logged in. 
Successfully logged! 
accessKeyId: ASIAIRV4HOMOH6DXFTWA 

Und dann, zur Verbindungszeit, erhalte ich den folgenden Fehler:

connect failed: {invocationContext: undefined, errorCode: 8, errorMessage: "AMQJS0008I Socket closed."} 

Ich nehme an, das liegt daran, dass die Rolle, die tatsächlich auf den authentifizierten Benutzer angewendet wird, die Aktion iot:Connect; Ich glaube, weil ich genau den gleichen Fehler für nicht authentifizierte Benutzer wiedergeben kann, wenn ich die folgenden in der Richtlinie für nicht authentifizierte Benutzer setzen:

{ 
    "Action": [ 
     "iot:Connect" 
    ], 
    "Resource": "*", 
    "Effect": "Deny" 
}, 

Dann authentifizierte Benutzer die gleiche Fehlermeldung AMQJS0008I Socket closed, wenn sie versuchen zu verbinden.

Es sieht also so aus, als würde meine Richtlinie für authentifizierte Benutzer nicht auf den authentifizierten Benutzer angewendet.

Ich habe viel experimentiert, bevor ich diese Frage geschrieben habe. Derzeit in meiner Identität Pool-Einstellungen in „authentifizierte Rollenauswahl“ Ich habe nur „Standard-Rolle“, die in der Tat meine authentifizierten Rolle wählen soll, das ist:

{ 
    "Version": "2012-10-17", 
    "Statement": [ 
     { 
      "Effect": "Allow", 
      "Action": "*", 
      "Resource": "*" 
     } 
    ] 
} 

Aber ich habe auch versucht, um „Rolle auswählen mit Regeln "und schreibe eine Regel, die meine Rolle basierend auf einer passenden Klausel setzt.

Ich habe auch versucht, eine Gruppe in meinem Benutzerpool zu erstellen, dort die gleiche Rolle zu verwenden, meinen Benutzer zu dieser Gruppe hinzuzufügen und in den Identitätspool-Einstellungen "Rolle aus Token auswählen" zu setzen.

Nichts half. Ich bekomme diese errorMessage: "AMQJS0008I Socket closed." Nachricht für authentifizierte Benutzer, während für nicht authentifizierte Benutzer alles funktioniert, auch wenn die Richtlinien identisch sind.

Jede Hilfe wird geschätzt.

Antwort

1

Das Problem war, dass für authentifizierten Cognito Benutzer, IAM Politik zur Identität Pool Befestigung ist nicht genug: zusätzlich zu dem, muss man zu jeder Identität (im Grunde eine IoT Politik (nicht IAM Politik) befestigen, um jeder Benutzer), wie folgt aus:

$ aws iot attach-principal-policy \ 
    --policy-name Some-Policy \ 
    --principal us-east-1:0390875e-98ef-420d-a52d-f4188ce3cf06 

prüfen auch dieses Themas https://forums.aws.amazon.com/thread.jspa?messageID=726121

+0

Also gibt es keine Möglichkeit, dies von der aws-Konsole zu tun, ist das richtig? –

Verwandte Themen