Update Status in Twitter via twitter4j Library - 401 Authontication Credentials... error - android

Hi I am trying to implement "status update" via twitter4j library.
However it am always getting the same error:
401:Authentication credentials (https://dev.twitter.com/pages/auth)
were missing or incorrect.
Ensure that you have set valid consumer key/secret, access token/secret, and the system clock in in sync.
TwitterException{exceptionCode=[6b80c41c-1bd1da85], statusCode=401,
retryAfter=-1, rateLimitStatus=null,
featureSpecificRateLimitStatus=null, version=2.2.5-SNAPSHOT(build:
5f9c44cd0e0c1972f8d17653a226b9b6a3392ac2)}
...
Below you can find the code piece:
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey(cons_key)
.setOAuthConsumerSecret(cons_secret)
.setOAuthAccessToken(acc_token)
.setOAuthAccessTokenSecret(acc_secret);
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();
twitter4j.Status status;
try {
status = twitter.updateStatus(params[0]);
if (status.getId() == 0) {
System.out.println("Error occured while posting tweets to twitter");
}
} catch (TwitterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I am pretty sure about I have the valid consumer/access tokens/secrets.
I don't know how to sync the system clock.
Do you have an idea what is the actual problem behind this error? I couldn't find any useful answer on internet.
Any help would be appreciated..
Thanks in advance!

You can try few things -
Regenerate the authentication keys for your registered app by logging in to https://apps.twitter.com.
Also ensure your registered application has Read/Write access to be able to post an status update.
I am not sure about clock sync on android, but for linux/Windows you can check
which NTP server to point your system to.
Also use latest version of twitter4j.

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?

Consume WebAPI2 site from Android client with Google Authentication

I've been wracking my brain these past two days to try and understand how to use the authentication built into ASP.NET's WebAPI 2 using Google as an external authentication, and not being familiar with OAuth 2, I'm quite lost. I have followed this tutorial to set up the sign-in button on my Android client and send the "idToken" to the Web API. I've also followed this (now out of date) tutorial on setting up Google as an external login.
The problem happens when I try to send it I get {"error":"unsupported_grant_type"} as a response. Some other tutorials lead me to believe that the POST to mysite.com/token does not contain the correct data. This means I'm either building the request incorrectlyon the client, I'm somehow handling it incorrectly on the backend, I'm sending it to the wrong url, or I'm doing something entirely else wrong.
I found this SO answer which says to get a URL from /api/Accounts/ExternalLogins, but the sign-in button already gives me the access token that would supply to me (if I understand that correctly).
If someone could help me out here on what the exact process should be from start to finish, that would be amazing.
UPDATE: Okay, so here are some things that I've learned since I asked this question.
website.com/token URI is the redirect for the built in OAuth server in the WebAPI2 template. This is not useful for this particular problem.
The id_token is an encoded JWT token.
The website.com/signin-google URI is the redirect for normal Google login, but does not accept these tokens.
I may have to write my own AuthenticationFilter that uses the Google Client library to authorize through the Google API.
UPDATE 2: I'm still working on getting this AuthenticationFilter Implementation. Things seem to be going well at this point, but I'm getting stuck on some things. I've been using this example to get the token verification code, and this tutorial to get the AuthenticationFilter code. The result is a mix of both of them. I'll post it here as an answer once it's complete.
Here are my current problems:
Producing an IPrincipal as output. The verification example makes a ClaimPrincipal, but the AuthenticationFilter example code uses a UserManager to match the username to an existing user and returns that principal. The ClaimsPrincipal as created in the verification example directly does not auto-associate with the existing user, so I need to attempt to match some element of the claims to an existing user. So how do I do that?
I still have an incomplete idea of what a proper flow for this is. I'm currently using the Authentication header to pass my id_token string using a custom scheme: "goog_id_token". The client must send their id_token for every method called on the API with this custom AuthenticationFilter. I have no idea how this would usually be done in a professional environment. It seems like a common enough use case that there would be tons of information about it, but I haven't seen it. I have seen the normal OAuth2 flow, and since I'm only using an ID Token, and not an Access Token I'm a bit lost on what an ID Token is supposed to be used for, where it falls in a flow, and where it's supposed to live in an HTTP packet. And because I didn't know these things, I've kind of been making it up as I go along.
Wow, I did it. I figured it out. I... I can't believe it.
As metioned in my question Update 2, this code is assembled from Google's official API C# example and Microsoft's Custom AuthenticationFilter tutorial and code example. I'm going to paste the AuthorizeAsync() here and go over what each block of code does. If you think you see an issue, please feel free to mention it.
public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
bool token_valid = false;
HttpRequestMessage request = context.Request;
// 1. Look for credentials in the request
//Trace.TraceInformation(request.ToString());
string idToken = request.Headers.Authorization.Parameter.ToString();
The client adds the Authorization header field with the scheme followed by a single space, followed by the id token. It looks something like Authorization: id-token-goog IaMS0m3.Tok3nteXt.... Putting the ID token in the body as given in the google documentation made no sense in this filter so I decided to put it in the header. For some reason it was difficult to pull custom headers from the HTTP packets so I just decided to use the Authorization header with a custom scheme followed by the ID token.
// 2. If there are no credentials, do nothing.
if (idToken == null)
{
Trace.TraceInformation("No credentials.");
return;
}
// 3. If there are credentials, but the filter does not recognize
// the authentication scheme, do nothing.
if (request.Headers.Authorization.Scheme != "id-token-goog")
// Replace this with a more succinct Scheme title.
{
Trace.TraceInformation("Bad scheme.");
return;
}
This whole point of a filter is to ignore requests that the filter doesn't govern (unfamiliar auth schemes, etc), and make judgement on requests that it's supposed to govern. Allow valid authentication to pass to the downstream AuthorizeFilter or directly to the Controller.
I made up the scheme "id-token-goog" because I had no idea if there was an existing scheme for this use case. If there is, somebody please let me know and I'll fix it. I guess it doesn't particularly matter at the moment as long as my clients all know the scheme.
// 4. If there are credentials that the filter understands, try to validate them.
if (idToken != null)
{
JwtSecurityToken token = new JwtSecurityToken(idToken);
JwtSecurityTokenHandler jsth = new JwtSecurityTokenHandler();
// Configure validation
Byte[][] certBytes = getCertBytes();
Dictionary<String, X509Certificate2> certificates =
new Dictionary<String, X509Certificate2>();
for (int i = 0; i < certBytes.Length; i++)
{
X509Certificate2 certificate =
new X509Certificate2(certBytes[i]);
certificates.Add(certificate.Thumbprint, certificate);
}
{
// Set up token validation
TokenValidationParameters tvp = new TokenValidationParameters()
{
ValidateActor = false, // check the profile ID
ValidateAudience =
(CLIENT_ID != ConfigurationManager
.AppSettings["GoogClientID"]), // check the client ID
ValidAudience = CLIENT_ID,
ValidateIssuer = true, // check token came from Google
ValidIssuer = "accounts.google.com",
ValidateIssuerSigningKey = true,
RequireSignedTokens = true,
CertificateValidator = X509CertificateValidator.None,
IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
{
return identifier.Select(x =>
{
// TODO: Consider returning null here if you have case sensitive JWTs.
/*if (!certificates.ContainsKey(x.Id))
{
return new X509SecurityKey(certificates[x.Id]);
}*/
if (certificates.ContainsKey(x.Id.ToUpper()))
{
return new X509SecurityKey(certificates[x.Id.ToUpper()]);
}
return null;
}).First(x => x != null);
},
ValidateLifetime = true,
RequireExpirationTime = true,
ClockSkew = TimeSpan.FromHours(13)
};
This is all unchanged from the Google example. I have almost no idea what it does. This basically does some magic in creating a JWTSecurityToken, a parsed, decoded version of the token string, and sets up the validation parameters. I'm not sure why the bottom portion of this section is in it's own statement block, but it has something to do with the CLIENT_ID and that comparison. I'm not sure when or why the value of CLIENT_ID would ever change, but apparently it's necessary...
try
{
// Validate using the provider
SecurityToken validatedToken;
ClaimsPrincipal cp = jsth.ValidateToken(idToken, tvp, out validatedToken);
if (cp != null)
{
cancellationToken.ThrowIfCancellationRequested();
ApplicationUserManager um =
context
.Request
.GetOwinContext()
.GetUserManager<ApplicationUserManager>();
Get the user manager from the OWIN context. I had to dig around in context intellisense until I found GetOwinCOntext(), and then found that I had to add using Microsoft.Aspnet.Identity.Owin; in order to add the partial class that included the method GetUserManager<>().
ApplicationUser au =
await um
.FindAsync(
new UserLoginInfo(
"Google",
token.Subject)
);
This was the very last thing I had to fix. Again, I had to dig through um Intellisense to find all of the Find functions and their overrides. I had noticed from the Identity Framework-created tables in my database that there is one called UserLogin, whose rows contain a provider, a provider key, and a user FK. The FindAsync() takes a UserLoginInfo object, which contains only a provider string and a provider key. I had a hunch that these two things were now related. I had also recalled that there was a field in the token format that included a key-looking field that was a long number that started with a 1.
validatedToken seems to be basically empty, not null, but an empty SecurityToken. This is why I use token instead of validatedToken. I'm thinking there must be something wrong with this, but since the cp is not null, which is a valid check for a failed validation, it makes enough sense that the original token is valid.
// If there is no user with those credentials, return
if (au == null)
{
return;
}
ClaimsIdentity identity =
await um
.ClaimsIdentityFactory
.CreateAsync(um, au, "Google");
context.Principal = new ClaimsPrincipal(identity);
token_valid = true;
Here I have to create a new ClaimsPrincipal since the one created above in validation is empty (apparently that's correct). Took a guess on what the third parameter of CreateAsync() should be. It seems to work that way.
}
}
catch (Exception e)
{
// Multiple certificates are tested.
if (token_valid != true)
{
Trace.TraceInformation("Invalid ID Token.");
context.ErrorResult =
new AuthenticationFailureResult(
"Invalid ID Token.", request);
}
if (e.Message.IndexOf("The token is expired") > 0)
{
// TODO: Check current time in the exception for clock skew.
Trace.TraceInformation("The token is expired.");
context.ErrorResult =
new AuthenticationFailureResult(
"Token is expired.", request);
}
Trace.TraceError("Error occurred: " + e.ToString());
}
}
}
}
The rest is just exception catching.
Thanks for checking this out. Hopefully you can look at my sources and see which components came from which codebase.

No authentication challenges found

I tried to use
try {
new TwitterFactory(new ConfigurationBuilder()
.setOAuthConsumerKey(TWITTER_KEY)
.setOAuthConsumerSecret(TWITTER_SECRET)
.setOAuthAccessToken(TWITTER_TOKEN)
.setOAuthAccessTokenSecret(TWITTER_TOKEN_SECRET)
.build()).getInstance().updateStatus("HELLO WORLD!");
} catch (TwitterException e) {
e.printStackTrace();
}
But as soon as I run it, it gives me this error:
this might be a possible answer: In order to get access acquire AccessToken using xAuth, you must apply by sending an email to api#twitter.com — all other applications will receive an HTTP 401 error. from here but his answer is not complete (does not have steps to follow)
How to fix this? Thanks!

Show last and early tweet with Twitter API android

hello i just learn API Twitter in android. At the start of my application, is shows 20 tweets with this URL
https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=name&count=20
I want to display the last 20 before 20 tweets that have been shown (with load endless) and all new tweet after tweet earlier 20 (with pull to refresh). but i don't know how the URL or method to get 20 last or newest tweet . how it's work ? sorry for my english.
You need this page: https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline found on this well documented page (https://dev.twitter.com/docs/api/1.1)
The URI you likely want though is:
https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=name&count=20&max_id=[lowest-id-from-last-batch]
If you're on Android I recommend using the Twitter4J library for easy Twitter API calls and response handling.
With use of Paging you can get the next 20 tweets (using Paging.page) or new tweets (using id's or time/since).
Code example for getting a Users timeline using Twitter4J in Android:
// Use as field
Twitter twitter;
// Get timeline
try {
if(twitter==null) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(Constants.DEBUG)
.setOAuthConsumerKey("YOUR CONSUMER KEY")
.setOAuthConsumerSecret("YOUR CONSUMER SECRET")
.setApplicationOnlyAuthEnabled(true)
.setHttpConnectionTimeout(5000)
.setHttpReadTimeout(5000)
.setHttpStreamingReadTimeout(5000);
twitter = new TwitterFactory(cb.build()).getInstance();
twitter.getOAuth2Token();
}
return twitter.getUserTimeline("TwitterName", twitterPaging);
} catch (Exception e) {
e.printStackTrace();
}

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