I'm looking for some improvements and recommendations for the AmazonS3 presignedURL with Cognito. I've noticed that sometimes the expiration date expires sooner than set. This causes the error "Unexpected response code 400".
MainActivity.java
// Amazon S3
private AmazonS3 amazonS3;
public AmazonS3 getAmazonS3() {
return amazonS3;
}
public void setAmazonS3(AmazonS3 amazonS3) {
this.amazonS3 = amazonS3;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
// AWS
RunnableAWSS3 runnableAWSS3 = new RunnableAWSS3(activity);
Thread thread = new Thread(runnableAWSS3);
thread.start();
thread.join();
// Getting the JSON data stored in S3 bucket
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, runnableAWSS3.getPresignedURL(), null, response -> {
...
});
}
RunnableAWSS3.java
public class RunnableAWSS3 implements Runnable {
private final ActivityMain activityMain;
private URL presignedURL;
public RunnableAWSS3(#NonNull Activity activity) {
activityMain = (ActivityMain) activity;
}
#Override
public void run() {
if (activityMain.getAmazonS3() == null) {
// AWS
// Initialize the Amazon Cognito credentials provider
CognitoCachingCredentialsProvider cognitoCachingCredentialsProvider = new CognitoCachingCredentialsProvider(
activityMain,
"us-east-1:xxxxxxxxxxxxxxxxxxxxxxxxx",
Regions.US_EAST_1
);
activityMain.setAmazonS3(new AmazonS3Client(cognitoCachingCredentialsProvider, Region.getRegion(Regions.US_EAST_1)));
}
// Set the presigned URL to expire after twelve hours.
presignedURL = activityMain.getAmazonS3().generatePresignedUrl(
"xxxxxxxxxxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
new Date(System.currentTimeMillis() + 43200000));
}
public String getPresignedURL() {
return presignedURL.toString();
}
}
Sometimes I'm getting an error E/Volley: [200] NetworkUtility.shouldRetryException: Unexpected response code 400 for ... when getting the presigned URL.
I would appreciate some recommendations for the improvements.
Presigned URLs have restricted expiration time based on how they were signed. For temporary credentials like with cognito it will have a much smaller expiration time than if it was signed using IAM credentials. Your presigned urls expire as soon as the session for the cognito user expires.
https://aws.amazon.com/premiumsupport/knowledge-center/presigned-url-s3-bucket-expiration/
Related
I am trying to my app connect with mqtt broker using cognito credentials provider. When I was trying to connect to mqtt broker..app saying identity poolId not found.
CognitoUserSession cognitoUserSession = AppHelper.getCurrSession();
String idToken = cognitoUserSession.getIdToken().getJWTToken();
Map<String,String> logins = new HashMap<String, String>();
logins.put("cognito-idp.ap-south-1.amazonaws.com/XXXX_XXXX", idToken);
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
getApplicationContext(),
"ap-south-1:XXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX", // Identity pool ID
Regions.AP_SOUTH_1 // Region
);
credentialsProvider.setLogins(logins);
AmazonCognitoIdentity cognitoIdentity = new AmazonCognitoIdentityClient(credentialsProvider);
GetIdRequest getIdReq = new GetIdRequest();
getIdReq.setLogins(logins); //or if you have already set provider logins just use credentialsProvider.getLogins()
getIdReq.setIdentityPoolId(credentialsProvider.getIdentityPoolId());
GetIdResult getIdRes = cognitoIdentity.getId(getIdReq);
AttachPrincipalPolicyRequest attachPolicyReq = new AttachPrincipalPolicyRequest(); //in docs it called AttachPolicyRequest but it`s wrong
attachPolicyReq.setPolicyName(AWS_IOT_POLICY_NAME); //name of your IOTAWS policy
attachPolicyReq.setPrincipal(getIdRes.getIdentityId());
new AWSIotClient(credentialsProvider).attachPrincipalPolicy(attachPolicyReq);
mqttManager.connect(credentialsProvider, new AWSIotMqttClientStatusCallback() {
#Override
public void onStatusChanged(final AWSIotMqttClientStatus status, Throwable throwable) {
runOnUiThread(new Runnable() {
#Override
public void run() {
txtStatus.setText(status.toString());
}
});
}
});
}catch(final AmazonClientException e){
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"exception : "+e,Toast.LENGTH_LONG).show();
}
});
Log.d(LOG_TAG,"Exception : "+e);
}
Log file:
com.amazonaws.services.cognitoidentity.model.ResourceNotFoundException: IdentityPool 'ap-south-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX' not found. (Service: AmazonCognitoIdentity; Status Code: 400; Error Code: ResourceNotFoundException; Request ID: bdd3c355-79b0-48f3-8a18-716fa17c44ce)
Can any one guide me how to resolve this one. What was the wrong in my code.
Thanks in
Advance.
As your log shows, you did not set the Cognito Identity Pool ID and the Region (where your Identity pool is) in your android app. You can find them under sample code of your identity pool in AWS federated identity dashboard.
I am developing an android app which uses firebase authentication for signin and uses AWS S3 and dynamodb for managing data/images. I am trying to delegate an access to AWS resource via AWSAssumeRoleWebIdentity. The reason I am doing this is AWS Sign-In UI does not allow enough customization for UI and UI flow. I decided to use firebase authentication only for sign-in and sign-up.
Please find the source code and OIDC Provider setting. With them the error log is
No OpenIDConnect provider found in your account for https://securetoken.google.com/[project-name] (Service: AWSSecurityTokenService; Status Code: 400; Error Code: InvalidIdentityToken; Request ID: 37607060-9e1c-11e8-8ae0-636eae27c3bf)
Identity Provider of AWS IAM has been created with the name of "securetoken.google.com/[my-project-name]/" with the Thumbprint that I created referring to [1] and OAuth 2.0 client IDs obtained in Credentials of Google Cloud Service API & Services.
The source code is shown below.
public void uploadImageFile() {
CustomLog.logI("start of uploadImageFile");
setIDToken();
}
private void setIDToken() {
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
// To get ID Token of the user authenticated by google authentication
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete (#NonNull Task< GetTokenResult > task) {
if (task.isSuccessful()) {
// Token information is set to mIDToken of the global variable
mIDToken = task.getResult().getToken();
AsyncTaskForAssumeRole asyncTaskForAssumeRole = new AsyncTaskForAssumeRole();
asyncTaskForAssumeRole.execute();
} else {
CustomLog.logE(task.getException().getMessage());
}
}
});
}
public class AsyncTaskForAssumeRole extends AsyncTask<Void, Void, BasicSessionCredentials> {
protected BasicSessionCredentials doInBackground(Void... params) {
try {
// set credentials from AssumeRoleWithWebIdentity
BasicSessionCredentials credentials = setAssumeRoleWithWebIdentity();
return credentials;
} catch (Exception e) {
CustomLog.logE(e.getMessage());
return null;
}
}
protected void onPostExecute(BasicSessionCredentials credentials) {
// upload file with S3 connection
connectToS3ForUpload(credentials);
}
}
private BasicSessionCredentials setAssumeRoleWithWebIdentity(){
CustomLog.logD("start of setAssumeRoleWithWebIdentity");
String ROLE_ARN = [my role arn];
// set AssumeRoleWithWebIdentity request with created policy and token information retrieved through Google Sign in information
AssumeRoleWithWebIdentityRequest request = new AssumeRoleWithWebIdentityRequest()
.withWebIdentityToken(mIDToken)
.withRoleArn(ROLE_ARN)
.withRoleSessionName("wifsession");
BasicAWSCredentials basicCreds = new BasicAWSCredentials("", "");
AWSSecurityTokenServiceClient sts = new AWSSecurityTokenServiceClient(basicCreds);
AssumeRoleWithWebIdentityResult result = sts.assumeRoleWithWebIdentity(request);
Credentials stsCredentials = result.getCredentials();
String subjectFromWIF = result.getSubjectFromWebIdentityToken();
BasicSessionCredentials credentials = new BasicSessionCredentials(stsCredentials.getAccessKeyId(),
stsCredentials.getSecretAccessKey(),
stsCredentials.getSessionToken());
return credentials;
}
Great thanks in advance.
[1] http://docs.aws.amazon.com/cli/latest/reference/iam/create-open-id-connect-provider.html
Consider using Amazon Cognito Federated Identities (Identity Pools) to federate (map) the user from your Identity Provider into Amazon Cognito and obtain a Cognito Identity Id, which can be used to authorize access to AWS resources. See https://docs.aws.amazon.com/cognito/latest/developerguide/open-id.html for further details.
Map<String, String> logins = new HashMap<String, String>();
logins.put("login.provider.com", token);
credentialsProvider.setLogins(logins);
Now, you can use the credentialsProvider object with an Amazon S3 client.
AmazonS3 s3Client = new AmazonS3Client(getApplicationContext(), credentialsProvider);
I am trying to use 'Authenticate using Cognito-Identity with Cognito user pool' in my Android application. My Cognito user pool authentication works well, when I run that separately and I had seen a JWTToken as well. When I run the the 'PubSub' sample application with Unauthenticated role, it worked as expected. When I integrate these two features in one application, the application threw following error.
W/System.err: MqttException (0) - java.io.IOException: Already connected
W/System.err: at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)
W/System.err: at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:664)
W/System.err: at java.lang.Thread.run(Thread.java:761)
W/System.err: Caused by: java.io.IOException: Already connected
W/System.err: at java.io.PipedOutputStream.connect(PipedOutputStream.java:100)
W/System.err: at java.io.PipedInputStream.connect(PipedInputStream.java:195)
W/System.err: at org.eclipse.paho.client.mqttv3.internal.websocket.WebSocketReceiver.<init>(WebSocketReceiver.java:42)
W/System.err: at org.eclipse.paho.client.mqttv3.internal.websocket.WebSocketSecureNetworkModule.start(WebSocketSecureNetworkModule.java:78)
W/System.err: at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:650)
W/System.err: ... 1 more
I have been trying to resolve this issue since last Thursday and still stuck at the same place. Really No idea where should i check.!
I am adding my Authentication(Cognito user pool authentication) activity and Connect activity.
AmazonCognitoIdentityProviderClient identityProviderClient = new
AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), new ClientConfiguration());
identityProviderClient.setRegion(Region.getRegion(Regions.US_WEST_2));
CognitoUserPool userPool = new CognitoUserPool(getApplicationContext(), "us-west-2_ghtcc6ho9", "4t0mk45hNso69dp2j4jvel5ghm", "1jmq0lhhq721oif9k6nug31c29i760vihua8hvrgu5umfr2a1vd7", identityProviderClient);
cogUser = userPool.getUser();
authenticationHandler = new AuthenticationHandler() {
#Override
public void onSuccess(CognitoUserSession userSession, CognitoDevice newDevice) {
String ids = userSession.getIdToken().getJWTToken();
Log.d("MyToken","session id___"+userSession.getIdToken().getExpiration()+"___"+userSession.getIdToken().getIssuedAt());
Intent pubSub = new Intent(MainActivity.this, PubSubActivity.class);
pubSub.putExtra("token",""+ids);
startActivity(pubSub);
//MainActivity.this.finish();
}
#Override
public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String userId) {
Log.d("MyToken","getAuthenticationDetails");
AuthenticationDetails authenticationDetails = new AuthenticationDetails("shone", "172737", null);
authenticationContinuation.setAuthenticationDetails(authenticationDetails);
// Allow the sign-in to continue
authenticationContinuation.continueTask();
}
#Override
public void getMFACode(MultiFactorAuthenticationContinuation multiFactorAuthenticationContinuation) {
Log.d("MyToken","getMFACode");
multiFactorAuthenticationContinuation.continueTask();
}
#Override
public void authenticationChallenge(ChallengeContinuation continuation) {
Log.d("MyToken","authenticationChallenge"+continuation.getChallengeName());
newPasswordContinuation.continueTask();
}
#Override
public void onFailure(Exception exception) {
exception.printStackTrace();
Log.d("MyToken","onFailure");
}
};
cogUser.getSessionInBackground(authenticationHandler);
When It reaches 'OnSuccess' I am launching my connect activity and passing my session token along with the Intent. Moving to the next activity
private static final String COGNITO_POOL_ID = "us-west-2:a153a090-508c-44c0-a9dd-efd450298c4b";
private static final Regions MY_REGION = Regions.US_WEST_2;
AWSIotMqttManager mqttManager;
String clientId;
AWSCredentials awsCredentials;
CognitoCachingCredentialsProvider credentialsProvider;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = getIntent();
if(null == intent){
Toast.makeText(getApplicationContext(), "Token is null", Toast.LENGTH_SHORT).show();
}else {
token = intent.getStringExtra("token");
}
clientId = UUID.randomUUID().toString();
credentialsProvider = new CognitoCachingCredentialsProvider(
getApplicationContext(),
COGNITO_POOL_ID,
MY_REGION
);
mqttManager = new AWSIotMqttManager(clientId, CUSTOMER_SPECIFIC_ENDPOINT);
Map loginsMap = new HashMap();
loginsMap.put("cognito-idp.us-west-2.amazonaws.com/us-west-2_ghtcc6ho9", token);
credentialsProvider.setLogins(loginsMap);
Log.d("SESSION_ID", ""+token);
new Thread(new Runnable() {
#Override
public void run() {
credentialsProvider.refresh();
awsCredentials = credentialsProvider.getCredentials();
Log.d("SESSION_ID B: ", ""+awsCredentials.getAWSAccessKeyId());
Log.d("SESSION_ID C: ", ""+awsCredentials.getAWSSecretKey());
}
}).start();
}
View.OnClickListener connectClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(LOG_TAG, "clientId = " + clientId);
try {
mqttManager.connect(credentialsProvider, new AWSIotMqttClientStatusCallback() {
#Override
public void onStatusChanged(final AWSIotMqttClientStatus status,
final Throwable throwable) {
Log.d(LOG_TAG, "Status = " + String.valueOf(status)+"______"+((null !=throwable)?throwable.getMessage():""));
runOnUiThread(new Runnable() {
#Override
public void run() {
if (status == AWSIotMqttClientStatus.Connecting) {
tvStatus.setText("Connecting...");
} else if (status == AWSIotMqttClientStatus.Connected) {
tvStatus.setText("Connected");
} else if (status == AWSIotMqttClientStatus.Reconnecting) {
if (throwable != null) {
Log.e(LOG_TAG, "Connection error.", throwable);
}
tvStatus.setText("Reconnecting");
} else if (status == AWSIotMqttClientStatus.ConnectionLost) {
if (throwable != null) {
Log.e(LOG_TAG, "Connection error.", throwable);
throwable.printStackTrace();
}
tvStatus.setText("Disconnected");
} else {
tvStatus.setText("Disconnected");
}
}
});
}
});
} catch (final Exception e) {
Log.e(LOG_TAG, "Connection error.", e);
}
}
};
What is wrong in my code? Why it throws exception when the MQTT connect is being invoked? Any help would be appreciated.
I beat my head up with this almost a week.
Full course of action ->
After succesfull login you will have a jwt token
String idToken = cognitoUserSession.getIdToken().getJWTToken();
put it into a map
Map<String, String> logins = new HashMap<String, String>();
//fill it with Cognito User token
logins.put("cognito-idp.<REGION>.amazonaws.com/<COGNITO_USER_POOL_ID>", idToken);
then use it to set in two places (not stated in any documentation!)
CognitoCachingCredentialsProvider credentialsProvider = new
CognitoCachingCredentialsProvider(context, IDENTITY_POOL_ID, REGION);
credentialsProvider.setLogins(logins);
and
AmazonCognitoIdentity cognitoIdentity = new AmazonCognitoIdentityClient(credentialsProvider);
GetIdRequest getIdReq = new GetIdRequest();
getIdReq.setLogins(logins); //or if you have already set provider logins just use credentialsProvider.getLogins()
getIdReq.setIdentityPoolId(COGNITO_POOL_ID);
GetIdResult getIdRes = cognitoIdentity.getId(getIdReq);
after that you still nedd to make some call
AttachPrincipalPolicyRequest attachPolicyReq = new AttachPrincipalPolicyRequest(); //in docs it called AttachPolicyRequest but it`s wrong
attachPolicyReq.setPolicyName("allAllowed"); //name of your IOTAWS policy
attachPolicyReq.setPrincipal(getIdRes.getIdentityId());
new AWSIotClient(credentialsProvider).attachPrincipalPolicy(attachPolicyReq);
and only after that you can enable connect button and continue like that
mqttManager.connect(credentialsProvider, new AWSIotMqttClientStatusCallback() {
Really for this small piece of code i spent a lot of time...
I was also getting same error -
Feb 27, 2019 10:23:09 AM com.amazonaws.services.iot.client.mqtt.AwsIotMqttConnectionListener onFailure
WARNING: Connect request failure
MqttException (0) - java.io.IOException: Already connected
at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)
at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:664)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: Already connected
at java.io.PipedOutputStream.connect(PipedOutputStream.java:100)
but the problem was different.
First of all, you do not need to call attachPrincipalPolicy from code. You can use the command line as well. You can do something like -
aws iot attach-principal-policy --principal us-east-1:1c973d17-98e6-4df6-86bf-d5cedc1fbc0d --policy-name "thingpolicy" --region us-east-1 --profile osfg
You will get the principal ID from identity browser of your identity pool. Now lets come to the error -
To successfully connect to mqtt with authenticated Cognito credentials, you need 2 correct policies -
Authenticated role corresponding to your identity pool should allow all mqtt operations.
AWS IoT policy should allow the same operations and you need to associate your cognito identity with this policy. We use attachPrincipalPolicy to do so.
If anyone step is missed we get above error. I agree the error is misleading - Already connected makes no sense to me for this. I would normally think it has to do with clientId, which should be unique. But anyways hopefully AWS folks would make this better at some point.
For my particular case issue was point 1. Though my IoT policy had all the required permissions, the auth role corresponding to the identity pool did not. So make sure you do that.
I have created a youtube video to show this as well: https://www.youtube.com/watch?v=j2KJVHGHaFc
When a client connected to broker it has a unique client ID. If clients tried to connect with same client id then this error occur. Use different client IDs like foo1, foo2, foo3, etc.
I use retrofit2 in my android apps for any http/rest call. Now I need to call an api generated with Amazon AWS API Gateway.
The AWS documentation say I should generate the client code throw the API Gateway console and use the class ApiClientFactory to build the request:
ApiClientFactory factory = new ApiClientFactory();
// Use CognitoCachingCredentialsProvider to provide AWS credentials
// for the ApiClientFactory
AWSCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
context, // activity context
"identityPoolId", // Cognito identity pool id
Regions.US_EAST_1 // region of Cognito identity pool
};
factory.credentialsProvider(credentialsProvider);
// Create an instance of your SDK (this should come from the generated code).
final MyApiClient client = factory.build(MyApiClient.class);
// Invoke a method (e.g., 'parentPath1Get(param1,body)') exposed by your SDK.
// Here the method's return type is OriginalModel.
OriginalModel output = client.parentPath1Get(param1,body);
// You also have access to your API's models.
OriginalModel myModel = new OriginalModel();
myModel.setStreetAddress(streetAddress);
myModel.setCity(city);
myModel.setState(state);
myModel.setStreetNumber(streetNumber);
myModel.setNested(nested);
myModel.setPoBox(poBox);
Instead I would like to define the API like I would with retrofit: with an interface I write, connect it to RxJava, OkHttp etc...
My question is: how can I sign the retrofit requests with Cognito Identity Provider?
It took me several days to figure out how to make it work. Don't know why they don't point out the class instead of dozen of document pages. There are 4 steps in total, you must call in worker thread, I am using Rxjava but you can use AsyncTask instead:
Observable.create((Observable.OnSubscribe<String>) subscriber -> {
//Step 1: Get credential, ask server team for Identity pool id and regions
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
this, // Context
"Identity Pool ID", // Identity Pool ID
Regions.US_EAST_1 // Region
);
//Step 2: Get these 3 three keys, test with postman v4.9.3 to see if identity is correct
String identityId = credentialsProvider.getIdentityId();
Log.show("identityId = " + identityId);
String AccessKey = credentialsProvider.getCredentials().getAWSAccessKeyId();
String SecretKey = credentialsProvider.getCredentials().getAWSSecretKey();
String SessionKey = credentialsProvider.getCredentials().getSessionToken();
Log.show("AccessKey = " + AccessKey);
Log.show("SecretKey = " + SecretKey);
Log.show("SessionKey = " + SessionKey);
//Step 3: Create an aws requets and sign by using AWS4Signer class
AmazonWebServiceRequest amazonWebServiceRequest = new AmazonWebServiceRequest() {
};
ClientConfiguration clientConfiguration = new ClientConfiguration();
String API_GATEWAY_SERVICE_NAME = "execute-api";
Request request = new DefaultRequest(amazonWebServiceRequest,API_GATEWAY_SERVICE_NAME);
request.setEndpoint(URI.create("YOUR_URI"));
request.setHttpMethod(HttpMethodName.GET);
AWS4Signer signer = new AWS4Signer();
signer.setServiceName(API_GATEWAY_SERVICE_NAME);
signer.setRegionName(Region.getRegion(Regions.US_EAST_1).getName());
signer.sign(request, credentialsProvider.getCredentials());
Log.show("Request header " + request.getHeaders().toString());
//Step 4: Create new request with authorization headers
OkHttpClient httpClient = new OkHttpClient();
Map<String, String> headers = request.getHeaders();
List<String> key = new ArrayList<String>();
List<String> value = new ArrayList<String>();
for (Map.Entry<String, String> entry : headers.entrySet())
{
key.add(entry.getKey());
value.add(entry.getValue());
}
try {
okhttp3.Request request2 = new okhttp3.Request.Builder()
.url("Your_url") // remember to add / to the end of the url, otherwise the signature will be different
.addHeader(key.get(0), value.get(0))
.addHeader(key.get(1), value.get(1))
.addHeader(key.get(2), value.get(2))
.addHeader(key.get(3), value.get(3))
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.build();
Response response = null;
response = httpClient.newCall(request2).execute();
String body = response.body().string();
Log.show("response " + body);
} catch (Exception e) {
Log.show("error " + e);
}
subscriber.onNext(identityId);
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<String>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
Log.show("Throwable = " + e.getMessage());
}
#Override
public void onNext(String s) {
}
});
The key here is the AWS4Signer class does 4 steps as documented here, you don't need to build one from scratch. In order to use AWS4Signer and AmazonWebServiceRequest, you need to import aws sdk in gradle:
compile 'com.amazonaws:aws-android-sdk-cognito:2.3.9'
Created an OkHttp interceptor based on #thanhbinh84 answer. Give it a try: https://github.com/Ghedeon/AwsInterceptor
The signature process is documented here: http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
But you could probably try to reuse some of the code from the core runtime package that the default API Gateway client depends on. There may be libraries out there already for signing requests of type RxJava or OkHttp since the signature process is well-known.
Having an issue using Cognito and API Gateway to access our REST API's
I can't for the life of me find a simple example of how to call a secured REST api on our AWS server.
I call
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
ProfileViewActivity.this, // get the context for the current activity
AMAZON_COGNITO_IDENTITY_POOL_ID, // your identity pool id
Regions.US_EAST_1 //Region
);
and then try to make a call to our server which is a part of that POOL. I keep getting back "Forbidden".
What should I do with credentialsProvider in the headers of the HttpURLConnection ?
UPDATED:
Ok using the APIGateWay the right way with the AWS Generated SDK however unsure how to change the generated file:
private class MyAsyncTask extends AsyncTask<String, Void, String> {
private TextView textView;
public MyAsyncTask() {
}
#Override
protected String doInBackground(String... strings) {
AWSCredentialsProvider credenetialsProvider = new CognitoCachingCredentialsProvider(
ProfileViewActivity.this, // activity context
AMAZON_COGNITO_IDENTITY_POOL_ID, // Cognito identity pool id
Regions.US_EAST_1 // region of Cognito identity pool
);
ApiClientFactory factory = new ApiClientFactory()
.credentialsProvider(credenetialsProvider)
.region("us-east-1")
.endpoint("https://myendpoint")
.apiKey("xxxxxxxxxxxxxxxxxxxxxxx");
// MyClient is the AWS Android SDK Generated class
final MyClient client = factory.build(MyClient.class);
client.feedGet();
String str = client.testGet().toString();
Log.d("###", "here after test" +client.testGet().toString());
return "DONE";
}
#Override
protected void onPostExecute(String temp) {
Log.d("####", "onPostExecute");
}
}
and then
private class MyAsyncTask extends AsyncTask<String, Void, String> {
private TextView textView;
public MyAsyncTask() {
}
#Override
protected String doInBackground(String... strings) {
AWSCredentialsProvider credenetialsProvider = new CognitoCachingCredentialsProvider(
ProfileViewActivity.this, // activity context
AMAZON_COGNITO_IDENTITY_POOL_ID, // Cognito identity pool id
Regions.US_EAST_1 // region of Cognito identity pool
);
ApiClientFactory factory = new ApiClientFactory()
.credentialsProvider(credenetialsProvider)
.region("us-east-1")
.endpoint("https://myendpoint")
.apiKey("xxxxxxxxxxxxxxxxxxxxxxx");
// MyClient is the AWS Android SDK Generated class
final MyClient client = factory.build(MyClient.class);
client.feedGet();
String str = client.testGet().toString();
Log.d("###", "here after test" +client.testGet().toString());
return "DONE";
}
#Override
protected void onPostExecute(String temp) {
Log.d("####", "onPostExecute");
}
}
========= MyClient.java - AWS Android SDK Generated File
#com.amazonaws.mobileconnectors.apigateway.annotation.Service(endpoint = https:myaws_server)
public interface MyClient {
#com.amazonaws.mobileconnectors.apigateway.annotation.Operation(path = \"/test\", method = "GET")
Empty testGet();
If you are using AWS API Gateway, you can use it independently without using AWS Cognito. AWS API Gateway is a http service just like a proxy to your server or a Gateway to your AWS Lambda Function.
aws api gateway