I am working on developer authenticated project.And I am trying to get credentials using this below code.But it is giving me following error.
I have pasted IdentityId and Token manually into this code from server code:
Caused by: com.amazonaws.services.cognitoidentity.model.ResourceNotFoundException: Identity 'ap-northeast-1:fe81cd76-e9d4-4416-99ea-b684b78743c8' not found. (Service: AmazonCognitoIdentity; Status Code: 400; Error Code: ResourceNotFoundException; Request ID: 2ac65fe8-d41a-11e5-8674-677eefdb5331)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:709)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:385)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:196)
at com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient.invoke(AmazonCognitoIdentityClient.java:533)
at com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient.getCredentialsForIdentity(AmazonCognitoIdentityClient.java:406)
at com.example.sandesh.aws.MainActivity$network.doInBackground(MainActivity.java:101)
at com.example.sandesh.aws.MainActivity$network.doInBackground(MainActivity.java:52)
at android.os.AsyncTask$2.call(AsyncTask.java:292)
Here is my code: MainActivity.java
public class MainActivity extends AppCompatActivity {
Button button;
protected static CognitoCachingCredentialsProvider credentialsProvider = null;
private GetCredentialsForIdentityResult credentialsForIdentityResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
network net = new network();
net.execute();
}
});
}
public class network extends AsyncTask<Void,Void,String>{
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
Authentication developerProvider = new Authentication(
null,
"ap-northeast-1:XXXXXXXXXXXXXXXXXX",
Regions.AP_NORTHEAST_1);
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
getApplicationContext(),
developerProvider,
Regions.AP_NORTHEAST_1);
HashMap<String, String> loginsMap = new HashMap<String, String>();
loginsMap.put(developerProvider.getProviderName(), "7386372772");
credentialsProvider.setLogins(loginsMap);
credentialsProvider.refresh();
GetCredentialsForIdentityRequest credentialsForIdentityRequest = new GetCredentialsForIdentityRequest();
credentialsForIdentityRequest.setIdentityId(developerProvider.getIdentityId());
credentialsForIdentityRequest.setLogins(loginsMap);
AmazonCognitoIdentityClient cognitoIdentityClient = new AmazonCognitoIdentityClient(credentialsProvider);
credentialsForIdentityResult = cognitoIdentityClient.getCredentialsForIdentity(credentialsForIdentityRequest);
Log.d("access_key",credentialsForIdentityResult.getCredentials().getAccessKeyId());
return credentialsForIdentityResult.getCredentials().getAccessKeyId();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}}
Authentication.java
public class Authentication extends AWSAbstractCognitoDeveloperIdentityProvider {
private static final String PROVIDERNAME = "login.blupinch.app";
public String response = " ";
String line = " ";
public Authentication(String accountId, String identityPoolId, Regions region) {
super(accountId, identityPoolId, region);
}
#Override
public String getProviderName() {
return PROVIDERNAME;
}
public String refresh() {
setToken(null);
if (getProviderName() != null &&
!this.loginsMap.isEmpty() &&
this.loginsMap.containsKey(getProviderName())) {
update(identityId, token);
return "eyJraWQiOiJhcC1ub3J0aGVhc3QtMTEiLCJ0eXAiOiJKV1MiLCJhbGciOiJSUzUxMiJ9.eyJzdWIiOiJhcC1ub3J0aGVhc3QtMTpmZTgxY2Q3Ni1lOWQ0LTQ0MTYtOTllYS1iNjg0Yjc4NzQzYzgiLCJhdWQiOiJhcC1ub3J0aGVhc3QtMTphODcxZmE1Zi0yM2EyLTQ4MGQtYmFhNi1iNGVkMzE0MzcyNDQilCJhbXIiOlsiYXV0aGVudGljYXRlZCIsImxvZ2luLmJsdXBpbmNoLmFwcCIsImxvZ2luLmJsdXBpbmNoLmFwcDphcC1ub3J0aGVhc3QtMTphODcxZmE1Zi0yM2EyLTQ4MGQtYmFhNi1iNGVkMzE0MzcyNDQ6NzM4NjM3Mjg3MiJdLCJpc3MiOiJodHRwczovL2NvZ25pdG8taWRlbnRpdHkuYW1hem9uYXdzLmNvbSIsImV4cCI6MTQ1NTU5NTM5NywiaWF0IjoxNDU1NTU5Mzk3fQ.fHHH6aeCn5EaJGxGD6tw7bWyQpPHuYcW8SZLRGVn-3cbamJrWEPmUnNvcLJ-D6nL8AvMQy7-s1LGQ5MNaiuIH7QF6W8aWt2OMALmA_Y7eqpGQ6iQXVma_jTZSpiyBe2cPNggWgeslPtFxomwE90vW0rzS1sY3D5Y3UbnrIHNdiPKIzzP9JaQo1IsTJMKEpQM-jzWP6stV1radDuIzWQroBVQseOQSD-MXV_-cgWWSx0eQmtFbjJW6RP_nACgh0uTbGmMuOi2iKXKQAdGlYWO-PHlShbiHT-WLQoZNWuh95Hh9dMldv-mNdnYSblqYyqptLA3kObioI08XXkTqwaaAw";
} else {
this.getIdentityId();
return null;
}
}
public String getIdentityId() {
identityId = "ap-northeast-1:XXXXXXXXXXXXXXXXXXXXXXXX";
if (identityId == null) {
if (getProviderName() != null && !this.loginsMap.isEmpty()
&& this.loginsMap.containsKey(getProviderName())) {
update(identityId, token);
return "ap-northeast-1:XXXXXXXXXXXXXXXXXXXX";
} else {
return super.getIdentityId();
}
} else {
return identityId;
}
}}
I have tried it in PHP where I performed getOpenIdTokenForDeveloperIdentity , stsClient and AssumerolewithWebIdentity to get credentials it worked great. Thank you in advance.
When using Developer Authenticated Identities, the logins map for the call GetCredentialsForIdentity should have "cognito-identity.amazonaws.com" as the key instead of developer provider name.
Also, you should not be calling this method yourself, the SDK will take care of this.
Update:
When calling getCredentialsForIdentity, in the logins map, when key is "cognito-identity.amazonaws.com", the value should be the token you got from your backend after calling GetOpenIdTokenForDeveloperIdentity. You do not need to get the credentials for doing AWS operations, just initialize the AWS Service Client with this credentials provider and you should be good to go.
(1) In your application, you do not need to call GetCredentialsForIdentity, the CredentialsProvider does all of this for you. (And ensures the correct arguments are passed in).
--> You can test that you are getting credentials by making a call to another service that requires credentials (ex S3)
--> Another option is to call getCredentials() on the Credentials Provider and validate that an exception is not thrown
(2) In Authentication.java, refresh, you seem to be using a hard coded token? This is likely expired, and you should make sure to get new ones. (If you are just testing app side, make sure you hard code a fresh one).
(3) In Authentication.java, refresh, it looks like you are calling update with a null token.
(4) Also make sure you are getting tokens for the hard coded identity you are using. (Again, you should only be hard coding this if you are testing).
Related
I am currently trying to login to create a login to realm, but I am unable to access a SyncUser because my logInAsync is not entering the onSuccess or onError method. The onSuccess method returns a SyncUser, but this is not occurring. My code is
String authURL = "https://my-realm.us1a.cloud.realm.io";
String email = "testemail#gmail.com";
String password = "testPassword";
SyncCredentials credentials = SyncCredentials.usernamePassword(email, password, true);
RealmAsyncTask task = SyncUser.logInAsync(credentials, authURL, new SyncUser.Callback<SyncUser>() {
#Override
public void onSuccess(SyncUser result) {
user = result;
}
#Override
public void onError(ObjectServerError error) {
System.out.println("failed");
}
});
String url = "realms://unbranded-metal-bacon.us1a.cloud.realm.io/~/travelin";
config = user.createConfiguration(url).build();
I have a private SyncUser user declared above. In the last line, I am getting a null object reference because user is null. What is the reason that I am not entering onSuccess or onError?
Auth URL is wrong, need to be
String authURL = "https://my-realm.us1a.cloud.realm.io/auth";
Also, SyncUser.logInAsync() runs in background so this line need to be inside onSuccess(), otherwise User will be null
config = user.createConfiguration(url).build();
I'm completely new to Google's Cloud Platform and I'm having trouble setting it up for my Android device. I am attempting to follow this tutorial and I'm at the point of trying to test my backend with my Android Emulator. The emulator, however, gives me this message after 20 seconds, Where instead it should say my name. Here's my code so far:
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
buildUI();
new EndpointsAsyncTask().execute(new Pair<Context, String>(this, "Solomon"));
}
EndpointsAsyncTask.java
public class EndpointsAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
private static MyApi myApiService = null;
private Context context;
#Override
protected String doInBackground(Pair<Context, String>... params) {
if(myApiService == null) { // Only do this once
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
// end options for devappserver
myApiService = builder.build();
}
context = params[0].first;
String name = params[0].second;
try {
return myApiService.sayHi(name).execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
}
All Help is appreciated!
EDIT: Part of the problem was that I was running Endpoints Backend rather than the App Engine Servlet Backend. But now I'm now getting "connection refused" and I am running the App Engine Servlet Backend. Any Ideas?
After a tough few days, i found that the problem was that I needed to change my rootUrl from http://10.0.2.2:8080/_ah/api/ to my appspot domain. Now I'm getting the Hello World message.
I have the following code for FitBit integration into Android, it is used from this library https://github.com/manishsri01/FitbitIntegration, I can get the response.getBody() to show the JSON body in the webview but I would like the application to be able to automatically update the code without having to login and grab the PIN for OAuth everytime I run the app. What can I do to fix this? I would also like to parse the JSON .getBody() into separate string variables. How can I accomplish this?
MainActivity
public class MainActivity extends Activity {
OAuthService service;
Token requestToken;
// Replace these with your own api key and secret
private String apiKey = "************************";
private String apiSecret = "*************************";
private String accessToken;
private String tokenSecret;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final WebView wvAuthorize = (WebView) findViewById(R.id.wvAuthorize);
final EditText etPIN = (EditText) findViewById(R.id.etPIN);
service = new ServiceBuilder().provider(FitbitApi.class).apiKey(apiKey)
.apiSecret(apiSecret).build();
// network operation shouldn't run on main thread
new Thread(new Runnable() {
public void run() {
requestToken = service.getRequestToken();
final String authURL = service
.getAuthorizationUrl(requestToken);
// Webview nagivation should run on main thread again...
wvAuthorize.post(new Runnable() {
#Override
public void run() {
wvAuthorize.loadUrl(authURL);
}
});
}
}).start();
}
public void btnRetrieveData(View view) {
EditText etPIN = (EditText) findViewById(R.id.etPIN);
String gotPIN = etPIN.getText().toString();
final Verifier v = new Verifier(gotPIN);
// network operation shouldn't run on main thread
new Thread(new Runnable() {
public void run() {
Token accessToken = service.getAccessToken(requestToken, v);
OAuthRequest request = new OAuthRequest(Verb.GET,
"http://api.fitbit.com/1/user/-/profile.json");
service.signRequest(accessToken, request); // the access token from step
// 4
final Response response = request.send();
final TextView tvOutput = (TextView) findViewById(R.id.tvOutput);
// Visual output should run on main thread again...
tvOutput.post(new Runnable() {
#Override
public void run() {
tvOutput.setText(response.getBody());
}
});
}
}).start();
}
}
FitBitApi
public class FitbitApi extends DefaultApi10a {
private static final String AUTHORIZE_URL = "https://www.fitbit.com/oauth/authorize?oauth_token=%s";
public String getAccessTokenEndpoint() {
return "https://api.fitbit.com/oauth/access_token";
}
public String getRequestTokenEndpoint() {
return "https://api.fitbit.com/oauth/request_token";
}
public String getAuthorizationUrl(Token token) {
return String.format(AUTHORIZE_URL, token.getToken());
}
}
It sounds like you have two separate questions here. Firstly, in regards to saving credentials, there are a number of ways you can do this, the easiest is probably by saving the user/pin details in Android's SharedPreferences. However, you'll still need to make the request for an access token. You should also save the access token (in a cache or DB) and re-use it until it is expired. You may want to read up on ways to secure these credentials if they're considered private.
Your second question regarding parsing JSON is quite common, and if your intention is to map JSON objects to Java objects, you should consider using Google's GSON or Jackson JSON Processor.
If you're intending for Fitbit's API to be a large part of your app, consider using Spring Social and make a Fitbit endpoint (there is a Spring for Android which uses Spring Social). It might be a bit overkill though, but I generally like the structure.
I am currently trying to handle a situation in a demo application I'm writing where I have an expired access token, and I need to use a refresh token to get a new access token. Now for background tasks like this, I'd normally use an AsyncTask like my app currently does for login (which works fine), but I'm not sure how to do this - if it can even be done (I'm sure it can, but I'm just not seeing it right now).
Below is my current flow - the call to get() blocks the UI thread, which isn't what I'm supposed to be doing here. Our access ticket class contains both the access token and refresh token.
public boolean isLoggedIn() {
if (isFreshAccessToken())
return true;
// If the access token is expired, we'll need to use the
// refresh token to get another one. Use a background task
// to do this.
String refreshToken = preferences.getString(REFRESH_TOKEN_KEY, null);
if (StringUtils.isNotBlank(refreshToken)) {
RefreshAccessTokenAsyncTask refreshLogin = new RefreshAccessTokenAsyncTask();
refreshLogin.execute(refreshToken);
try {
return refreshLogin.get();
} catch (Exception e) {
Log.d(TAG, "isLoggedIn() : Exception in async task. Returning false.");
return false;
}
} else
return false;
}
Here is what my AsyncTask implementation currently looks like. The refreshAccessTicket() method simply makes the REST call to get the AccessTicket response.
private class RefreshAccessTokenAsyncTask extends AsyncTask<String, Void, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
String refreshToken = params[0];
try {
// Get a new access token using the refresh token
// in the background ...
AccessTicket accessTicket = refreshAccessTicket(refreshToken);
// ... and save the updated information to the shared
// preferences
saveAccessTicket(accessTicket);
return true;
} catch (Exception ex) {
// If the call for a new access token fails for any reason,
// return FALSE. We'll force the user to log in again to
// get a completely new access ticket.
return false;
}
}
#Override
protected void onPostExecute(Boolean isLoggedIn) {
super.onPostExecute(isLoggedIn);
Log.d(TAG, "RefreshAccessTokenAsyncTask.onPostExecute() : " +
"Returning isLoggedIn value of " + isLoggedIn);
}
}
What am I missing here? As I mentioned above, I want this process to be silent - if the access token has expired, I want to use the refresh token to automatically get a new access token without the user having to do anything or have the app jump out of the current flow (such as getting a friends list, etc.) - it will happen in the background. Should I be using something other than AsyncTask?
AsyncTask should work fine, but you can't get the result like that. Try something like this instead.
private interface Callback {
void done(boolean result);
}
private class RefreshAccessTokenAsyncTask extends AsyncTask<String, Void, Boolean> {
private Callback cb;
private RefreshAccessTokenAsyncTask(Callback callback)
cb = callback;
}
#Override
protected Boolean doInBackground(String... params) {
String refreshToken = params[0];
try {
// Get a new access token using the refresh token
// in the background ...
AccessTicket accessTicket = refreshAccessTicket(refreshToken);
// ... and save the updated information to the shared
// preferences
saveAccessTicket(accessTicket);
return true;
} catch (Exception ex) {
// If the call for a new access token fails for any reason,
// return FALSE. We'll force the user to log in again to
// get a completely new access ticket.
return false;
}
}
#Override
protected void onPostExecute(Boolean isLoggedIn) {
super.onPostExecute(isLoggedIn);
Log.d(TAG, "RefreshAccessTokenAsyncTask.onPostExecute() : " +
"Returning isLoggedIn value of " + isLoggedIn);
cb.done(isLoggedIn);
}
}
Then use the AsyncTask like so:
public boolean isLoggedIn() {
if (isFreshAccessToken())
return true;
// If the access token is expired, we'll need to use the
// refresh token to get another one. Use a background task
// to do this.
String refreshToken = preferences.getString(REFRESH_TOKEN_KEY, null);
if (StringUtils.isNotBlank(refreshToken)) {
Callback callback = new Callback() {
public void done(boolean result){
// whatever you need to do here
}
}
RefreshAccessTokenAsyncTask refreshLogin = new RefreshAccessTokenAsyncTask(callback);
refreshLogin.execute(refreshToken);
} else
return false;
}
I am new to android and java and am trying to setup a login page that posts to a webpage that verifies the credentials and returns a cookie.
I am using the login template included with eclipse. I am not sure what to put for the
// TODO: attempt authentication against a network service.
All I need it so post to my page like this: www.mywebsite.com/login?userid=john&password=test
and if the credentials are correct I get a json success string and cookie back. How can I incorporate this into this template or what do i need to put in place of the authentication against a network service
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
#Override
protected Boolean doInBackground(Void... params) {
// TODO: attempt authentication against a network service.
try {
// Simulate network access.
Thread.sleep(2000);
} catch (InterruptedException e) {
return false;
}
for (String credential : DUMMY_CREDENTIALS) {
String[] pieces = credential.split(":");
if (pieces[0].equals(mEmail)) {
// Account exists, return true if the password matches.
return pieces[1].equals(mPassword);
}
}
// TODO: register the new account here.
return true;
}
#Override
protected void onPostExecute(final Boolean success) {
mAuthTask = null;
showProgress(false);
if (success) {
finish();
} else {
mPasswordView
.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
}
}
#Override
protected void onCancelled() {
mAuthTask = null;
showProgress(false);
}
}
}
edit: I tried searching for an example of this but did not find one that fit my case. Any links to a solution or example of what im trying to do are appreciated.