Get HTTP status code from AWS API Gateway Android SDK - android

I'm trying to use the AWS generated Android SDK for my API Gateway project. Based on the information on this Site I created a client interface with a API method like this:
#com.amazonaws.mobileconnectors.apigateway.annotation.Operation(path = "/events/bookingUpdate", method = "POST")
void bookingUpdatePost(BookingUpdate body);
So when I want to call my API I used the following code:
try {
clientInterface.bookingUpdatePost(generateBookingUpdateDeviceInformation(bookingUpdate));
} catch (ApiClientException e) {
Log.e(BuildConfig.APPLICATION_ID, e.getLocalizedMessage());
if (listener != null) {
listener.onBookingUpdatePostRequestFinished(new Error(e.getLocalizedMessage()));
}
}
is there any way to retrieve the APIResponse Headers from the amazon mobile connectors library?

There isn't a way to do so because it's not exposed externally. But you can use a generic invoker instead to achieve this.

Related

How does Keycloak with Android work using SAML protocol?

I've successfully created a demo in Android using keycloak openid-connect protocol configuration for SSO. Now I want to do with SAML protocol.
Details I used in openid-connect:
client_id
username
password
grant_type
client_secret
Now, when I changed from openid-connect to SAML inside keycloak dashboard, so client-secreted option got invisible.
So, in android I removed that variable, and also changed in URL from openid-connect to SAML. But getting error that Page not found
I seen lot of example, searched and imported github project as well, but wither I'll get demo with openid-connect or I'll get demo without using keyclaok.
I don't understand what else is required.
BTW, I followed this example for openid-connect and it is working as well: https://github.com/thomasdarimont/android-openid-connect/tree/feature/keycloak-oidc-demo
I'll share a bit code:
protected Boolean doInBackground(String... args) {
String authToken = args[0];
IdTokenResponse response;
showLog("Requesting ID token.");
try {
response = OIDCUtils.requestTokens(Config.tokenServerUrl,
Config.redirectUrl,
Config.clientId,
authToken);
} catch (IOException e) {
Log.e(TAG, "Could not get response.");
e.printStackTrace();
return false;
}
if (isNewAccount) {
createAccount(response);
} else {
setTokens(response);
}
return true;
}
Have a look, and there are really less examples on this things. Don't know why!
SAML is primarily for Browser Based Authentication (including Auth-Requests, Redirects, ...). So that's not really suitable for Android apps.
Do you have a good reason to use SAML and not stick to your (already working) OIDC solution?

Authenticating a REST API with Cognito using AWS Amplify & Android

I am currently trying to configure a REST API I added using AWS Amplify. I have already configured user authentication in which users can sign-up and sign-in by following the steps outlined in the authentication docs. I then added a REST API using the api steps.
At the moment, I am just trying to retrieve a list of items from DynamoDB. The api is successful when I test it on the aws console, however, when I make the call from my android api, it returns the following error:
{"message":"Authorization header requires 'Credential' parameter. Authorization header requires 'Signature' parameter. Authorization header requires 'SignedHeaders' parameter. Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header. Authorization=[a long string of characters]
I understand that amplify automatically sets the API to be restricted using AWS_IAM, which I think is why the above message is returned. I am trying to get it to authenticate using the user pools I setup before with the authentication steps. The code in my android that app that makes the call to the API is as follows:
RestOptions options = new RestOptions("/models");
Amplify.API.get("modelsapi", options, new ResultListener<RestResponse>() {
#Override
public void onResult(RestResponse restResponse) {
Log.i(TAG, restResponse.toString());
Log.i(TAG, restResponse.getData().asString());
}
#Override
public void onError(Throwable throwable) {
Log.e(TAG, throwable.toString());
}
});
Do I need to setup a Authorizer on AWS api console? And if so, How do I pass the authorization header with the user token. I have a seen a few responses from people using react native but not with android: AWS-amplify Including the cognito Authorization header in the request
The function which the Api invokes is as follows if needed:
app.get(path, function(req, res) {
let queryParams = {
TableName: tableName
}
dynamodb.scan(queryParams, (err, data) => {
if (err) {
res.statusCode = 500;
res.json({error: 'Could not load items: ' + err});
} else {
res.json(data.Items);
}
});
});
Any points/help would be greatly appreciated! Thanks!
Have figured it out. Even though Amplify is meant to take the credentials automatically when making an API call, it seemed to throw up the unauthorized error anyway. When I tested using the console it worked fine. I had to manually add the authorization header to the Rest options:
RestOptions options = RestOptions.builder()
.addPath("models")
.addHeader("Authorization", token.getTokenString())
.build();

Implementing SSL pinning using Trustkit with Google Cloud Endpoints

I am using Google Cloud Endpoints to interact with the app engine backend for my Android app. I want to implement public key/SSL pinning. It's easy to do this for Android N and above, but i want to implement pinning for earlier versions of Android. It seems like a common way to do this is using Trustkit.
The Getting Started notes on the Trustkit link, describe how to set it up by setting the SSLSocketFactory, for example
// HttpsUrlConnection
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(TrustKit.getInstance().getSSLSocketFactory(serverHostname));
// OkHttp 2.x
OkHttpClient client =
new OkHttpClient()
.setSSLSocketFactory(TrustKit.getInstance().getSSLSocketFactory(serverHostname));
But i'm not sure how to apply this to Google Cloud Endpoints because of the way the connection is set up, for example here's how its set up for Google Cloud Endpoints in my code
import com.xxxx.backend.myApi.MyApi;
//I believe the MyApi class is generated automatically as part of the Google Cloud Endpoints integration in Android Studio.
class EndpointsAsyncTask extends AsyncTask<HashMap, Void, String> {
#Override
protected String doInBackground(HashMap... params) {
HashMap<String, String> dict = params[0];
String data = dict.get("dataString");
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
.setRootUrl("https://xxxxx").setApplicationName("xxxx");
myApiService = builder.build();
//This calls the API method
return myApiService.customApiMethodName(data).execute().getDict().toString();
}
}
What I want to find out is how i can I implement SSL pinning in early versions of Android e.g. API16-API23 while still connecting to Google Cloud Endpoints in the same way my App does as shown above?
If possible i'd like to use Trustkit, maybe there is a different way i can set up how to connect with my Api methods so i can use it? If this is not possible is there an alternative to Trustkit i can use? or just a completely different way to implement SSL pinning while still using Google Cloud Endpoints in this way?
You would have to stop using the AndroidHttp helper and write your own, based off of it.
Instead of just calling new NetHttpTransport() or new ApacheHttpTransport(), you must use their builders instead, for example:
public static HttpTransport newCompatibleTransport(String hostname) {
SSLSocketFactory factory = TrustKit.getInstance().getSSLSocketFactory(serverHostname);
if (AndroidUtils.isMinimumSdkLevel(9)) {
return new NetHttpTransport.Builder()
.setSslSocketFactory(factory)
.build();
}
return new ApacheHttpTransport.Builder()
.setSslSocketFactory(factory)
.build();
}

WebApi: How to call Facebook Graph API by using an access token originated from the OAuth dialog

I have an ASP.NET WebApi 2.1 application with OAuth2 configured. I have and Android client where I can do authentication by using the following methods:
WebView approach (Web Api External Providers): redirect to https://www.facebook.com/dialog/oauth..., user do login there, FB asks for permissions, redirects to my url, catch it, access token got, done.
Facebook SDK approach: under the hood it does: redirect to https://graph.facebook.com/oauth..., user do login there, FB asks for permissions, redirects to my url, catch it, access token got, done.
The problem is, if I go with the WebView version, the token is good for authorizing user in my Web Api application, but I cannot call Graph API by using it, I receive OAuthException 190 (no subcode).
But if I do the SDK authorization, Graph API is accessible (through the Android Facebook SDK), but using the token I've got from it, Web Api authorization is not working, I get 401 by calling Authorization/UserInfo.
So my question are the above token types interchangeable somehow?
Any help would be greatly appreciated.
Sorry if that was not clear, I'm using Web Api w/ ASP.NET Identity 2.0 template, so OAuth plumbing code is already present there.
I was able to find an answer to my own question, let me share it with you.
So the problem is that the token I've got from the Facebook's OAuth dialog after the redirect is not the same token that my application can use to call Facebook Graph APIs in the name of the actual user. That Graph API token is reachable at the following point:
Assume you are using the mentioned template above, you can find App_Data/Startup.Auth.cs class with definition of a FacebookAuthenticationOptions instance. There you can catch the API token and can persist that into the database. For example:
var fbopts = new FacebookAuthenticationOptions
{
AppId = Global.Config.ExternalServices.FacebookAppID,
AppSecret = Global.Config.ExternalServices.FacebookAppSecret,
Scope = { "email", "user_friends", "publish_actions" },
Provider = new FacebookAuthenticationProvider
{
OnAuthenticated = async context =>
{
// This token will be OK for calling Graph API
string accessToken = context.AccessToken;
using (var tracer = Global.Tracer.CreateBuilder())
{
try
{
tracer.InformationLine("Storing Facebook OAuth token: " + accessToken);
string fbUserID = context.Identity.GetUserId();
string fbUserName = context.Identity.Name;
tracer.InformationLine("Facebook User ID: " + fbUserID);
tracer.InformationLine("Facebook User Name: " + fbUserName);
// Store it into the db
// assume Task StoreOAuthToken(string providerName, string providerKey, string accessToken) is defined
await StoreOAuthToken("Facebook", fbUserID, accessToken);
}
catch (Exception ex)
{
tracer.ErrorLine("Failed.", ex);
}
}
}
}
};
app.UseFacebookAuthentication(fbopts);
At this point you're gonna have a row in a table that consists of the following columns:
OAuthAccessToken.ProviderName
OAuthAccessToken.ProviderKey
OAuthAccessToken.AccessToken
Now you can provide an API to your consumers to have that API token for calling Graph API, like:
[Route("AccessTokens")]
[Authorize]
public async Task<List<OAuthAccessToken>> GetAccessTokens(string providerName = null)
{
var userID = User.Identity.GetUserId();
var q = from l in this.Context.AspNetUserLogins // Managed by ASP.NET Identity 2.0
from t in this.Context.OAuthAccessTokens // Stored by you with above code
where l.UserId == userID && t.ProviderName == l.LoginProvider && t.ProviderKey == l.ProviderKey
select t;
if (!string.IsNullOrEmpty(providerName)) q = q.Where(t => t.ProviderName == providerName);
return await q.ToListAsync();
}
So on Android after doing a Facebook login I have the Bearer token for my application's Web Api calls, and I can get my token for accessing Graph API by calling the action above.
Maybe there are easier methods for achieving the above. Please let me know if you find any.

Retrieve Google Docs document list

I managed to get an auth token from the AccountManager on Android for "writely" (Google Docs).
Now I want to get all documents from the user - but I have absolutley no idea how to do this.
There are a lot of libraries out there including the Google-Api-Java-Client but I have no clue how to use them. The picasa sample app also dosent help me... :(
Anyone, any idea?
Document List API V3 is what you can use - For details of using it and what to do with OAuth token etc take a look at here
DocService's JavaDocs
DocsService service = new DocsService("test-docs-service");
service.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer());
try {
DocumentListFeed feed = service.getFeed(new URL("https://docs.google.com/feeds/default/private/full"), DocumentListFeed.class);
if(null != feed || feed.getEntries().size() > 0){
System.out.println("feed size = " +feed.getEntries().size());
for(DocumentListEntry entry : feed.getEntries())
{
System.out.println("filename = "+entry.getTitle().getPlainText());
}
}
else{
System.out.println("feed null OR size <=0");
}
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
There are several sample projects at the Google Code project of google-api-java-client here
Specifically for Android there are Calendar, Picasa and Tasks samples but there is also a Google Docs sample for command line Java. I would think it can be easily ported to Android.

Categories

Resources