Scribe Tumblr Response body is incorrect. Can't extract token and secret from this: 'Missing or invalid oauth_verifier.' - tumblr

I'm having problems with authenticating Tumblr using Scribe. I've followed an example that I found here on SO but I keep getting "org.scribe.exceptions.OAuthException: Response body is incorrect. Can't extract token and secret from this: 'Missing or invalid oauth_verifier.'"
Any ideas? Help would be GREATLY appreciated! Thanks.
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.webkit.WebSettings;
import android.webkit.WebView;
import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.TumblrApi;
import org.scribe.model.*;
import org.scribe.oauth.OAuthService;
public class MyActivity extends Activity {
private static OAuthService service;
private Token requestToken;
private Verifier verifier;
private static final String PROTECTED_RESOURCE_URL = "http://api.tumblr.com/v2/user/info";
private static Boolean authInProgress = false;
public WebView TumblrWebView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
setContentView(R.layout.main);
if ( ! authInProgress ) {
authInProgress = true;
service = new ServiceBuilder()
.provider(TumblrApi.class)
.apiKey("xxx")
.apiSecret("yyy")
.callback("thisapp://tumblr")
.build();
// Obtain the Request Token
Log.d("Tumblr", "Fetching the Request Token...");
requestToken = service.getRequestToken();
Log.d("Tumblr", "Got the Request Token!");
Log.d("Tumblr", "Now go and authorize Scribe here:");
Log.d("Tumblr", ""+service.getAuthorizationUrl(requestToken));
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse( service.getAuthorizationUrl(requestToken) ));
startActivity(browserIntent);
}
}
#Override
protected void onResume() {
super.onResume();
if (this.getIntent()!=null && this.getIntent().getData()!=null){
Uri uri = this.getIntent().getData();
if (uri != null && uri.toString().startsWith("thisapp://tumblr")) {
verifier = new Verifier ( uri.getQueryParameter("oauth_verifier") );
// Trade the Request Token and Verfier for the Access Token
requestToken = service.getRequestToken();
Log.d("Tumblr", "Trading the Request Token for an Access Token...");
Log.d("Tumblr", " ---> Request Token: " + requestToken.getToken());
Log.d("Tumblr", " ---> Request Token Secret: " + requestToken.getSecret());
Log.d("Tumblr", " ---> Verifier: " + verifier.getValue());
Token accessToken = service.getAccessToken(requestToken, verifier);
Log.d("Tumblr", "Got the Access Token!");
Log.d("Tumblr", "(if you're curious it looks like this: " + accessToken + " )");
// Now let's go and ask for a protected resource!
Log.d("Tumblr", "Now we're going to access a protected resource...");
OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
service.signRequest(accessToken, request);
Response response = request.send();
Log.d("Tumblr", "Got it! Lets see what we found...");
Log.d("Tumblr", ""+response.getBody());
Log.d("Tumblr", "Thats it man! Go and build something awesome with Scribe! :)");
}
}
}
}

I was facing the same issue. This was caused because of different request token.
The way Tumblr's OAuth works:
Your application requests for a requestToken and generates AuthorizationUrl.
The user is redirected to tumblrs page for authentication.
Once the user has granted all the permissions, tumblr redirects back to callback URL with oauth_verifier code.
Now you try to generate accessToken based on oauth_verifier and requestToken.
Now here is the twist, you need to make sure that the requestToken is same which was used while getting the URL, else it will throw an error as can't extract token.

Related

How to do the Automation of Rest API With Bearer Token Authentication and Authorization?

I am Trying to Automate the Rest API with Rest Assured and i am doing the Scenario which has Bearer Token Authentication first and Then need to do the Authorization of another URL
I have Tried the Below Code
public class Authentication {
#BeforeTest
public void setUp() {
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
RestAssured.authentication =
preemptive().basic("username", "password");
}
#Test
public void successfulTest() {
String bearerToken = null;
URI url = null;
#SuppressWarnings("unused")
Response response =given.headers
("Authorization", "Bearer " + bearerToken, "Content- Type",ContentType.JSON,"Accept", ContentType.JSON)
.when()
.get(url)
.then()
.contentType(ContentType.JSON)
.extract()
.response();
}
}

Security Attacks possible on TokenBased Authentication?

I have designed a web application which uses very simple implementation of JWT token's to provide Authentication/Authorization.
My Implementation :
There are two types of urls's public and secure.
Public urls are to generate token with username/password.
I have added filter on secure url to check for the Authorization Header and JWT Token.
#Bean
public FilterRegistrationBean jwtFilter()
{
final FilterRegistrationBean registrationBean = new
FilterRegistrationBean();
registrationBean.setFilter(new JwtFilter());
registrationBean.addUrlPatterns("/secure/*");
return registrationBean;
}
Filter will validate the token. I haven't added expiration date yet.
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
final String authHeader = request.getHeader("authorization");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
chain.doFilter(req, res);
} else {
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw new ServletException("Missing or invalid Authorization header");
}
final String token = authHeader.substring(7);
try {
final Claims claims = Jwts.parser().setSigningKey(secretKey.toString).parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
} catch (final SignatureException e) {
throw new ServletException("Invalid token");
}
chain.doFilter(req, res);
}
This is providing authentication and also its is immune to CSRF.No one can create valid token without secret Key.
Are there other attacks possible on token base authentication service which i have missed?

WSO2IS JWT access token

I am trying get a JWT access token from WSO2 IS. I followed instructions from msf4j Oauth2 Security Sample, and managed to get a JWT acces token by resource owner password grant type.
but I have problem authenticating the token externally.
it seems that the token had not been signed by the default "wso2carbon.jks".
also, my claim configurations in the "service providers" was not reflected in jwt content
so my questions: how to config the JWT signing certificate in WSO2IS?
and also:
How to manipulate the claims in the JWT?
I do not want to turn to the "introspect" endpoint out of performance concern, and my strategy is to just trust the IS, only to make sure(locally) of the authenticity of the JWT token
please advise
thanks
You can follow [1] to get JWT Access Tokens(Self contained access tokens) using WSO2 Identity Server
[1] https://medium.com/#hasinthaindrajee/self-contained-access-tokens-with-wso2-identity-server-82111631d5b6
well, it seems to be my own fault.
I had been using the jose4j JWT package, and kept getting verification failed message.
after further checking into the msf4j implementation, I switched over to nimbus-jose-jwt JWT package, and got it done,
below are my implementation.
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
public class JwtParser {
private static final String KEYSTORE = System.getProperty("javax.net.ssl.trustStore");
private static final String KEYSTORE_PASSWORD = System.getProperty("javax.net.ssl.trustStorePassword");
private static Map<String, JWSVerifier> verifiers = getVerifiers();
public static JWTClaimsSet verify(String jwt) throws Exception {
SignedJWT signedJWT = SignedJWT.parse(jwt);
if (!new Date().before(signedJWT.getJWTClaimsSet().getExpirationTime())) {
new Exception("token has expired");
}
boolean notYet = true;
for(Iterator<JWSVerifier> it = verifiers.values().iterator(); notYet && it.hasNext();){
JWSVerifier verifier = it.next();
notYet = !signedJWT.verify(verifier);
}
if(notYet){
throw new Exception("token verification failed");
}
JWTClaimsSet claims = signedJWT.getJWTClaimsSet();
if (claims == null) {
// Do something with claims
throw new Exception("non valid payload in token, failed");
}
return claims;
}
private static Map<String, JWSVerifier> getVerifiers(){
Map<String, JWSVerifier> verifiers = new HashMap<>();
try (InputStream inputStream = new FileInputStream(KEYSTORE)) {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(inputStream, KEYSTORE_PASSWORD.toCharArray());
Enumeration<String> aliases = keystore.aliases();
while(aliases.hasMoreElements()){
String alias = aliases.nextElement();
if(!keystore.isCertificateEntry(alias)){
continue;
}
Certificate cert = keystore.getCertificate(alias);
if(cert == null){
continue;
}
PublicKey key = cert.getPublicKey();
verifiers.put(alias, new RSASSAVerifier((RSAPublicKey)key));
}
}catch(KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e){
//TODO: report the exception
}
return verifiers;
}
}

Box Java SDK Retrieve acces/refresh tokens

I am trying to create a java program that will search for certain files in Box Storage. For this i am trying to use the Box Java SDK and i created an application in Box (https://app.box.com/developers/services).
When i use the developer token i am able to traverse through my box parent/child folders. Since this token is valid for 60 mins i want to programmatically retrieve and set the token. When i looked at the manuals it says to manully call api's to get these tokens.
I tried the below code..
BoxAPIConnection api = new BoxAPIConnection(clientid,clientsecret);
String accesstoken = api.getAccessToken();
String refreshtoken = api.getRefreshToken();
I dont want to throw a box login page to the user and want to run this program as a daemon which will search files and spit out some report text file.
Thanks for all the help.
It is possible to manage Box login through code.
For the first time you access Box.com and get the client id, client secret, access token and refresh token.
Save it in DB or property file.
Use below code, and each and every time update the actual access and refresh token.
String accessToken = // access token from DB/property
String refreshToken = // refresh token from DB/property
String boxClientId = // client id from DB/property
String boxClientSecret = // client secret from DB/property
try {
BoxAPIConnection api = new BoxAPIConnection(boxClientId, boxClientSecret, accessToken, refreshToken);
api.addListener(new BoxAPIConnectionListener() {
#Override
public void onRefresh(BoxAPIConnection api) {
String newAccessToken = api.getAccessToken();
String newrefreshToken = api.getRefreshToken();
// update new access and refresh token in DB/property
}
#Override
public void onError(BoxAPIConnection api, BoxAPIException error) {
LOGGER.error("Error in Box account details. " + error.getMessage());
}
});
LOGGER.debug("Completed Box authentication");
} catch (Exception e) {
LOGGER.error("Error in Box authentication. Error msg : " + e.getMessage());
}
If you use a state.conf file, you'll be able to refresh the token/refres_token pair programmatically without getting an auth code. Here's a code snippet that I use:
private static BoxAPIConnection getBoxAPIConnection(String client_id, String client_secret, String token, String refresh_token, String stateConfPath) {
String state = null;
try {
logger.info("Getting state.conf: " + stateConfPath + "/state.conf");
InputStream fis = new FileInputStream(stateConfPath + "/state.conf");
InputStreamReader isr = new InputStreamReader(fis, Charset.forName("UTF-8"));
BufferedReader br = new BufferedReader(isr);
state = br.readLine();
}
catch (FileNotFoundException f) {
try {
// create file if it doesn't exist
PrintWriter writer = new PrintWriter(stateConfPath + "/state.conf", "UTF-8");
writer.println("");
writer.close();
}
catch (Exception w) {
logger.fatal("Exception", w);
}
}
catch (IOException e) {
logger.fatal("IOException", e);
}
BoxAPIConnection api = null;
//if (null == state || "".equals(state)) {
if (!token.equals("") && !refresh_token.equals("")) {
api = new BoxAPIConnection(client_id, client_secret, token, refresh_token);
} else {
logger.info("Restoring state..." + state);
api = BoxAPIConnection.restore(client_id, client_secret, state);
if (api.needsRefresh()) { // this is not a reliable call. It can still throw a 401 below
logger.info("api refreshing...");
api.refresh();
}
else {
logger.info("api good...");
}
}
return api;
}

HTTP Basic Authentication for Play framework 2.4

I am looking some way to make some authentication for my play framework app: I want allow/disallow the whole access to non authenticated users
Is there exists some working module/solution for it? I don't need any forms for auth, just 401 HTTP response for non authenticated users (like Apache .htacccess "AuthType Basic" mode).
I've updated Jonck van der Kogel's answer to be more strict in parsing the authorization header, to not fail with ugly exceptions if the auth header is invalid, to allow passwords with ':', and to work with Play 2.6:
So, BasicAuthAction class:
import java.io.UnsupportedEncodingException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import org.apache.commons.codec.binary.Base64;
import play.Logger;
import play.Logger.ALogger;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Http.Context;
import play.mvc.Result;
public class BasicAuthAction extends Action<Result> {
private static ALogger log = Logger.of(BasicAuthAction.class);
private static final String AUTHORIZATION = "Authorization";
private static final String WWW_AUTHENTICATE = "WWW-Authenticate";
private static final String REALM = "Basic realm=\"Realm\"";
#Override
public CompletionStage<Result> call(Context context) {
String authHeader = context.request().getHeader(AUTHORIZATION);
if (authHeader == null) {
context.response().setHeader(WWW_AUTHENTICATE, REALM);
return CompletableFuture.completedFuture(status(Http.Status.UNAUTHORIZED, "Needs authorization"));
}
String[] credentials;
try {
credentials = parseAuthHeader(authHeader);
} catch (Exception e) {
log.warn("Cannot parse basic auth info", e);
return CompletableFuture.completedFuture(status(Http.Status.FORBIDDEN, "Invalid auth header"));
}
String username = credentials[0];
String password = credentials[1];
boolean loginCorrect = checkLogin(username, password);
if (!loginCorrect) {
log.warn("Incorrect basic auth login, username=" + username);
return CompletableFuture.completedFuture(status(Http.Status.FORBIDDEN, "Forbidden"));
} else {
context.request().setUsername(username);
log.info("Successful basic auth login, username=" + username);
return delegate.call(context);
}
}
private String[] parseAuthHeader(String authHeader) throws UnsupportedEncodingException {
if (!authHeader.startsWith("Basic ")) {
throw new IllegalArgumentException("Invalid Authorization header");
}
String[] credString;
String auth = authHeader.substring(6);
byte[] decodedAuth = new Base64().decode(auth);
credString = new String(decodedAuth, "UTF-8").split(":", 2);
if (credString.length != 2) {
throw new IllegalArgumentException("Invalid Authorization header");
}
return credString;
}
private boolean checkLogin(String username, String password) {
/// change this
return username.equals("vlad");
}
}
And then, in controller classes:
#With(BasicAuthAction.class)
public Result authPage() {
String username = request().username();
return Result.ok("Successful login as user: " + username + "! Here's your data: ...");
}
You can try this filter:
https://github.com/Kaliber/play-basic-authentication-filter
It looks pretty simple to use and configure.
You could also solve this with a play.mvc.Action, like this.
First your Action:
import org.apache.commons.codec.binary.Base64;
import play.libs.F;
import play.libs.F.Promise;
import play.mvc.Action;
import play.mvc.Http.Context;
import play.mvc.Result;
import util.ADUtil;
public class BasicAuthAction extends Action<Result> {
private static final String AUTHORIZATION = "authorization";
private static final String WWW_AUTHENTICATE = "WWW-Authenticate";
private static final String REALM = "Basic realm=\"yourRealm\"";
#Override
public Promise<Result> call(Context context) throws Throwable {
String authHeader = context.request().getHeader(AUTHORIZATION);
if (authHeader == null) {
context.response().setHeader(WWW_AUTHENTICATE, REALM);
return F.Promise.promise(new F.Function0<Result>() {
#Override
public Result apply() throws Throwable {
return unauthorized("Not authorised to perform action");
}
});
}
String auth = authHeader.substring(6);
byte[] decodedAuth = new Base64().decode(auth);
String[] credString = new String(decodedAuth, "UTF-8").split(":");
String username = credString[0];
String password = credString[1];
// here I authenticate against AD, replace by your own authentication mechanism
boolean loginCorrect = ADUtil.loginCorrect(username, password);
if (!loginCorrect) {
return F.Promise.promise(new F.Function0<Result>() {
#Override
public Result apply() throws Throwable {
return unauthorized("Not authorised to perform action");
}
});
} else {
return delegate.call(context);
}
}
}
Next your annotation:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import play.mvc.With;
#With(BasicAuthAction.class)
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE})
#Inherited
#Documented
public #interface BasicAuth {
}
You can now annotate your controller functions as follows:
#BasicAuth
public Promise<Result> yourControllerFunction() {
...
I'm afraid there's no such solution, reason is simple: usually when devs need to add authorization/authentication stack they build full solution.
The easiest and fastest way is using HTTP front-end server as a reverse-proxy for your application (I'd choose nginx for that task, but if you have running Apache on the machine it can be used as well). It will allow you to filter/authenticate the traffic with common server's rules
Additionally it gives you other benefits, i.e.: you can create CDN-like path, so you won't waste your apps' resources for serving public, static assets. You can use load-balancer for redeploying your app without stopping it totally for x minutes, etc.