I need your help.
I need to connect to my Magento store using REST but I have a problem to retrieve the oauth token.
I did what was said in this tutorial : gmartinezgil.wordpress.com/2013/08/05/using-the-magento-rest-api-in-java-with-scribe/
My code is available here : https://www.dropbox.com/sh/zglzl9xsxcjrpid/lGrZNYfRzG
I'm working with Magento 1.8.1.0 using Wampserver
Here is my Main.java file:
package foo;
import java.util.Scanner;
import org.scribe.builder.*;
import org.scribe.builder.api.*;
import org.scribe.model.*;
import org.scribe.oauth.*;
/**
* #author jerry
*/
public final class Main {
/**
* #param args
*/
public static void main(String[] args) {
final String MAGENTO_API_KEY = "r0ntsryd0hamwmdnjezb8joun01c4h1s";
final String MAGENTO_API_SECRET = "czylgk8yxhkvrx141v1q9trx0iw4qbgt";
final String MAGENTO_REST_API_URL = "http://localhost/magento/api/rest/";
//final String MAGENTO_REST_API_URL = "http://localhost/magento/api.php?type=rest/";
// three-legged oauth
OAuthService service = new ServiceBuilder()
.provider(MagentoThreeLeggedOAuth.class)
.apiKey(MAGENTO_API_KEY)
.apiSecret(MAGENTO_API_SECRET)
.debug()
.build();
System.out.println("" + service.getVersion());
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();
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();
}
}
The terminal displays :
1.0
Magento's OAuth Workflow
Fetching the Request Token...
obtaining request token from http://`magentohost`/oauth/initiate/
setting oauth_callback to oob
generating signature...
using base64 encoder: CommonsCodec
base string is: POST&http%3A%2F%2F127.0.0.1%2Fmagento%2Foauth%2Finitiate%2F&oauth_callback%3Doob%26oauth_consumer_key%3Dr0ntsryd0hamwmdnjezb8joun01c4h1s%26oauth_nonce%3D2085598405%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1395911858%26oauth_version%3D1.0
signature is: edOifgJQfBg2QoM7ifVBWwvYj30=
appended additional OAuth parameters: { oauth_callback -> oob , oauth_signature -> edOifgJQfBg2QoM7ifVBWwvYj30= , oauth_version -> 1.0 , oauth_nonce -> 2085598405 , oauth_signature_method -> HMAC-SHA1 , oauth_consumer_key -> r0ntsryd0hamwmdnjezb8joun01c4h1s , oauth_timestamp -> 1395911858 }
using Http Header signature
sending request...
response status code: 404
response body: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /magento/oauth/initiate/ was not found on this server.</p>
</body></html>
Exception in thread "main" 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">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /magento/oauth/initiate/ was not found on this server.</p>
</body></html>
'
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:64)
at org.scribe.oauth.OAuth10aServiceImpl.getRequestToken(OAuth10aServiceImpl.java:40)
at org.scribe.oauth.OAuth10aServiceImpl.getRequestToken(OAuth10aServiceImpl.java:45)
at foo.Main.main(Main.java:35)
I think I found the solution. I activated mod_rewrite :http://www.webdevdoor.com/php/mod_rewrite-windows-apache-url-rewriting/ and did what is said here http://doc.prestashop.com/display/PS16/What+you+need+to+get+started and it worked.
Related
Currently I have a method that does some authorization, which is used for my access token POST request in the body to establish the proper access token. In my authorization method, I am able to extract the Location header value in the response. The only issue is that I only need to extract the values between code= and & as seen in the below string (locationHeaderForAuthCode):
https://something.url.com/myapp/auth/token?code=**12WVUcPyFbmTZUOcgaluGl98r08**&iss=https%3A%2F%2Fsomething.url.com%3A8443%2Fam%2Foauth2%2Fvendors&client_id=5c1d7ex3-g3rc-4a64-9855-074a57cc1570
Since that code is used for the request body in my access token POST request, I need to extract only that portion. How do I achieve this in Rest Assured, and if not, then just using plain Java?
Any help would be appreciated. Below is my method for authorization that sets the Location header, and the other method for the access token post request:
private static void getAuthorizeCode() throws JsonException {
response = given()
.config(RestAssured.config()
.encoderConfig(EncoderConfig.encoderConfig()
.encodeContentTypeAs("x-www-form-urlencoded",
ContentType.URLENC)))
.cookies(cookies)
.header("Accept-Encoding", "gzip, deflate, br")
.formParam("redirect_uri", devRedirectUrl)
.formParam("response_type", responseType)
.formParam("client_id", userClientID)
.formParam("client_secret", userClientSecrets)
.formParam("decision", decision)
.formParam("csrf", tokenId)
.post(urlProps.getProperty("devVGWAuthorizeUrl"))
.then()
.assertThat()
.statusCode(302)
.extract().response();
locationHeaderForAuthCode = response.getHeader("Location");
}
private static void getAccToken() throws JsonException {
response = given()
.log().all().config(RestAssured.config()
.encoderConfig(EncoderConfig.encoderConfig()
.encodeContentTypeAs("x-www-form-urlencoded",
ContentType.URLENC)))
.cookies(cookies)
.header("Accept-Encoding", "gzip, deflate, br")
.formParam("grant_type", "authorization_code")
.formParam("client_id", userClientID)
.formParam("client_secret", userClientSecrets)
.formParam("redirect_uri", devRedirectUrl)
.formParam("code", locationHeaderForAuthCode)
.post(urlProps.getProperty("devVGWAccessTokenUrl"))
.then()
// .assertThat()
// .statusCode(200)
.log().all()
.extract().response();
accToken = response.jsonPath().getString("access_token");
System.out.println("Access token is " + accToken);
}
You just need simple split() method of String to extract value from this text.
String url = "https://something.url.com/myapp/auth/token?code=**12WVUcPyFbmTZUOcgaluGl98r08**&iss=https%3A%2F%2Fsomething.url.com%3A8443%2Fam%2Foauth2%2Fvendors&client_id=5c1d7ex3-g3rc-4a64-9855-074a57cc1570";
String[] texts = url.split("code=");
String code = texts[1].split("&")[0];
System.out.println(code); //**12WVUcPyFbmTZUOcgaluGl98r08**
We have a Daemon application that uses the EWS API to access office365/Exchange server with basic authentication. I am trying to implement the Oauth2. There are a lot of documents. However, they are often out of date and caused more confusion. I followed this document https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-overview, which seems up-to-date. I did the following steps:
Register App
Document: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-app-registration
- Registered a secret with application password in Azure AD, i.e. certificate is used. The generated secret is recorded.
- selected the “Accounts in this organizational directory only”.
- Requested API Permission for Application permissions for Exchange full_access_as_app and Mail.Read. Admin consent is granted.
Get Token
Document: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-acquire-token?tabs=java
I prototyped to use Protocol to get token
POST /{tenant}/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id={myAppClientId}
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret={myAppSecret}
&grant_type=client_credentials
I got token with
{
"token_type": "Bearer",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "……thetoken…"
}
Call EWS API in my App
My App works with the Basic Authentication. I modified it by adding the Authorization header ("Authorization", "Bearer " + accessToken); Basially the prepareWebRequest() function is overriden by adding the Authorization header. Compared with a Basic Authentication case, the request has the additional Authorization header with the Bearer token.
For the same EWS API call that the Basic Authorization had worked, the response is 401 with
x-ms-diagnostics
2000003;reason="The audience claim value is invalid for current resource. Audience claim is 'https://graph.microsoft.com', request url is 'https://outlook.office365.com/EWS/Exchange.asmx' and resource type is 'Exchange'.";error_category="invalid_resource"
Researched in stackoverflow, people suggested to use the following as scope value to get token in step 2:
https://outlook.office365.com/full_access_as_app
https://outlook.office.com/Mail.Read
I tried and both returned “invalid_scope” error. It seems both worked before but not anymore. Following the working scope value format, I tried to use https://outlook.office.com/.default as scope value. I was able to get a token! However, when I use this token in EWS API to access the mailbox, I got 500 error instead of the 401.
What are the right things to do to make it work? What is the right Scope to access an office365 mail box?
More Code Snippets
This is a new class added for oauth2
package microsoft.exchange.webservices.data;
import java.util.Map;
public final class BearerTokenCredentials extends ExchangeCredentials {
private static final String BEARER_TOKEN_FORMAT_REGEX = "^[-._~+/A-Za-z0-9]+=*$";
private static final String AUTHORIZATION = "Authorization";
private static final String BEARER_AUTH_PREAMBLE = "Bearer ";
private String token;
public String getToken() {
return token;
}
public BearerTokenCredentials(String bearerToken) {
if (bearerToken == null) {
throw new IllegalArgumentException("Bearer token can not be null");
}
this.validateToken(bearerToken);
this.token = bearerToken;
}
protected void validateToken(String bearerToken) throws IllegalArgumentException {
if (!bearerToken.matches(BEARER_TOKEN_FORMAT_REGEX)) {
throw new IllegalArgumentException("Bearer token format is invalid.");
}
}
#Override
public void prepareWebRequest(HttpWebRequest request) {
Map<String, String> headersMap = request.getHeaders();
String bearerValue = BEARER_AUTH_PREAMBLE + token;
headersMap.put(AUTHORIZATION, bearerValue);
//headersMap.put("X-AnchorMailbox","esj_office365_imap#genesyslab.onmicrosoft.com");
request.setHeaders(headersMap);
}
}
Use the token to acceess EWS/Exchange ews-java-api 2.0-patched
ExchangeService service = new
ExchangeService(ExchangeVersion.Exchange2010_SP2); //version is
Exchange2010_SP2
service.setTraceEnabled(true);
BearerTokenCredentials credentials = new BearerTokenCredentials("thetoken");
service.setCredentials(credentials);
service.setUrl(new
URI(host));//https://outloook.office365.com/EWS/Exchange.asmx
try{
Folder.bind(service, WellKnownFolderName.Inbox);
}catch(Exception e)
{
//The remote server returned an error: (500)Internal Server Error
}
The code you use to connect to the Office365 Mailbox still needs to use EWS Impersonation eg
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, mailboxName);
Where MailboxName is the Mailbox you want to connect to.
I was following this tutorial: https://developers.docusign.com/esign-rest-api/code-examples/config-and-auth
(I used java)
In the third step I dont know how to get the code that is sent back form DocuSign as query param in the redirect uri:
// Java request auth token
**String code = "{ENTER_AUTH_CODE_FROM_PREVIOUS_STEP}";**
// assign it to the token endpoint
apiClient.getTokenEndPoint().setCode(code);
// optionally register to get notified when a new token arrives
apiClient.registerAccessTokenListener(new AccessTokenListener() {
#Override
public void notify(BasicOAuthToken token) {
System.out.println("Got a fresh token: " + token.getAccessToken());
}
});
// following call exchanges the authorization code for an access code and updates
// the `Authorization: bearer <token>` header on the api client
apiClient.updateAccessToken();
I get an error saying the requested access token is null. Below is the error:
Error while requesting an access token. No accessTokenResponse object received, maybe a non HTTP 200 received?
Has anybody ever got the same one or could maybe someone tell me how to fix it.
I ran below code and its working fine for me, after getting code from the previous step in the URL:
public static void main(String[] args) {
String IntegratorKey = "[Your_Integrator_Key]";
String ClientSecret = "[Your_Secret_Key]";
String RedirectURI = "https://www.getpostman.com/oauth2/callback";//This REDIRECT_URI should match whats configured with IntegratorKey in your Sandbox account
String AuthServerUrl = "https://account-d.docusign.com";
String RestApiUrl = "https://demo.docusign.net/restapi";
ApiClient apiClient = new ApiClient(AuthServerUrl, "docusignAccessCode", IntegratorKey, ClientSecret);
apiClient.setBasePath(RestApiUrl);
apiClient.configureAuthorizationFlow(IntegratorKey, ClientSecret, RedirectURI);
Configuration.setDefaultApiClient(apiClient);
String code = "{ENTER_AUTH_CODE_FROM_PREVIOUS_STEP}";
apiClient.getTokenEndPoint().setCode(code);
apiClient.registerAccessTokenListener(new AccessTokenListener() {
#Override
public void notify(BasicOAuthToken token) {
System.out.println("Got a fresh token: " + token.getAccessToken());
}
});
apiClient.updateAccessToken();
}
To get the code returned by DocuSign from browser, you need to have a WEBApp to which DocuSign will redirect the browser, this same callback URL should be configured in your DS Sandbox's REDIRECT_URI, for instance if you WEBApp callback URL is http://locahost:8080/docusignapp/callback, then this should be added in REDIRECT_URI in IntegratorKey and same needs to be added when calling DS URL to authenticate a user. Once DS authenticates the user, it will redirect the browser to your APP url. On hitting your WEBApp then you need to read the URL and strip off the code part using Javascript, then run the step2 to get the access Token. A sample JS code to strip the code part is:
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
var authCode = vars["code"];
In the example which you share they did it using Standalone code, where you are manually copying the code part from the URL after authentication and running the step2.
Trying to connect Magento 1.9 using REST API and Scribe-Java 1.3.7
Done creating Web Services Role and Consumer as below:
After that, run the following codes:
public final class MagentoThreeLeggedOAuth extends DefaultApi10a {
private static final String BASE_URL = "http://my.magentoshop.com/";
#Override
public String getAccessTokenEndpoint() {
return BASE_URL + "oauth/token";
}
#Override
public String getAuthorizationUrl(Token requestToken) {
return BASE_URL + "admin/oauth_authorize?oauth_token="
+ requestToken.getToken(); //this implementation is for admin roles only...
}
#Override
public String getRequestTokenEndpoint() {
return BASE_URL + "oauth/token";
}
public static class Main {
public static void main(String[] args) {
final String MAGENTO_API_KEY = "[xxxxxxxxx]";
final String MAGENTO_API_SECRET = "[yyyyyyyyyy]";
final String MAGENTO_REST_API_URL = "http://my.magentoshop.com/api/rest";
// three-legged oauth
OAuthService service = new ServiceBuilder()
.provider(MagentoThreeLeggedOAuth.class)
.apiKey(MAGENTO_API_KEY).apiSecret(MAGENTO_API_SECRET).debug()
.build();
// 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();
}
}
}
and below are the errors shown on console:
Magento's OAuth Workflow
Fetching the Request Token...
obtaining request token from http://my.magentoshop.com/oauth/token
setting oauth_callback to oob
generating signature...
using base64 encoder: CommonsCodec
base string is: POST&http%3A%2F%2Fmy.magentosgop.com%2Foauth%2Ftoken&oauth_callback%3Doob%26oauth_consumer_key%3Dxxxxxxxxxxxxxxxx%26oauth_nonce%3D2939370741%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1429517137%26oauth_version%3D1.0
signature is: nINxAFwv6woAAQYbdHn6v2Uc+lw=
appended additional OAuth parameters: { oauth_nonce -> 2939370741 , oauth_signature -> nINxAFwv6woAAQYbdHn6v2Uc+lw= , oauth_callback -> oob , oauth_consumer_key -> 20482d9e12ead3420a4c5aeb6978bf8e , oauth_timestamp -> 1429517137 , oauth_signature_method -> HMAC-SHA1 , oauth_version -> 1.0 }
using Http Header signature
sending request...
response status code: 400
response body: oauth_problem=parameter_absent&oauth_parameters_absent=oauth_token
Exception in thread "main" org.scribe.exceptions.OAuthException: Response body is incorrect. Can't extract token and secret from this: 'oauth_problem=parameter_absent&oauth_parameters_absent=oauth_token'
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:64)
at org.scribe.oauth.OAuth10aServiceImpl.getRequestToken(OAuth10aServiceImpl.java:40)
at org.scribe.oauth.OAuth10aServiceImpl.getRequestToken(OAuth10aServiceImpl.java:45)
at MagentoThreeLeggedOAuth$Main.main(MagentoThreeLeggedOAuth.java:49)
What did I missed or wrongly done?
Thanks
OK, just found out the mistakes was:
Change this:
#Override
public String getRequestTokenEndpoint() {
return BASE_URL + "oauth/token";
}
To this:
#Override
public String getRequestTokenEndpoint() {
return BASE_URL + "oauth/initiate";
}
I'm trying to write a simple Jenkins plug-in with integration with Box, but I always get this error:
=== Box's OAuth Workflow ===
Fetching the Authorization URL...
Got the Authorization URL!
Now go and authorize Scribe here:
https://www.box.com/api/oauth2/authorize?client_id=abc123&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fjenkins%2Fconfigure&response_type=code&state=authenticated
And paste the authorization code here
>>xyz9876543
Trading the Request Token for an Access Token...
Exception in thread "main" org.scribe.exceptions.OAuthException: Cannot extract an acces token. Response was: {"error":"invalid_request","error_description":"Invalid grant_type parameter or parameter missing"}
at org.scribe.extractors.JsonTokenExtractor.extract(JsonTokenExtractor.java:23)
at org.scribe.oauth.OAuth20ServiceImpl.getAccessToken(OAuth20ServiceImpl.java:37)
at com.example.box.oauth2.Box2.main(Box2.java:40)
Box2 class (for testing) :
public class Box2 {
private static final Token EMPTY_TOKEN = null;
public static void main(String[] args) {
// Replace these with your own api key and secret
String apiKey = "abc123";
String apiSecret = "xyz987";
OAuthService service = new ServiceBuilder().provider(BoxApi.class)
.apiKey(apiKey).apiSecret(apiSecret)
.callback("http://localhost:8080/jenkins/configure")
.build();
Scanner in = new Scanner(System.in);
System.out.println("=== Box's OAuth Workflow ===");
System.out.println();
// Obtain the Authorization URL
System.out.println("Fetching the Authorization URL...");
String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
System.out.println("Got the Authorization URL!");
System.out.println("Now go and authorize Scribe 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();
// Trade the Request Token and Verfier for the Access Token
System.out.println("Trading the Request Token for an Access Token...");
Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
System.out.println("Got the Access Token!");
System.out.println("(if your curious it looks like this: "
+ accessToken + " )");
System.out.println();
}
}
BoxApi class:
public class BoxApi extends DefaultApi20 {
private static final String AUTHORIZATION_URL =
"https://www.box.com/api/oauth2/authorize?client_id=%s&redirect_uri=%s&response_type=code&state=authenticated";
#Override
public String getAccessTokenEndpoint() {
return "https://www.box.com/api/oauth2/token?grant_type=authorization_code";
}
#Override
public String getAuthorizationUrl(OAuthConfig config) {
return String.format(AUTHORIZATION_URL, config.getApiKey(),
OAuthEncoder.encode(config.getCallback()));
}
#Override
public Verb getAccessTokenVerb(){
return Verb.POST;
}
#Override
public AccessTokenExtractor getAccessTokenExtractor() {
return new JsonTokenExtractor();
}
}
I'm not sure how I get these exceptions. Can anyone who knows the Box API tell me if I've done anything wrong with it?
The request for the access token needs to be in the form of a POST request, with the parameters included in the body of the request–it looks like you're sending a GET with the parameters as URL parameters.