Flutter AWS Cognito Token showing invalid signature - amazon-web-services

I am stared developing a flutter project with AWS Cognito login features. In flutter, AWS Cognito login was working fine and I am getting the access token but when checking that in API or JWT its shows the error "Invalid Signature".
I add the below code for the AWS Cognito login features. I have installed the amplify_auth_cognito: '<1.0.0' in pubspec.yaml file to create the AWS Cognito login features in the app. Login codes working fine and perfectly but the token which returns from that code shows "Invalid Signature".
Future<String> _signIn(LoginData data) async {
try {
SignInResult res = await Amplify.Auth.signIn(
username: data.name,
password: data.password,
);
final resp = await Amplify.Auth.fetchAuthSession(
options: CognitoSessionOptions(getAWSCredentials: true),
);
if (resp.isSignedIn) {
final sess = resp as CognitoAuthSession;
print("TOKEN FROM THE COGNITO: ${sess.userPoolTokens.accessToken}");
}
setState(() {
isSignedIn = res.isSignedIn;
});
if (isSignedIn) {
_btnController.success();
AWSConfigurationHelper().getUserDetails();
Timer(Duration(seconds: 1), () {
_btnController.reset();
Navigator.pushReplacementNamed(context, DeviceList.routeName);
});
}
} on AuthError catch (e) {
Alert(
context: context,
type: AlertType.error,
title: "Login Failed",
desc: e.cause.toString(), //e.toString(),
).show();
_btnController.error();
Timer(Duration(seconds: 1), () {
_btnController.reset();
});
print(e.cause);
for (final exception in e.exceptionList) {
print(exception.exception);
print(exception.detail);
}
return 'Log In Error: ' + e.toString();
}}
My pubspec.yaml file screenshot was attached. In that file I am using amplify_auth_cognito: '<1.0.0' for the Cognito login.
I am new to this Flutter so I really need someone help to fix this problem. I have done the AWS Cognito Login features in iOS and web with the same AWS credentials but there I am not getting this type of "Invalid Signature" issue in the access token. Someone, please help me because I am not any good link where this type of issue has been discussed.
Thanks in advance

Related

How to configure authorization for API Gateway for Cognito users?

My project is react native app that uses aws amplify and a rest api through api gateway. i am trying to add an item into my dynamoDB table by calling an API request like so :
const createItemDB = async () => {
API.post("nutritionAPI", "/items", {
body: {
userID: "authenticated user 1 ",
dateID: "1-28-2023",
},
headers: {
Authorization: `Bearer ${(await Auth.currentSession())
.getIdToken()
.getJwtToken()}`,
},
})
};
But this gets the error "request failed with 403 at node_modules\axios\lib\helpers\cookies.js:null in write" Prior to calling createItemDB, i authenticated myself as an "end-user" by Auth.signIn and each time i restart the app, I am still authenticated through my function below
const loadApp = async () =>{
await Auth.currentAuthenticatedUser()
.then(user=>{
console.log("successfully authd" + user)
})
.catch(()=>{
console.log("error signing in")
})
}
So I know i am authenticated. Im new to aws services, and im unsure how to configure the api gateway correctly. the only way to add an item to dynamodb is if I remove the header in my createItemDB call which means any unauthenticated user can add to my dynamodb? I tried to enable CORS inside api gateway but it still doesnt work

Unable to by pass amazon cognito authentication using cypress

I am trying to get login, but login functionality takes place in 'AWS Cognito Authetication', which is making my life little mess.
What happens, when user enters base url on browser, app navigates to 'AWS Cognito' message, where I enter my credentials, after adding credentials, app is showing me an alert message i.e.
An error was encountered with the requested page.
Screenshot is attached. I have checked network logs, but it is showing me that:
{"error":{"name":"UnauthorizedError","message":"No authorization token was found"}}
I need to know , where to start the procedure, I have gone through AWS Cognito Credentials section, but nothing happened yet.
Can someone help me there, how to start and how to work with it?
Cypress documentation has advice on how to authenticate with Cognito.
It could be more complete though, this blog post by Nick Van Hoof offers a more complete solution.
First install aws-amplify and cypress-localstorage-commands libs.
Add a Cypress command like:
import { Amplify, Auth } from 'aws-amplify';
import 'cypress-localstorage-commands';
Amplify.configure({
Auth: {
region: 'your aws region',
userPoolId 'your cognito userPoolId',
userPoolWebClientId: 'your cognito userPoolWebClientId',
},
});
Cypress.Commands.add("signIn", () => {
cy.then(() => Auth.signIn(username, password)).then((cognitoUser) => {
const idToken = cognitoUser.signInUserSession.idToken.jwtToken;
const accessToken = cognitoUser.signInUserSession.accessToken.jwtToken;
const makeKey = (name) => `CognitoIdentityServiceProvider.${cognitoUser.pool.clientId}.${cognitoUser.username}.${name}`;
cy.setLocalStorage(makeKey("accessToken"), accessToken);
cy.setLocalStorage(makeKey("idToken"), idToken);
cy.setLocalStorage(
`CognitoIdentityServiceProvider.${cognitoUser.pool.clientId}.LastAuthUser`,
cognitoUser.username
);
});
cy.saveLocalStorage();
});
Then your test:
describe("Example test", () => {
before(() => {
cy.signIn();
});
after(() => {
cy.clearLocalStorageSnapshot();
cy.clearLocalStorage();
});
beforeEach(() => {
cy.restoreLocalStorage();
});
afterEach(() => {
cy.saveLocalStorage();
});
it("should be logged in", () => {
cy.visit("/");
// ...
});
});

Unable to fetch a valid error code when AWS Cognito authentication fails

I am using AWS Cognito for Authentication using user pools and I have all my APIs configured on the API gateway. I directly hit cognito from the Angular client, store the tokens returned by Cognito in local storage and use them in subsequent calls.
The problem however is, if the token I send from Angular has expired the Cognito authentication fails and no Integration backend is hit in this case. As a result, I am getting a 401 error in Chrome.
The interesting thing however is that this 401 code is not available to me in the HTTP response object that is passed to Angular. A default 0 code is received by the Angular and this seems to be the case with all the error code received from server (either cognito or backend).
I tried to explore around and found that the issue might be because the gateway is not sending proper CORS headers in the error cases. I have read following related docs but unfortunately I couldn't find out a way to resolve the issue.
Can someone suggest a solution to this.
Edit: I also read somewhere that it is a known AWS issue. Is that the case ?
You can manage the Cognito session before making the call to the API Gateway.
In the example below, the getSession method has a callback that prints out any error messages to the console, and returns.
////// Cognito.js
import {
CognitoUserPool,
CookieStorage
} from 'amazon-cognito-identity-js'
import config from '../config'
const cookieSettings = {
domain: '.xxxxxxxxxxx.com',
secure: true
}
export default {
cookieSettings,
pool: new CognitoUserPool({
UserPoolId: config.UserPoolId,
ClientId: config.ClientId,
Storage: new CookieStorage(cookieSettings)
})
}
//////
////// actions.js
import Cognito from './Cognito'
export function fetchUser() {
// get cognito user cookies
const cognitoUser = Cognito.pool.getCurrentUser()
if (cognitoUser != null) {
// try to get session from cognito
cognitoUser.getSession(function(err, session) {
if (err) {
console.log(err)
return;
}
fetch('https://api-gateway-url', {
headers: {
Authorization: 'Bearer ' + session.getAccessToken().getJwtToken(),
}
})
.then(response => response.json())
.then(json => console.log(json))
})
}
}

AWS Amplify - Disable Current User Account

AWS Amplify Authentication module has some methods for actions like sign in, sign up, forgot password etc. Even one can let the user to update his/her info through like:
import { Auth } from 'aws-amplify'
// Auth API Sign-in sample
Auth.signIn(username, password)
.then(user => console.log(user))
.catch(err => console.log(err))
// Auth API Change info sample
let result = await Auth.updateUserAttributes(user, {
'email': 'me#anotherdomain.com',
'family_name': 'Lastname'
})
However, I could not see anyway to disable (beware, not to delete) an account.
So, a user can sign up to a web application, but cannot deactivate it using AWS Amplify? If not, are there any other ways for disabling an AWS Cognito User Pool user via Javascript code?
I went through the AWS Documentation for the Cognito User Pools API and found some methods that let a function with admin privileges disable(not delete) a Cognito User Pool account!
Here is the link to the documentation on the AWS website:
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDisableUser.html
There is also a method to reenable the user:
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminEnableUser.html
The javascript implementation for this can be found here:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#adminDisableUser-property
The code would be something like this using the AWS SDK for JS:
var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18'});
var params = {
UserPoolId: 'STRING_VALUE', /* required */
Username: 'STRING_VALUE' /* required */
};
cognitoidentityserviceprovider.adminDisableUser(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});

How to subscribe AWS SNS Topic in React Native (Android)?

I tried with the aws-sdk-react-native module:
https://github.com/awslabs/aws-sdk-react-native
The configuration took some time, but thanks to this links I could i.e. list the topics:
https://github.com/awslabs/aws-sdk-react-native/issues/35
https://github.com/awslabs/aws-sdk-react-native/blob/master/SNS/IntegrationTests/SNSTests.js
The test includes a sample how to subscribe to get emails but not how to get notifications in the app. I don't know how to get the platformEndpoint, the PlatformApplicationArn and the deviceToken.
endPoint = sns.createPlatformEndpoint({
PlatformApplicationArn: '{APPLICATION_ARN}',
Token: '{DEVICE_TOKEN}'
})
...
var subscribeRequest= {
"Protocol":"application",
"TopicArn":topicARN,
"Endpoint":endPoint
}
try{
await AWSSNS.Subscribe(subscribeRequest);
}catch(e){
console.error(e);
shouldResolve = false;
return shouldResolve;
}
Are there any samples for this?
I'm also looking for an authentication sample.
Would it be easier to use firebase?
Thanks
I have used GCM over SNS to send notifications. Here are the steps I went through assuming you already set up GCM and added required libraries from AWS React Native SDK:
First create a SNS app from AWS:
Then you need to create Federated Identity through Cognito service of AWS. This is required for sending your device token from mobile app to AWS SNS app. Choose Manage Federated Identities
Then create your pool, don't forget to check Enable Access to unauthenticated identities
When you create the pool you will need to create IAM Roles for unauthenticated and authenticated roles of that pool. AWS will help you create new roles for that but you need to go to IAM Roles menu and attach AmazonSNSFullAccess to created roles, otherwise from the mobile app you won't able to send device token.
After doing these steps you will able send your device token using Amazon's React Native SDK. I have written a helper class for sending token to AWS SNS as suggested here:
class AWSUtility {
constructor() {
const region = "us-west-1"; //change it with your region
const IDENTITY_POOL_ID = "pool id created from Federated Identities"
AWSCognitoCredentials.initWithOptions({region, identity_pool_id: IDENTITY_POOL_ID});
AWSSNS.initWithOptions({region});
}
addTokenToAWSSNS(token, snsEndpointARN) {
const applicationArn = "change with SNS application Amazon resource name";
return Promise.try(() => {
if (!snsEndpointARN) {
return this.createPlatformEndpoint(token, applicationArn);
} else {
return AWSSNS.GetEndpointAttributes({EndpointArn: snsEndpointARN})
.then((result) => {
const {Attributes = {}} = result;
const {Token, Enabled} = Attributes;
const updateNeeded = Token !== token || Enabled !== 'true';
if (updateNeeded) {
return this.updateEndpoint(token).then(() => result.EndpointArn);
}
return snsEndpointARN;
})
.catch(() => {
this.createPlatformEndpoint(token, applicationArn)
});
}
});
}
updateEndpoint(snsEndpointARN, token) {
//AWS is returning error saying that it requires 6 params to update endpoint, if anyone has any idea about it let me know please
return AWSSNS.SetEndpointAttributes({EndpointArn: snsEndpointARN, Attributes: {Token: token, Enabled: true}});
}
createPlatformEndpoint(token, applicationArn) {
return AWSSNS.CreatePlatformEndpoint({Token: token, PlatformApplicationArn: applicationArn})
.then(result => result.EndpointArn)
.catch((error = {}) => {
console.log(error);
});
}
}
export default new AWSUtility();