Possible to authenticate an AWS Cognito user via the API? - javascript

JavaScript/AWS here, although this is more of an AWS API question (since the JavaScript SDK just implements the API).
I'm looking at the AWS Cognito JavaScript SDK and trying to figure out how to programmatically authenticate a user given:
a username
a password
a user pool ID
But nothing obvious is jumping out at me. Is this not possible to do through their API/SDK? Do they force you to login from a web form?! Thanks in advance for any-and-all-steering!

I think there are couple of options that we can use here.
Let me provide examples with InitiateAuthCommand and AdminInitiateAuthCommand.
InitiateAuthCommand:
In order to user this, we should enable ALLOW_USER_PASSWORD_AUTH in the app client. This can be used in client-side authentication flow.
return new CognitoIdentityProviderClient({region: "<aws-region>"}).send(
new InitiateAuthCommand({
ClientId: "<the client id of the app>",
AuthFlow: AuthFlowType.USER_PASSWORD_AUTH,
AuthParameters: {
USERNAME: "<user#example.com>",
PASSWORD: "<password>",
},
})
)}
AdminInitiateAuthCommand:
In order to user this, we should enable ALLOW_ADMIN_USER_PASSWORD_AUTH in the app client. Also we have to configure the AWS credentials in the execution environment. So this can be used in Server-side authentication flow
return new CognitoIdentityProviderClient({region: "<aws-region>"}).send(
new AdminInitiateAuthCommand ({
ClientId: "<the client id of the app>",
AuthFlow: AuthFlowType.ADMIN_NO_SRP_AUTH,
UserPoolId:"<the user pool id>",
AuthParameters: {
USERNAME: "<user#example.com>",
PASSWORD: "<password>",
},
})
)}
NOTE: You can change the AuthFlow based on your requirement. Please read User pool authentication flow, InitiateAuthCommandInput.AuthFlow and AdminInitiateAuthCommandInput.AuthFlow for more details.

Related

Request had insufficient authentication scopes javascript

I already have a project to query google calendar apis.
I wanted to go further by querying google mail apis.
In my project I have activated mail API
I have added discoveryDocs in my javascript app like this
[
"https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest",
"https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"
]
And scopes like this
"https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events https://mail.google.com/"
Initialization of my client is done like this:
initClient(): void {
gapi.client.init({
apiKey: 'ma_api_key',
clientId: 'my_client_id.apps.googleusercontent.com',
discoveryDocs: [
"https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest",
"https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"
],
scope: 'https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events https://mail.google.com/',
}).then(() => {
console.log('ok')
});
}
I still can get my calendars and events but I can not get my labels with this code:
getMails(): void {
console.log(gapi);
gapi.client.gmail.users.labels.list({
'userId': 'me'
}).then(function(response) {
var labels = response.result.labels;
console.log(labels);
});
}
What am I missing please ?
Thanks
Request had insufficient authentication scopes javascript
Means that the user who you have authentication with has authorized your application to use some scopes but they are not the scopes, but you are trying to use a method which requires addental scopes then the user has authorized your application for.
This error normally occurs when you authorize your application once then change the scopes and run it again, if your application still has a session var or cookies from the previous authorization request then your application will run without requesting access of the user and adding the additional scopes.
You need to revoke the access token or force the application show the consent screen again

How to sign user in after registration using AWS Amplify and React

When a user signs up using the withAuthenticator component, they are automatically logged in after confirming their email address. It this possible to automatically sign them in using a custom sign-in flow and the Auth object? How would this be accomplished?
I recently dealt with an issue in which I wanted to use the Storage module of Amplify, but had to implement the Auth module in order to do it. I had a working signin flow, and didn't want it disturbed, so I used the Auth api to sign users into AWS in the background, while signing them into my app using my original flow.
The docs describe how to sign a user in programmatically here: https://docs.amplify.aws/lib/auth/emailpassword/q/platform/js
Implementing the JS code isn't too hard
import { Auth } from 'aws-amplify';
async function signIn() {
try {
const user = await Auth.signIn(username, password);
} catch (error) {
console.log('error signing in', error);
}
}
I implemented a pre-sign up lambda trigger to auto confirm users, their email, etc bc I didn't want this Auth flow interrupting my existing flow. This method is described here:
https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-sign-up.html#aws-lambda-triggers-pre-registration-example-2
Here are the notes I took as I was working, in case it helps to give you more context. Sorry if they're confusing, they're only really meant for me to read: https://www.evernote.com/shard/s713/sh/ccf96dcc-b51e-9963-5207-ac410b02a13a/0bcdb4bc85ea8a31b7f5621a6812c837
As of Amplify JS API v4.3.29 it is now possible. Simply include the autoSignIn attribute in the signUp method.
Auth.signUp({
username: 'xxxxxx',
password: '*********,
attributes: {
email: 'xxxxxxxxxx'
},
autoSignIn: {
enabled: true
}
})

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/

How to authenticate as an User in Podio using NodeJS

I'm working on an integration between Slack and Podio. Up until now I've been authenticating as an APP in order to make some API calls. Now I find myself trying to use the Views API but I'm getting the following error message:
message: { error_parameters: {},
error_detail: null,
error_propagate: false,
request:
{ url: '<api url>',
query_string: '',
method: 'POST' },
error_description: 'Authentication as app is not allowed for this method',
error: 'forbidden' },
status: 403,
url: '<app url>',
name: 'PodioForbiddenError' }
The error_description makes me think that I need to authenticate as an user, in order to get the access to this API. This is how I'm authenticating right now:
const Podio = require('podio-js').api;
const podio = new Podio({
authType: 'app',
clientId: process.env.clientId,
clientSecret: process.env.clientSecret
});
I haven't been able to find an example of user authentication using node.js/javascript. Do I need to generate a new clientId and/or clientSecret? Can anyone provide a working example?
Thanks for your time!
To authenticate with app you need to provide the app id and app token. By providing client id and client secret you can get the podio client, then you need to authenticate the podio client with app credentials. like
podio.AuthenticateWithApp(appId, appToken);
you can get appid and app token from the developer tab of the app.
I ended up using podio.AuthenticateWithCredentials(userName, password);

Google account gets suspended when using Gmail API from Node.js Nodemailer

I have an Express web application on a Node.js server. It supports sending email notifications for registration, password reset, etc. For this, I use Nodemailer and XOAuth2 to connect to Google API using a normal Google account. The connection works well and emails are being sent as expected. But after a while (1-3 days), Google sends me a message saying my account "has been suspended because of a violation of our Terms of Service" (screenshot). So I have to manually recover the account using the link in the notification and then the emails that were blocked during suspension are sent.
After getting 3 of those notifications, I noticed that they follow only if I triggered my email sending function (see below)
I tried to log XOAuth2's token refresh and seems like it works
I tried to renew the refreshToken from the playground several times but the problem remains
IMHO, it might be that I'm using a free account and Google wants me to pay for using its API, it thinks I do some kind spams, or it just doesn't want me to use its API. I'm I wrong?
So my questions are:
Why does my account get suspended?
What can I do to fix this problem?
Code details (approximate):
var bluebird = require('bluebird');
var nodemailer = require('nodemailer');
var xoauth2 = require('xoauth2');
// clientId, clientSecret taken from: https://console.developers.google.com/
// Create credentials > OAuth client ID > Web application >
// Name = Nodemailer,
// Authorised redirect URIs = https://developers.google.com/oauthplayground
//
// refreshToken taken from: https://developers.google.com/oauthplayground/
// Access token location: Autorization header w/ Bearer prefix
// Access type: Offline
// Force prompt: Consent Screen
// Use your own OAuth credentials: yes
// Authorized APIs: everything inside Gmail API v1
// Auto refresh the token after it expires: yes
xoauth2Gen = xoauth2.createXOAuth2Generator({
user: 'example#gmail.com', // my real google account
clientId: '84037...t.com', // my real clientId
clientSecret: 'c3Yo...KP', // my real clientSecret
refreshToken: '1/ex...Wk' // my real refreshToken
// nothing more here
});
var mail_transport: {
service: 'Gmail',
auth: { xoauth2: xoauth2Gen }
};
var mailer = bluebird.promisifyAll(nodemailer.createTransport(mail_transport));
mailer.sendMail({
from : '"Example User" <example#gmail.com>',
to : 'recipient#gmail.com',
subject : 'Example subject',
text : 'Example\nplain\ntext',
// could it be bad html?
html : 'Example<br><strong>html</strong><br>version'
}).then(function (info) { console.log(info); });

Categories

Resources