I get a Signature invalid problem when I try to get data from Magento in Java. What is wrong with my code:
public class MagentoFacade {
final String MAGENTO_API_KEY = "apikey";
final String MAGENTO_API_SECRET = "apisecret";
final String MAGENTO_REST_API_URL = "urlmagento/api/rest";
public void testMethod() {
OAuthService service = new ServiceBuilder()
.provider(MagentoThreeLeggedOAuth.class)
.apiKey(MAGENTO_API_KEY)
.apiSecret(MAGENTO_API_SECRET)
.debug()
.build();
System.out.println("" + service.getVersion());
// start
Scanner in = new Scanner(System.in);
System.out.println("Magento's OAuth Workflow");
System.out.println();
// Obtain the Request Token
System.out.println("Fetching the Request Token...");
Token requestToken = service.getRequestToken();
System.out.println("Got the Request Token!");
System.out.println();
// Obtain the Authorization URL
System.out.println("Fetching the Authorization URL...");
String authorizationUrl = service.getAuthorizationUrl(requestToken);
System.out.println("Got the Authorization URL!");
System.out.println("Now go and authorize Main here:");
System.out.println(authorizationUrl);
System.out.println("And paste the authorization code here");
System.out.print(">>");
Verifier verifier = new Verifier(in.nextLine());
System.out.println();
System.out.println("Trading the Request Token for an Access Token...");
Token accessToken = service.getAccessToken(requestToken, verifier);
System.out.println("Got the Access Token!");
System.out.println("(if your curious it looks like this: "
+ accessToken + " )");
System.out.println();
OAuthRequest request = new OAuthRequest(Verb.GET, MAGENTO_REST_API_URL+ "/products?limit=2");
service.signRequest(accessToken, request);
Response response = request.send();
System.out.println();
System.out.println(response.getCode());
System.out.println(response.getBody());
System.out.println();
}
public static void main(String[] args) {
MagentoFacade mf = new MagentoFacade();
mf.testMethod();
}
}
public final class MagentoThreeLeggedOAuth extends DefaultApi10a {
private static final String BASE_URL = "urltoMagento/";
#Override
public String getRequestTokenEndpoint() {
return BASE_URL + "oauth/initiate";
}
#Override
public String getAccessTokenEndpoint() {
return BASE_URL + "oauth/token";
}
#Override
public String getAuthorizationUrl(Token requestToken) {
return BASE_URL + "richard/oauth_authorize?oauth_token="
+ requestToken.getToken(); //this implementation is for admin roles only...
}
}
signature is: NnRaB73FqCcFAAVB4evZtGkWE3k=
appended additional OAuth parameters: { oauth_callback -> oob , oauth_signature -> NnRaB73FqCcFAAVB4evZtGkWE3k= , oauth_version -> 1.0 , oauth_nonce -> 753236685 , oauth_signature_method -> HMAC-SHA1 , oauth_consumer_key -> ptrij1xt8tjisjb6kmdqed2v4rpla8av , oauth_timestamp -> 1359710704 }
using Http Header signature
sending request...
response status code: 401
response body: oauth_problem=signature_invalid&debug_sbs=MCe/RB8/GNuqV0qku00ubepc/Sc=
Exception in thread "main" org.scribe.exceptions.OAuthException: Response body is incorrect. Can't extract token and secret from this: 'oauth_problem=signature_invalid&debug_sbs=MCe/RB8/GNuqV0qku00ubepc/Sc='
at org.scribe.extractors.TokenExtractorImpl.extract(TokenExtractorImpl.java:41)
at org.scribe.extractors.TokenExtractorImpl.extract(TokenExtractorImpl.java:27)
at org.scribe.oauth.OAuth10aServiceImpl.getRequestToken(OAuth10aServiceImpl.java:52)
at magento.MagentoFacade.testMethod(MagentoFacade.java:39)
at magento.MagentoFacade.main(MagentoFacade.java:73)
I might have an answer for you, but it may not work in your case.
I struggled hard to find out why I got signature invalid on my local machine.
Turns out that when calculating the signature in Mage_Oauth_Model_Server::_validateSignature(), Magento builds the request URI part with the URL port path trimmed : $this->_request->getHttpHost()
In my case, the local webserver runs on port 81, thus my signature and the Magento one could not match.
By passing the false parameter to the getHttpHost method you can keep prevent port trim.
I know this is very specific, but I lost all my hair figuring out why so I needed to share it. And who knows, maybe this could help.
Cheers
Bouni
I'd just like to add that in Postman I simply added another urlparameter of getHttpHost with the value of false and that worked as well. I fought with this for an entire day. I hope this saves someone else time.
Related
I'm stuck on this issue, please help...
So, Post request working fine on Postman, but in Rest Assured I am getting 307 Temporary Redirect status code. I find that this issue related to redirects. Because I checked settings on Postman and when I am turning "Automatically follow redirect" toggle OFF, it gives same issue in Postman as well, but it works when it is ON.
How can I add the same to my code (turn ON "Automatically follow redirect" in Rest Assured/Java?)
Here is my code:
static {
baseURI = ConfigReader.getProperty("url");
}
RequestSpecification requestSpecification;
Response response;
String accessToken;
#Given("I am authorized at endpoint {string}")
public void getAccessToken(String endpoint) {
response = given().log().all()
.header("Content-Type", "application/json").body("{\n" +
" \"username\": \"" + ConfigReader.getProperty("username") + "\",\n" +
"\"password\": \"" + ConfigReader.getProperty("password") + "\" \n" +
"}").post(endpoint);
String jsonString = response.asString();
accessToken = JsonPath.from(jsonString).get("AccessToken");
}
#When("I add the header {string} {string}")
public void setAuthorizationHeaders(String key, String value) {
requestSpecification = given()
.header(key, value).
header("AccessToken", accessToken);
}
#Then("I send a POST request to {string} endpoint with the body {body}")
public void iSendAPOSTRequestToEndpointWithTheBody(String string, String body) throws InterruptedException {
requestSpecification.body(new File("body"))
.post(string).then().log().all().
statusCode(200);
}
I already used these ways and they did not work (or I used them wrong):
Please advise based on my above code!
given().config(RestAssured.config().redirect(redirectConfig().followRedirects(false)))
RequestSpecification spec = new RequestSpecBuilder().setConfig(RestAssured.config().redirect(redirectConfig().followRedirects(false))).build();
RestAssured.config = config().redirect(redirectConfig().followRedirects(true).and().maxRedirects(0));
Rest assured will automatically redirect if it is GET/HEAD request and status code is 302. In your case this is a POST request so it wont automatically redirect.
You might need to do it manually like:
Response resp1 =
given().
contentType(ContentType.URLENC).
body("AUTH_TOKEN=&j_username=" + encodedUsername + "&j_password=" + password + "&userName=&AUTH_TOKEN=").
redirects().follow(false).
expect().
statusCode(302).
when().
post("/authenticate/j_spring_security_check");
String headerLocationValue = resp1.getHeader("Location");
Response resp2 =
given().
cookie(resp1.getDetailedCookie("JSESSIONID")).
expect().
statusCode(200).
when().
get(headerLocationValue);
I have a requirement to make a post-call to a URL which has OAuth 1.0 authentication. I am pretty new to all these. From my research, I got to know about Scribe in Java, but I can find only Get calls using Scribe. I already have consumerKey and consumerSecret key for OAuth 1.0 authentication. Are there any suggestions on how to achieve this successfully.
With postman I am able to fetch the data successfully, but I want to achieve it using Java.
I have tried something like this
I tried this way
public String getSmartCommPDF(#RequestBody Model model) throws IOException {
OAuthService service = new ServiceBuilder().provider(ModelAPI.class).apiKey(consumerKey)
.apiSecret(consumerSecret).build();
OAuthRequest request = new OAuthRequest(Verb.POST, url);
ObjectMapper mapper = new ObjectMapper();
request.addHeader("Content-Type", "application/json;charset=UTF-8");
request.addPayload(mapper.writeValueAsString(model));
Token accessToken = new Token("", ""); // not required for context.io
service.signRequest(accessToken, request);
Response response = request.send();
System.out.println("Response = " + response.getBody());
return "Success";
}
This is my ModelAPI class
public class ModelAPI extends DefaultApi10a {
#Override
public String getRequestTokenEndpoint() {
return "https://domain/one/oauth1/api/v6/job";
}
#Override
public String getAccessTokenEndpoint() {
return "https://domain/one/oauth1/api/v6/job";
}
#Override
public String getAuthorizationUrl(Token requestToken) {
return "https://domain/one/oauth1/api/v6/job";
}
}
This part of code is not throwing any error but, the response body is empty. Where I am going wrong, any one has any idea?
Thank you.
The data was coming back in the input stream. So, I used
response.getStream();
and write it to a file and use it.
I want to use access token to get userinfo with a java open-id connect library the same as nodejs.
I use npm-openid-client to get the userInfo and it works very well in nodejs
/**
** client_id and client_secret can be empty now
*/
const { Issuer } = require('openid-client');
const end_point = 'xxx'
const access_token = 'xxx'
Issuer.discover(end_point).then(function (issuer) {
const client = new issuer.Client({
client_id: 'xx',
client_secret: 'xx',
});
client.userinfo(access_token).then(function (userinfo) {
console.log('userinfo %j', userinfo);
});
});
I google java open-id library and find some library from openid.net
and finally I use connect2id
I follow the link openid-connect/userinfo and write some code below:
import java.io.*;
import java.net.*;
import com.nimbusds.oauth2.sdk.http.*;
import com.nimbusds.oauth2.sdk.token.*;
import com.nimbusds.openid.connect.sdk.claims.*;
class Test {
public static void main (String[] args) throws Exception{
String uriStr = "";
String tokenStr = "";
URI userInfoEndpoint = new URI(uriStr);
BearerAccessToken token = new BearerAccessToken(tokenStr);
// Make the request
HTTPResponse httpResponse = new UserInfoRequest(userInfoEndpoint, token)
.toHTTPRequest()
.send();
// Parse the response
UserInfoResponse userInfoResponse = UserInfoResponse.parse(httpResponse);
if (! userInfoResponse.indicatesSuccess()) {
// The request failed, e.g. due to invalid or expired token
System.out.println(userInfoResponse.toErrorResponse().getErrorObject().getCode());
System.out.println(userInfoResponse.toErrorResponse().getErrorObject().getDescription());
return;
}
// Extract the claims
UserInfo userInfo = userInfoResponse.toSuccessResponse().getUserInfo();
System.out.println("Subject: " + userInfo.getSubject());
System.out.println("Email: " + userInfo.getEmailAddress());
System.out.println("Name: " + userInfo.getName());
}
}
the result is that httpResponse return 404 not found. how can I fix it and get the userInfo ?
We're using stormpath with Java & also trying to combine form Login with REST API authentication on the same application.
I've setup stormpath servlet plugin as described here https://docs.stormpath.com/java/servlet-plugin/quickstart.html... This works very fine.
Now, on the same application, we have APIs where I've implemented oAuth authentication with stormpath see here http://docs.stormpath.com/guides/api-key-management/
The first request for an access-token works fine by sending Basic Base64(keyId:keySecret) in the request header and grant_type = client_credentials in the body. Access tokens are being returned nicely. However trying to authenticate subsequent requests with the header Bearer <the-obtained-access-token> does not even hit the application before
returning the following json error message...
{
"error": "invalid_client",
"error_description": "access_token is invalid."
}
This is confusing because I've set breakpoints all over the application and I'm pretty sure that the API request doesn't hit the anywhere within the application before stormpath kicks in and returns this error. And even if stormpath somehow intercepts the request before getting to the REST interface, this message doesn't make any sense to me because i'm certainly making the subsequent API calls with a valid access-token obtained from the first call to get access-token.
I have run out of ideas why this could be happening but i'm suspecting that it may have something to do with stormpath config especially with a combination
of form Login/Authentication for web views and oAuth Athentication for REST endpoints. With that said, here's what my stormpath.properties looks like. Hope this could help point at anything I may be doing wrong.
stormpath.application.href=https://api.stormpath.com/v1/applications/[app-id]
stormpath.web.filters.authr=com.app.security.AuthorizationFilter
stormpath.web.request.event.listener = com.app.security.AuthenticationListener
stormpath.web.uris./resources/**=anon
stormpath.web.uris./assets/**=anon
stormpath.web.uris./v1.0/**=anon
stormpath.web.uris./** = authc,authr
stormpath.web.uris./**/**=authc,authr
Help with this would be highly appreciated.
The problem might be related to an incorrect request.
Is it possible for you to try this code in your app?:
private boolean verify(String accessToken) throws OauthAuthenticationException {
HttpRequest request = createRequestForOauth2AuthenticatedOperation(accessToken);
AccessTokenResult result = Applications.oauthRequestAuthenticator(application)
.authenticate(request);
System.out.println(result.getAccount().getEmail() + " was successfully verified, you can allow your protect operation to continue");
return true;
}
private HttpRequest createRequestForOauth2AuthenticatedOperation(String token) {
try {
Map<String, String[]> headers = new LinkedHashMap<String, String[]>();
headers.put("Accept", new String[]{"application/json"});
headers.put("Authorization", new String[]{"Bearer " + token});
HttpRequest request = HttpRequests.method(HttpMethod.GET)
.headers(headers)
.build();
return request;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
I've prepared an example that demonstrates oauth token creation as well as authorized access to protected pages using access tokens.
It builds off of the servlet example in the Stormpath SDK. The repo can be found here: https://github.com/stormpath/stormpath-java-oauth-servlet-sample
It demonstrates running a servlet application and having an out-of-band program get and use oauth tokens to access protected resources.
The core of the oauth part is in TokenAuthTest.java:
public class TokenAuthTest {
public static void main(String[] args) throws Exception {
String command = System.getProperty("command");
if (command == null || !("getToken".equals(command) || "getPage".equals(command))) {
System.err.println("Must supply a command:");
System.err.println("\t-Dcommand=getToken OR");
System.err.println("\t-Dcommand=getPage OR");
System.exit(1);
}
if ("getToken".equals(command)) {
getToken();
} else {
getPage();
}
}
private static final String APP_URL = "http://localhost:8080";
private static final String OAUTH_URI = "/oauth/token";
private static final String PROTECTED_URI = "/dashboard";
private static void getToken() throws Exception {
String username = System.getProperty("username");
String password = System.getProperty("password");
if (username == null || password == null) {
System.err.println("Must supply -Dusername=<username> -Dpassword=<password> on the command line");
System.exit(1);
}
PostMethod method = new PostMethod(APP_URL + OAUTH_URI);
method.setRequestHeader("Origin", APP_URL);
method.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
method.addParameter("grant_type", "password");
method.addParameter("username", username);
method.addParameter("password", password);
HttpClient client = new HttpClient();
client.executeMethod(method);
BufferedReader br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
String readLine;
while(((readLine = br.readLine()) != null)) {
System.out.println(readLine);
}
}
private static void getPage() throws Exception {
String token = System.getProperty("token");
if (token == null) {
System.err.println("Must supply -Dtoken=<access token> on the command line");
System.exit(1);
}
GetMethod method = new GetMethod(APP_URL + PROTECTED_URI);
HttpClient client = new HttpClient();
System.out.println("Attempting to retrieve " + PROTECTED_URI + " without token...");
int returnCode = client.executeMethod(method);
System.out.println("return code: " + returnCode);
System.out.println();
System.out.println("Attempting to retrieve " + PROTECTED_URI + " with token...");
method.addRequestHeader("Authorization", "Bearer " + token);
returnCode = client.executeMethod(method);
System.out.println("return code: " + returnCode);
}
}
I am using scribe library to register android with Magento.
But I am getting error:
org.scribe.exceptions.OAuthException: Response body is incorrect. Can't extract token and secret from this: '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<p>The requested URL /oauth/initiate was not found on this server.</p>
But my key,secret and url all are correct. I defined user and roles correctly.
I took reference from here:https://gmartinezgil.wordpress.com/2013/08/05/using-the-magento-rest-api-in-java-with-scribe/
My code is like this:
calling Asyntask from activity: new OauthAsyncTask().execute();
and then my task is:
public class OauthAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
// oauth for magento api access
OAuthService service = new ServiceBuilder()
.provider(MagentoThreeLeggedOAuth.class)
.apiKey(MAGENTO_API_KEY)
.apiSecret(MAGENTO_API_SECRET)
.build();
Token requestToken = service.getRequestToken();
String authorizationUrl = service.getAuthorizationUrl(requestToken);
Verifier verifier = new Verifier("Getting TOken");
Log.e("authorizationUrl:", authorizationUrl);
Token accessToken = service.getAccessToken(requestToken, verifier);
Log.e("accessToken:", accessToken.toString());
OAuthRequest request = new OAuthRequest(Verb.GET, "MAGENTO_REST_API_URL"+ "/products");
service.signRequest(accessToken, request);
Response response = request.send();
Log.e("response:", response.toString());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
// auth class
public static final class MagentoThreeLeggedOAuth extends DefaultApi10a {
private static final String BASE_URL = "http://myapp.com/";
#Override
public String getRequestTokenEndpoint() {
return BASE_URL + "oauth/initiate";
}
#Override
public String getAccessTokenEndpoint() {
return BASE_URL + "oauth/token";
}
#Override
public String getAuthorizationUrl(Token token) {
return null;
}
}
Please help me out on this issue.
Problem is silly but tricky, I asked my Magento developer that what is the BASE URL he replied with "http://myapp.com/" and got stuck with above problem, when I searched about it more, I found that some users using BASE URL like "http://myapp.com/magento" or "http://myapp.com/magento/index.php" etc. So I found that the real path was "http://myapp.com/index.php", it was not directed to BASE URL. So some times when product is in development mode these kind of problems occur and just confirm with magento dev's what is exact path.