Use same unauthenticated identity for AWS Analytics and Cognito Sync - javascript

I'm developing an app which makes use of both AWS Mobile Analytics and Cognito Sync for user data. From looking at my network logs, I can see that the AMA.Manager for Mobile Analytics makes the same API calls as Cognito Sync to request limited temp credentials from AWS.
AWS.config.credentials.get()
My question is if its possible for both new AMA.Manager() and new AWS.CognitoSyncManager() to use the same unauthenticated identity which is requested initially from AWS.config.credentials.get()? Assuming they're both using the same Identity Pool.

Solved my own issue. As long as both AMA.Manager and AWS.CognitoSyncManager are initialized with the same credentials provider using a single IdentityPoolId it works fine. Example of my code below:
AWS.config.region = 'us-east-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: SHARED_COGNITO_IDENTITY_POOL_ID
});
var analytics = null;
var syncClient = null;
var options = {
appId : MOBILE_ANALYTICS_APP_ID
};
AWS.config.credentials.get(function(err) {
if(!err){
syncClient = new AWS.CognitoSyncManager();
analytics = new AMA.Manager(options);
}
});

Related

How to get user parameters using Amazon Cognito hosted Web UI

Recently I was using the Sign-up and Sign-in template similar this one developed by Vladimir Budilov.
But now, I've been modifying my application to use the hosted UI developed by Amazon. So my application redirects to the hosted UI, all the authentication is made there and they send me the authentication token, more os less as explained in this tutorial.
Summarizing, I call the hosted UI and do login:
https://my_domain/login?response_type=token&client_id=my_client_id&redirect_uri=https://www.example.com
I'm redirected to:
https://www.example.com/#id_token=123456789tokens123456789&expires_in=3600&token_type=Bearer
So, I have now the token_id but I can't get the current user or user parameters from this. Could anyone help me with informations or some directions?
I've tried the methods in Amazon developer guide .
It works well when I was using Vladimir Budilov's template but trying to use the token_id, I'm not succeeding. Thanks in advance for your time and help.
var data = {
UserPoolId : '...', // Your user pool id here
ClientId : '...' // Your client id here
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(data);
var cognitoUser = userPool.getCurrentUser();
if (cognitoUser != null) {
cognitoUser.getSession(function(err, session) {
if (err) {
alert(err);
return;
}
console.log('session validity: ' + session.isValid());
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId : '...' // your identity pool id here
Logins : {
// Change the key below according to the specific region your user pool is in.
'cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>' : session.getIdToken().getJwtToken()
}
});
// Instantiate aws sdk service objects now that the credentials have been updated.
// example: var s3 = new AWS.S3();
});
}
The attributes you configure to be added as claims are already available inside the id_token with base64 encoding (Since its a JWT token).
You can decode the token and access these attributes both at Client Side using Javascript and on Server.
For more info refer the StackOverflow question How to decode JWT tokens in JavaScript.
Note: If you need to trust these attributes for a backend operation, make sure you verify the JWT signature before trusting the attributes.
Here's a specific example of how to parse the callback parameters and set up a user session. This could be initiated in onLoad of your page.
import { CognitoAuth } from 'amazon-cognito-auth-js';
const authData = {
ClientId : '<TODO: add ClientId>', // Your client id here
AppWebDomain : '<TODO: add App Web Domain>',
TokenScopesArray : ['<TODO: add scope array>'], // e.g.['phone', 'email', 'profile','openid', 'aws.cognito.signin.user.admin'],
RedirectUriSignIn : '<TODO: add redirect url when signed in>',
RedirectUriSignOut : '<TODO: add redirect url when signed out>',
IdentityProvider : '<TODO: add identity provider you want to specify>', // e.g. 'Facebook',
UserPoolId : '<TODO: add UserPoolId>', // Your user pool id here
AdvancedSecurityDataCollectionFlag : '<TODO: boolean value indicating whether you want to enable advanced security data collection>', // e.g. true
Storage: '<TODO the storage object>' // OPTIONAL e.g. new CookieStorage(), to use the specified storage provided
};
const auth = new CognitoAuth(authData);
auth.userhandler = {
onSuccess: function(result) {
alert("Sign in success");
showSignedIn(result);
},
onFailure: function(err) {
alert("Error!");
}
};
const curUrl = window.location.href;
auth.parseCognitoWebResponse(curUrl);
Now you're "signed in" as far as the Cognito JS client is concerned, and you can use getCurrentUser(), getSession(), etc. `See "Use case 2" here for more context/details.

Using AWS Cognito can I resolve the authenticated IdentityId given a disabled unauthenticated IdentityId?

I have a JavaScript web application that supports Cognito unauthenticated identities. I'm trying to figure out how to identify the linked authenticated IdentityId for a DISABLED unauthenticated IdentityId.
First unauthenticated users are issued an IdentityId via AWS.config.credentials.get. Internally CognitoIdentityCredentials is using getId to generate a new unauthenticated IdentityId.
let unathenticatedIdentityId;
const AWS = require('aws-sdk');
AWS.config.region = region;
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId
});
AWS.config.credentials.get(err => {
unathenticatedIdentityId = AWS.config.credentials.identityId;
});
Then our user authenticates to a Cognito User Pool via amazon-cognito-identity-js and the unauthenticated IdentityId changes to the authenticated IdentityId associated with their Cognito Login. The unauthenticated IdentityId is automatically marked DISABLED and is linked internally to the authenticated IdentityId.
let authenticatedIdentityId;
const { CognitoUserPool, CognitoUser, AuthenticationDetails } = require('amazon-cognito-identity-js');
const Pool = new CognitoUserPool({
UserPoolId,
ClientId,
});
const authDetails = new AuthenticationDetails({
Username,
Password,
});
const user = new CognitoUser({
Pool,
Username,
});
user.authenticateUser(authDetails, {
onSuccess: (session) => {
AWS.config.credentials.params.Logins = {
[PoolProviderName]: session.idToken.jwtToken,
};
AWS.config.credentials.expired = true;
AWS.config.credentials.refresh(err => {
authenticatedIdentityId = AWS.config.credentials.identityId;
});
},
});
I have the value for unathenticatedIdentityId and authenticatedIdentityId but I do not see a way in the AWS Cognito API's to resolve that the DISABLED unauthenticatedIdentityId has been linked to the authenticatedIdentityId. Conversely I do not see a way to identify what IdentityIds have been linked to the authenticatedIdentityId. The describeIdentity API will tell me that unauthenticatedIdentityId is DISABLED and that it has no Logins, but it does not point to the linked authenticatedIdentityId.
How can I, with only the value of the linked/DISABLED unauthenticatedIdentityId, resolve the value authenticatedIdentityId?
I have an app that uses AWS Cognito to obtain an identity id and then possibly authenticate it. The situation is a client uses the app first as unauthenticated (guest) and then logs in using Facebook, making him/herself as authenticated, and AWS preserves the given identity ID for the authenticated user, because he is a new user. Now, the problem comes, when you log out of the app and someone else wants to use this app as unauthenticated or even authenticated. Cognito will error out saying that the access to the identity ID is forbidden, because it has already been linked to the previous user's Facebook account.
The Cognito mobile SDKs have a way built in to handle this. They cache the identity id when using it, which is causing the issue you are seeing. When you log out, you'll want to clear that cache. I'm not sure which SDK you're using, but in iOS it's AWSCognitoIdentityProvider.clear() and CognitoCachingCredentialsProvider.clear() in Android. Similarly, if you're using Cognito Sync, there's a method in that client that will wipe the cached id and sync data.
Also have a look at https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication/
Hope you are also following https://aws.amazon.com/blogs/mobile/using-the-amazon-cognito-credentials-provider/

Microsoft Graph API - 403 Forbidden for v1.0/me/events

I'm building a page with numerous calls to Microsoft Graph to different end points: to get OneDrive files, emails, user properties, etc.
The one call that does not work is to get the current user's calendar events. The end point I'm using is https://graph.microsoft.com/v1.0/me/events. The response is 403 Forbidden.
According to the Microsoft documentation here the application needs Calendars.Read or Calendars.ReadWrite permissions. I checked both of these under delegated permissions and still the same problem. I then ticked all 51 permission scopes in Azure AD for this app, and still the same problem.
I also tried creating a new app in Azure AD, but this did not help.
How can I use Microsoft Graph to get back the current user's calendar events? What am I missing?
EDIT:
I'm using ADAL.js for authentication. This is the code I have in my own doAuth function that takes in the client ID of the application.
function doAuth(clientId) {
var variables = {
// Domain of Azure AD tenant
azureAD: // the appropriate URL,
// ClientId of Azure AD application principal
clientId: clientId,
// Name of SharePoint tenant
sharePointTenant: // the appropriate URL
}
// Create config and get AuthenticationContext
window.config = {
tenant: variables.azureAD,
clientId: variables.clientId,
postLogoutRedirectUri: window.location.origin,
endpoints: {
graphApiUri: "https://graph.microsoft.com",
sharePointUri: "https://" + variables.sharePointTenant + ".sharepoint.com",
},
cacheLocation: "localStorage"
}
var authContext = new AuthenticationContext(config);
var isCallback = authContext.isCallback(window.location.hash);
authContext.handleWindowCallback();
if (isCallback && !authContext.getLoginError()) {
window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
}
var user = authContext.getCachedUser();
var token = authContext.getCachedToken(clientId);
if (!user || !token)
authContext.login();
return authContext
}
It sounds like you've changed the scopes assigned to the application. When this happens you also need to have user's reauthorize using those new scopes. To do this, add &prompt=consent to the query string of your initial ODATA redirect. This will force your new scopes to be presented to the user for authorization.
You can trigger this in the ADAL.js library using the extraQueryParameter parameter in your configuration:
// Create config and get AuthenticationContext
window.config = {
tenant: variables.azureAD,
clientId: variables.clientId,
postLogoutRedirectUri: window.location.origin,
endpoints: {
graphApiUri: "https://graph.microsoft.com",
sharePointUri: "https://" + variables.sharePointTenant + ".sharepoint.com",
},
cacheLocation: "localStorage",
extraQueryParameter: "prompt=consent"
}
In the end I wasn't able to figure this out and ended up using the Exchange API instead of Graph for mail, calendar and tasks (tasks would have required Exchange API anyway, since this is only currently available in the beta Graph API).

Getting additional data from Firebase Auth Facebook Login

I'm developing an application with Firebase Web and Javascript.
I built a Facebook Login, but i can't understand how to access the scopeData i requested in the sign-in step.
Here is my signInWithRedirect and getRedirectResult code:
// signInWithRedirect
var provider = new firebase.auth.FacebookAuthProvider();
provider.addScope('user_birthday');
provider.addScope('user_friends');
firebase.auth().signInWithRedirect(provider);
// getRedirectResult
firebase.auth().getRedirectResult().then(function(result){
if(result.credential)
var token = result.credential.accessToken;
var user = result.user;
}).catch(function(error){
console.log(error.code);
console.log(error.message);
});
Currently additional OAuth provider data is not returned in Firebase. You will need to use the access token returned and query facebook api to get that additional information.

AWS Cognito Identity NotAuthorizedException

I'm using the AWS javascript sdk in order to integrate user pools with a web app that I am building. The user pool is setup and I've followed the usage example here: https://github.com/aws/amazon-cognito-identity-js
I keep getting an error that says:
"NotAuthorizedException: Unable to verify secret hash for client (my app client id)"
AWS.config.region = 'us-east-1'; // Region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: '...' // my identity pool id here
});
AWSCognito.config.region = 'us-east-1';
AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: '...' // my identity pool id here
})
var poolData = {
UserPoolId: '...', // my user pool id here
ClientId: '...' // client id here
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : 'username',
Pool : userPool
};
var attributeList = [];
var dataEmail = {
Name : 'email',
Value : 'email#mydomain.com'
};
var dataPhoneNumber = {
Name : 'phone_number',
Value : '+15555555555'
};
var attributeEmail = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataEmail);
var attributePhoneNumber = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataPhoneNumber);
attributeList.push(attributeEmail);
attributeList.push(attributePhoneNumber);
userPool.signUp('username', 'password', attributeList, null, function(err, result){
if (err) {
alert(err);
return;
}
cognitoUser = result.user;
console.log('user name is ' + cognitoUser.getUsername());
});
Any suggestions or potential issues with the code snippet above? Thanks!
The solution to this is actually quite straightforward. You have to delete the app in aws and re-add it without a secret key so it can authorize.
When creating a web application using the Javascript SDK you cannot use a secret key as there is no where to store it. This will cause the exception you are seeing.
As you discovered, creating an app without a secret key solves the issue.
For JavaScript SDK, Cognito still not supports the "Client Secret". When you are creating the App Client be sure uncheck the "Generate Secret" key.
This is the same issue I am facing with Java SDK as well.
But its a question to AWS Cognito team? How we will use the Client Secret which is preferred for production environment.
Time being if anyone facing the similar issues please delete your Client App and re-create the Client app without generating Client Secret. Still we are expecting from the expert developer to answer, how we will use the client secret?
In my case, I typed incorrectly to UserPoolId. So check your credential once again.

Categories

Resources