Using gitskarios/GithubAndroidSdk - android

I'm trying to use the gitskarios/GithubAndroidSdk to provide my alpha and beta testers a way to view current github issues and report new ones. Here are the steps I've already taken:
Create a GitHub application at LINK.
Add the client info to my application's metadata:
com.alorma.github.sdk.client -> my client's ID
com.alorma.github.sdk.secret -> my client's secret
com.alorma.github.sdk.oauth -> my client's 'Authorization callback URL'
Run this code in my fragment's onCreate:
GithubDeveloperCredentials.init(new MetaDeveloperCredentialsProvider(mParent));
UserReposClient client = new UserReposClient(getActivity(), null);
client.setOnResultCallback(new BaseClient.OnResultCallback<List<Repo>>() {
#Override
public void onResponseOk(List<Repo> repos, Response response) {
Log.d("GitHub", "onResponseOK: " + response);
}
#Override
public void onFail(RetrofitError retrofitError) {
Log.d("GitHub", "onFail: " + retrofitError);
}
});
Log.d("GitHub", "getting repos");
client.execute();
The result is a single log for "getting repos" and no callback.
I've tried removing the call to GithubDeveloperCredentials.init() but that just causes a crash saying that provider is null. I then thought that maybe I didn't have an auth token so I made a call to the RequestTokenClient using null for the second parameter in RequestTokenClient(Context context, String code) but this too never gets a callback or return a null token if executed with executeSync().
UPDATE
I tried using the Personal access tokens (see comments) page to generate an access token then save it into StoreCredentials. When running the execute() command now it appears to be getting a little further but now I'm getting a new error saying:
retrofit.RetrofitError: LoginService.requestToken: HTTP method annotation is required (e.g., #GET, #POST, etc.).
Looking around I found an answer (see comments) saying this might be a proguard issue with the retrofit package. So I added those lines into my app's proguard file but no luck yet.
Can anybody help me? All I want to do is get a list of the open issues.

OK, so I got this working finally though not quite in the best way I wanted. I initially intended each of my Alpha testers to require having their own GitHub account and be added to the project then using their own credentials to obtain an auth token and accessing the bug list. Instead, using the auth token I generated in my update I was able to access the repo. I had to change the proguard to:
-keepattributes *Annotation*,Signature
-keep class retrofit.** { *; }
-keepclasseswithmembers class * {
#retrofit.http.* <methods>; }
(For some reason the *Annotation* and Signature nedded to be on the same line)

Related

Deleting a user from Azure Active Directory B2C Android/Java

I have an Android application in which I'm using Azure AD B2C to authenticate users. Users login and logout of the application as needed. I would like to give the user the option to delete their own account.
I understand that I need to use the Azure AD Graph API to delete the user. This is what I have so far:
According to this link, it looks like deleting a user from a personal account (which is what the B2C users are using) is not possible. Is that correct?
Here's my code snippet for the Graph API call. Feel free to ignore it if I'm off track and there is a better way to solve this.
I believe I need a separate access token than what my app currently has (as the graph API requires other API consent). So, I'm getting the access token as follows:
AcquireTokenParameters parameters = new AcquireTokenParameters.Builder()
.startAuthorizationFromActivity(getActivity())
.fromAuthority(B2CConfiguration.getAuthorityFromPolicyName(B2CConfiguration.Policies.get("SignUpSignIn")))
.withScopes(B2CConfiguration.getGraphAPIScopes())
.withPrompt(Prompt.CONSENT)
.withCallback(getGraphAPIAuthCallback())
.build();
taxApp.acquireToken(parameters);
In the getGraphAPIAuthCallback() method, I'm calling the Graph API using a separate thread (in the background):
boolean resp = new DeleteUser().execute(authenticationResult.getAccessToken()).get();
Finally, in my DeleterUser() AsyncTask, I'm doing the following:
#Override
protected Boolean doInBackground(String... aToken) {
final String asToken = aToken[0];
//this method will be running on background thread so don't update UI from here
//do your long running http tasks here,you dont want to pass argument and u can access the parent class' variable url over here
IAuthenticationProvider mAuthenticationProvider = new IAuthenticationProvider() {
#Override
public void authenticateRequest(final IHttpRequest request) {
request.addHeader("Authorization",
"Bearer " + asToken);
}
};
final IClientConfig mClientConfig = DefaultClientConfig
.createWithAuthenticationProvider(mAuthenticationProvider);
final IGraphServiceClient graphClient = new GraphServiceClient.Builder()
.fromConfig(mClientConfig)
.buildClient();
try {
graphClient.getMe().buildRequest().delete();
} catch (Exception e) {
Log.d(AccountSettingFragment.class.toString(), "Error deleting user. Error Details: " + e.getStackTrace());
}
return true;
}
Currently, my app fails when trying to get an access token with a null pointer exception:
com.microsoft.identity.client.exception.MsalClientException: Attempt to invoke virtual method 'long java.lang.Long.longValue()' on a null object reference
Any idea what I need to do to provide the user the option to users to delete their own account? Thank you!
Thanks for the help, #allen-wu. Due to his help, this azure feedback request and this azure doc, I was able to figure out how to get and delete users silently (without needing intervention).
As #allen-wu stated, you cannot have a user delete itself. So, I decided to have the mobile app call my server-side NodeJS API when the user clicks the 'Delete Account' button (as I do not want to store the client secret in the android app) and have the NodeJS API call the Azure AD endpoint to delete the user silently. The one caveat is that admin consent is needed the first time you try to auth. Also, I have only tested this for Graph API. I'm not a 100% sure if it works for other APIs as well.
Here are the steps:
Create your application in your AAD B2C tenant. Create a client secret and give it the following API permissions: Directory.ReadWrite.All ;
AuditLog.Read.All (I'm not a 100% sure if we need the AuditLog permission. I haven't tested without it yet).
In a browser, paste the following link:
GET https://login.microsoftonline.com/{tenant}/adminconsent?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&state=12345
&redirect_uri=http://localhost/myapp/permissions
Login using an existing admin account and provide the consent to the app.
Once you've given admin consent, you do not have to repeat steps 1-3 again. Next, make the following call to get an access token:
POST https://login.microsoftonline.com/{B2c_tenant_name}.onmicrosoft.com/oauth2/v2.0/token
In the body, include your client_id, client_secret, grant_type (the value for which should be client_credentials) and scope (value should be 'https://graph.microsoft.com/.default')
Finally, you can call the Graph API to manage your users, including deleting them:
DELETE https://graph.microsoft.com/v1.0/users/{upn}
Don't forget to include the access token in the header. I noticed that in Postman, the graph api had a bug and returned an error if I include the word 'Bearer' at the start of the Authorization header. Try without it and it works. I haven't tried it in my NodeJS API yet, so, can't comment on it so far.
#allen-wu also suggested using the ROPC flow, which I have not tried yet, so, cannot compare the two approaches.
I hope this helps!
There is a line of code: graphClient.getUsers("").buildRequest().delete();
It seems that you didn't put the user object id in it.
However, we can ignore this problem because Microsoft Graph doesn't allow a user to delete itself.
Here is the error when I try to do it.
{
"error": {
"code": "Request_BadRequest",
"message": "The principal performing this request cannot delete itself.",
"innerError": {
"request-id": "8f44118f-0e49-431f-a0a0-80bdd954a7f0",
"date": "2020-06-04T06:41:14"
}
}
}

Error while migrating to latest Google Drive API in Android - Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup

An application is published on Play Store and it is using 'application data folder' for the backup-restore purpose using Drive API. Everything works fine. However, this API is about to be turned down on 6th December, 2019 according to Google's announcement. Therefore, in order to support existing users, I have been migrating to latest API according to migration guidlines and an official sample app.
I can successfully authenticate using the code (from the official link) below.
GoogleSignInOptions signInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestScopes(new Scope(DriveScopes.DRIVE_APPDATA))
.build();
GoogleSignInClient client = GoogleSignIn.getClient(this, signInOptions);
// The result of the sign-in Intent is handled in onActivityResult.
startActivityForResult(client.getSignInIntent(), REQUEST_CODE_SIGN_IN);
I am also using correct scope - DriveScopes.DRIVE_APPDATA as mentioned in the official documentation.
I am also seeing correct values of 'email' and 'granted scopes' inside onActivityResult()
if (requestCode == REQUEST_CODE_SIGN_IN && resultCode == RESULT_OK) {
GoogleSignIn.getSignedInAccountFromIntent(data).addOnSuccessListener(new OnSuccessListener<GoogleSignInAccount>() {
#Override
public void onSuccess(GoogleSignInAccount googleSignInAccount) {
Log.e("TAG", "Email - " + googleSignInAccount.getEmail()); // prints correct value
Log.e("TAG", "Granted scopes - " + googleSignInAccount.getGrantedScopes()); // prints correct value
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(getActivity(), Collections.singleton(DriveScopes.DRIVE_APPDATA));
credential.setSelectedAccount(googleSignInAccount.getAccount());
Drive googleDriveService = new Drive.Builder(
AndroidHttp.newCompatibleTransport(),
new GsonFactory(),
credential)
.setApplicationName("App Name") // Changed it for now
.build();
mDriveServiceHelper = new DriveServiceHelper(googleDriveService);
queryFiles();
}
});
}
However, whenever I try to access a backup file in queryFiles() using the code (from the official link) below,
FileList files = driveService.files().list()
.setSpaces("appDataFolder")
.setFields("nextPageToken, files(id, name)")
.setPageSize(10)
.execute();
for (File file : files.getFiles()) {
System.out.printf("Found file: %s (%s)\n",
file.getName(), file.getId());
}
It throws the following error
{
"errors": [
{
"domain": "usageLimits",
"reason": "dailyLimitExceededUnreg",
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.",
"extendedHelp": "https://code.google.com/apis/console"
}
],
"code": 403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
}
Kindly help me fix the error. I believe that as everything is working fine with the published version, everything should be correct in terms of configuring on Google API console.
I probably can't find ALL threads with this problem but I can try to help in a few or so.
PRIMARY ANSWER
IF you're using ProGuard same as I am. ProGuard can cause this error to happen during query. I fixed it using the following.
# Fix OAuth Drive API failure for release builds
-keep class * extends com.google.api.client.json.GenericJson { *; }
-keep class com.google.api.services.drive.** { *; }
-keepclassmembers class * { #com.google.api.client.util.Key <fields>; }
SECONDARY ANSWER
Note that you DO NOT need to use keys/tokens using the Drive rest API with Android like you may find from other solutions (it may not hurt either, but it can). It doesn't match up here to what people talk about elsewhere (here they don't know what they're talking about).
See my notes here for further info: Google Drive via OAuth release version receives dailyLimitExceededUnreg
IF you have the problem however in debug build then you did not do everything correctly. My notes should get you on the right track.
If you need further help, I might assist because of how nuts it is.
EXAMPLE OF GETTING A FILE FROM DRIVE WITH THE NEW API USE
Just see from the following link
public Task<Pair<String, String>> readFile(String fileId)
https://github.com/gsuitedevs/android-samples/blob/master/drive/deprecation/app/src/main/java/com/google/android/gms/drive/sample/driveapimigration/DriveServiceHelper.java
The id comes from the query result where the id is part of that query info attached to that which is returned from the Drive query. The id is the file id for the file you want to retrieve. Pass that in to readFile and it gives you the file contents back that you can save locally to java.io.File eg fileOutputStream.write(contents.getBytes()); the contents of which is pair.second. You would then have your hopefully (because sometimes we have more work to do) identical java.io.File.
You can see a basic query if you need one in the the link sample as well but its missing some important info because depending on what you do you may need to check if trashed, get file size, modify time, md5, set order, etc. You may need to see https://developers.google.com/drive/api/v2/reference/files/list and https://developers.google.com/drive/api/v3/reference/files etc to figure that out. If enough files, there will be a paged requirement as well.
I know using Drive from code is a bit nuts (well, it is to me anyway lol) so hang in there =)
For Documentation purposes as a troubleshooting step:
Go to
https://console.developers.google.com/project/<project-id>/apiui/api
Or for Google Scripts:
https://script.google.com/home/usersettings
Replace with the ID of your application and check that the Google Drive API is turned on.
If it isn't - make sure to get a new token after turning it on if this is the case.

"Invalid state" on vimeo video upload from other android app

I am trying the upload videos into vimeo from my android application. The video is getting uploaded . But when the Delete request is called in order to get the video id , I am getting a response as "Invalid state". The same piece of code works in Htc X. Is this the issue with video codec format or something else ?
This is my piece of code for delete request
public void vimeoDelete() {
// Vimeo upload step 3
RestClient.mEndPoint.setUrl(APIHandler.VIMEO_BASE_URL);
RestClient.getVimeo().deleteVideo(mCompleteUri.substring(1), new Callback<Response>() {
#Override
public void success(Response response, Response response2) {
Log.i("Delete", "Done");
Log.i("Header", response2.getHeaders().toString());
Log.i("Body", response2.getBody().toString());
List<Header> aHeaders = response2.getHeaders();
for (Header aHeader : aHeaders) {
if (aHeader.getName().equals("Location")) {
mVideoUrlLocation = aHeader.getValue();
}
}
Log.i("Location", mVideoUrlLocation);
mFinalVideoUrl = mVideoUrlLocation.substring(8);
saveDetails();
}
#Override
public void failure(RetrofitError error) {
mProgress.dismiss();
}
});
}
Can anyone suggest a solution to this .
Regards
I just replied to the same issue over on the Vimeo forum - I had the same issue and am simply posting it here as there didn't seem to be a solution on this particular thread.
Also, regarding your post - there's not a lot of information provided in your post. Your delete request is not all that's required - the assumption would be that you created a valid ticket request, uploaded properly, THEN tried the del request you posted.
Vimeo post:
https://vimeo.com/forums/api/topic:278394
My solution:
I solved my version of the issue - I think Vimeo corrected some stuff on their API recently because my code did not have a bug and then suddenly one appeared recently. I would bet they added rate limiting on their API gateway or potentially overwriting existing requests to clean up old requests...
Anyhow, here is my fix:
In order to complete a video upload via "Resumable HTTP PUT uploads" (developer.vimeo.com/api/upload/videos), there are 5 steps.
I do everything but the upload through my PHP backend. I was requesting a ticket through PHP as to not expose some secret info through my modified JS frontend (github.com/websemantics/vimeo-upload) but I had not edited out the ticket request properly through the JS code, so the current bug was probably being triggered on that second invalid request (i.e. overwriting or rate limiting my initial valid request through PHP). Once I bypassed the JS "upload" function properly and jumped right to JS "sendFile_", the upload works properly again.
Hope that helps somebody out there!

Robospice caching when exception occured

I wan't to achieve next.
Depends on json content deside put or not to put data to Robospice Cache.
Sometimes data returned from the server is not valid. For example our authorization token goes off time. So we shouldn't cache this response.
But i can't find API which can help me to solve this trouble.
Here is how i am using requests now:
getSpiceManager().execute(getRequestCreator().getAllCategories(), getRequestCreator().getLastCacheKey(),
DurationInMillis.ONE_MINUTE * 120, new JSONCategoryListener(mCategories));
So the actual response is normal (status 200), but json content is telling me about exception.
So, what you want to get? It is right behavior for server. Server returns 200, means that request is successful. But it not guarantee, that wasn't some internal error of 'business logic' on server, such as not valid data or anything else.
EDITED
May be you can use your custom error handler:
class MyErrorHandler implements ErrorHandler {
#Override public Throwable handleError(RetrofitError cause) {
//check response on errors
}
}
And in createRestAdapterBuilder():
new RestAdapter.Builder()..setErrorHandler(new MyErrorHandler());
EDITED 2
You can implement in your robospice service method putDataInCache(Object cacheKey, T data), and in your listener check errors in content, and if no error then add it to cache, or remove it from cache

Empty json data in Release build (using proguard)

My app doesn't post data to server when I run the release version (signed, Proguard packed). But if I run it directly from ADT, I see the data on the server.
It's weird because it just the same code, one is signed and the other is direct execution. Here is the Code (using org.springframework.web.client.RestTemplate):
private static String URL = "https://myappserver.com/abcservice/";
public ResponseEntity<String> sendMessage(UserMessage us) {
private RestTemplate template = getTemplate();
HttpEntity<UserMessage> reqEntity = new HttpEntity<UserMessage>(us, headers);
ResponseEntity<String> result =
template.postForEntity(URL, reqEntity, String.class);
return result;
}
Below are the 2 scenarios:
Case 1: Works Good
Run the App directly from ADT (Run as: Android Application)
User taps a button, which will invoke sendMessage(..) method.
Controller (on Server) gets the request and the data (UserMessage).
An entry with UserMessage is created.
Server send a 201 response (request has been fulfilled), to the app.
Case 2: PROBLEM
Pack the app (Android Tools -> Export Signed Application Package..)
Install it on device through command line (adb install xxx.apk)
Start the app.
User taps a button, which will invoke sendMessage(..) method.
Controller (on Server) gets the request but no data.
An entry with empty UserMessage is created.
Server send a 201 response (request has been fulfilled), to the app.
I have tried to log both on my device and web server, I can confirm that empty data is received for Case 2, and I'm not able to figure out why it doesn't send data when I pack it?
Does packed/released (Signed +Proguard) apps behave differently, compared to debug packaging?
I guess that it is caused by proguard. Proguard is probably obfuscating some portion of your code, but this code is dynamically invoked by Spring (and jackson ? you didn't mention it). (and so once it is obfuscate : dynamic invocation failed)
So try to :
disable proguard to confirm that it is the cause of the problem
if it is confirmed : try to configure it so hat it won't obfuscate class that are serialized in json (i.e. UserMessage) :
-keep class com.company.UserMessage** { *; }
I have same issue, and I committed below 2 line
// shrinkResources true
// minifyEnabled true
The above answer didnt work for me may be it was correct on 2014
For 2019 when I set the compileSdkVersion 28 it works.

Categories

Resources