Problems with making ebay REST api call - rest

I've write following code:
include('httpful.phar');
include('config.php');
use \Httpful\Request;
class fullfil_pol_data{
public $name='1dzien';
public $marketplace='EBAY_PL';
public $category=array('name' => 'ALL_EXCLUDING_MOTORS_VEHICLES');
public $czas_wysylki=array('value'=> 1, 'unit'=>'DAY');
}
class aukcja{
public $ilosc;
public $cat_id;
public $format;
public $opis;
}
class token{
public $token;
private $duration;
private $starts;
public function __construct($t, $d){
$this->token=$t;
$this->duration=$d;
$this->starts=time();
}
public function check(){
if($this->duration+$this->starts >= time()-15*60) ibej::get_token();
}
}
class ibej{
private $token;
private $sandbox=true;
public function get_token()
{
if(this->sandbox) $url='https://api.sandbox.ebay.com/identity/v1/oauth2/token';
$req= Request::post($url)->addHeader('Content-Type', 'application/x-www-form-urlencoded')
->addHeader('Authorization', 'Basic '.PASSES)
->body("grant_type=client_credentials&redirect_uri=Marketing_Desig-Marketin-wystaw-blzyg&scope=https://api.ebay.com/oauth/api_scope")->send();
$this->token = new token($req->body->access_token, $req->body->expires_in);
var_dump($this->token);
}
/*$url='https://api.sandbox.ebay.com/sell/inventory/v1/offer';
//$req= Request::post($url)->addHeader('Authorization', 'Bearer '.$token)
// ->addHeader('X-EBAY-C-MARKETPLACE-ID', 'EBAY-PL')
*/
public function post_fullfilment_policy()
{
if(this->sandbox) $url='https://api.sandbox.ebay.com/sell/account/v1/fulfillment_policy';
$test= new fullfil_pol_data;
$req= Request::post($url)->addHeader('Authorization', 'Bearer '.$this->token->token)
->addHeader('Accept', 'application/json')
->addheader('Content-Type', 'application/json')
->addHeader('X-EBAY-C-MARKETPLACE-ID', 'EBAY-US')
->body(json_encode($test))->send();
var_dump($req);
}
}
$ibej_api = new ibej;
$ibej_api->get_token();
$ibej_api->post_fullfilment_policy();
When I try to call fullfilmentpolicy (http://developer.ebay.com/Devzone/rest/api-ref/account/fulfillment_policy__post.html) with ->post_fullfilment_policy() method I've this error in response:
"{"errors":[{"errorId":1100,"domain":"ACCESS","category":"REQUEST","message":"Access denied","longMessage":"Insufficient permissions to fulfill the request."}]}"
I don't know what is wrong, I reckon that If I have obtained token, it should give me permissions to do things with my account. Could anyone help me?

It looks like you have created an Application token. In order to perform API operations on eBay that involve a seller's account you have to create a User Token.This is explained in the documentation. Note that the process involved in getting a user token requires the user to log into their eBay account to grant permission to your application. The process is very different to obtaining an application token.

Related

HTTP Status 500 – Internal Server Error API PUT : Update method doesn't work [Spring-boot]

I want to update user but it doesn't work for other models it's simply working, whereas user no so can someone help me to find the solution. By the way I'm using spring-boot and mongodb.
public void changeUserPassword(Utilisateur user, String password) {
user.setPassword(passwordEncoder.encode(password));
utilisateurRepository.save(user);
}
#PutMapping("/update/{id}")
public ResponseEntity<?> update(#Valid #RequestBody Utilisateur user, #PathVariable String id){
Optional<Utilisateur> userData = utilisateurRepository.findById(id);
if(userData.isPresent()) {
user.setId_user(id);
this.changeUserPassword(user, user.getNewpassword());
this.utilisateurRepository.save(user);
return new ResponseEntity<>("User successfully updated", HttpStatus.OK);
}
else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
What causing the issue is in the model I added #NotBlank for variable so I remove it and thats work perfectly

Can I force a logout or expiration of a JWT token?

For authentication currently we are using JWT, so once a token is created it's created for a lifetime, and if we set a time expire, the token will expire.
Is there any way to expire token?
While clicking log out button, I need to destroy the token.
I'm using ASP.NET Core WebAPI.
I think cancelling JWT is the best way to handle logout. Piotr explained well in his blog: Cancel JWT tokens
We will start with the interface:
public interface ITokenManager
{
Task<bool> IsCurrentActiveToken();
Task DeactivateCurrentAsync();
Task<bool> IsActiveAsync(string token);
Task DeactivateAsync(string token);
}
And process with its implementation, where the basic idea is to keep
track of deactivated tokens only and remove them from a cache when not
needed anymore (meaning when the expiry time passed) – they will be no
longer valid anyway.
public class TokenManager : ITokenManager
{
private readonly IDistributedCache _cache;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IOptions<JwtOptions> _jwtOptions;
public TokenManager(IDistributedCache cache,
IHttpContextAccessor httpContextAccessor,
IOptions<JwtOptions> jwtOptions
)
{
_cache = cache;
_httpContextAccessor = httpContextAccessor;
_jwtOptions = jwtOptions;
}
public async Task<bool> IsCurrentActiveToken()
=> await IsActiveAsync(GetCurrentAsync());
public async Task DeactivateCurrentAsync()
=> await DeactivateAsync(GetCurrentAsync());
public async Task<bool> IsActiveAsync(string token)
=> await _cache.GetStringAsync(GetKey(token)) == null;
public async Task DeactivateAsync(string token)
=> await _cache.SetStringAsync(GetKey(token),
" ", new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromMinutes(_jwtOptions.Value.ExpiryMinutes)
});
private string GetCurrentAsync()
{
var authorizationHeader = _httpContextAccessor
.HttpContext.Request.Headers["authorization"];
return authorizationHeader == StringValues.Empty
? string.Empty
: authorizationHeader.Single().Split(" ").Last();
}
private static string GetKey(string token)
=> $"tokens:{token}:deactivated";
}
As you can see, there are 2 helper methods that will use the current
HttpContext in order to make things even easier.
Next, let’s create a middleware that will check if the token was
deactivated or not. That’s the reason why we should keep them in cache
– hitting the database with every request instead would probably kill
your app sooner or later (or at least make it really, really slow):
public class TokenManagerMiddleware : IMiddleware
{
private readonly ITokenManager _tokenManager;
public TokenManagerMiddleware(ITokenManager tokenManager)
{
_tokenManager = tokenManager;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if (await _tokenManager.IsCurrentActiveToken())
{
await next(context);
return;
}
context.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
}
}
Eventually, let’s finish our journey with implementing an endpoint for
canceling the tokens:
[HttpPost("tokens/cancel")]
public async Task<IActionResult> CancelAccessToken()
{
await _tokenManager.DeactivateCurrentAsync();
return NoContent();
}
For sure, we could make it more sophisticated, via passing the token
via URL, or by canceling all of the existing user tokens at once
(which would require an additional implementation to keep track of
them), yet this is a basic sample that just works.
Make sure that you will register the required dependencies in your
container and configure the middleware:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddTransient<TokenManagerMiddleware>();
services.AddTransient<ITokenManager, Services.TokenManager>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddDistributedRedisCache(r => { r.Configuration = Configuration["redis:connectionString"];
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
...
app.UseAuthentication();
app.UseMiddleware<TokenManagerMiddleware>();
app.UseMvc();
}
And provide a configuration for Redis in appsettings.json file:
"redis": {
"connectionString": "localhost"
}
Try to run the application now and invoke the token cancellation[sic]
endpoint – that’s it.
Actually the best way to logout is just remove token from the client. And you can make lifetime of tokens short (5-15 minutes) and implement refresh tokens for additions security. In this case there are less chance for attacker to do something with your JWT
If you have implemented the login scenario with the refresh token, You can remove the refresh token from the server and then , and then you should remove the token from the client.

WebTestClient mutateWith apparently not mutating

My (Cucumber) BDD unit test using WebTestClient is failing (with a 403 Forbidden), when I believe it should be passing. After some debugging, I established that this is because the CSRF check is failing, which suggests the mutateWith(csrf()) operation is not working. What am I doing wrong?
My test scenario:
Scenario Outline: Login
Given that player "<player>" exists with password "<password>"
And presenting a valid CSRF token
When log in as "<player>" using password "<password>"
Then program accepts the login
My test steps code (note the presence of client.mutateWith(csrf())):
#SpringBootTest(...)
#AutoConfigureWebTestClient
public class WebSteps {
#Autowired
private WebTestClient client;
...
private WebTestClient.ResponseSpec response;
#Given("presenting a valid CSRF token")
public void presenting_a_valid_CSRF_token() {
client.mutateWith(csrf());
}
#When("log in as {string} using password {string}")
public void log_in_as_using_password(final String player,
final String password) {
response = client.post().uri("/login")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(BodyInserters.fromFormData("username", player)
.with("password", password))
.exchange();
}
#Then("program accepts the login")
public void program_accepts_the_login() {
response.expectStatus().isFound().expectHeader().valueEquals("Location",
"/");
}
...
Despite its name, the mutateWith() method does not really mutate its object. Rather, it returns a new object that has had the mutation applied. Therefore instead of writing
#Given("presenting a valid CSRF token")
public void presenting_a_valid_CSRF_token() {
client.mutateWith(csrf());
}
write
#Given("presenting a valid CSRF token")
public void presenting_a_valid_CSRF_token() {
client = client.mutateWith(csrf());
}
This error is more likely to occur in a Cucumber test because of the way that test steps alter shared state (The client object), rather than use a fluent API with a long chain of calls.

How to forward jwt token in Vert.x REST service

I have a Vert.x REST service that receive requests with jwt tokens, and I want to call my another REST service passing received token. Between router handler and WebClient call I have a business logic layer. My question is if there is a method to provide token to webClient other than passing it explicitly through my business logic layer? In other words is it possible to retrieve somehow my RoutingContext and token from e.g. vertxContext or an other component?
Example code demonstrating what I would like to achieve:
Verticle cass
public class RestApiVerticle extends AbstractVerticle {
businessLogicService service;
#Override
public void start() throws Exception {
initService();
HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
JWTAuth authProvider = JWTAuth.create(vertx, getAuthConfig());
router.route("/*").handler(JWTAuthHandler.create(authProvider));
router.route("/somePath").handler(this::handleRequest);
server.requestHandler(router::accept).listen(config().getInteger("port"));
}
private void handleRequest(RoutingContext context){
service.doSomeBusinessLogic(); //I could pass context here, but I thing this is not a proper way to do it, as business logic should not know about RequestContext
}
private void initService(){
ExternalAPICaller caller = new ExternalAPICaller(WebClient.create(vertx));
service = new BusinessLogicService(caller);
}
private JsonObject getAuthConfig() {
return new JsonObject();
}
}
BusinessLogicService:
public class BusinessLogicService {
ExternalAPICaller caller;
public BusinessLogicService(ExternalAPICaller caller){
this.caller = caller;
}
public void doSomeBusinessLogic(){
caller.doSth();
}
}
ExternalAPICaller:
public class ExternalAPICaller {
WebClient client;
public ExternalAPICaller(WebClient client){
this.client = client;
}
public void doSth(){
String TOKEN = null; // I would like to retrive here my token from some vertx component
client.post("externalAPIpath")
.putHeader("Authorization", "Bearer" + TOKEN)
.send(ctx -> {
//(..)
});
}
}
My implementation is in JavaScript (Node.js/Express), but I used cookies to send the JWT to the client.
res.cookie("auth", token);
return res.redirect(`http://localhost:3000/socialauthredirect`);
When you call your do business logic method you could pass the request authorization header value as it contains your untouched jwt token. Then on your web client add a header with that value and of course named authorization and your token is forwarded to the next service.

how to get absoluteURIbuilder to return newly created resource in loaction header in JAX-RS?

Consider the following example:
create new user
POST request for this url : www.example.com/accounts/checking/users
GET user detail
GET request for this url : www.example.com/accounts/checking/user/1
return resource for user with id 1.
Now my question is
when I post to www.example.com/accounts/checking/users for a new user creation,
a new user is created and its resource uri must be returned in the location header. I am having trouble building this uri using getAbsoluteURIbuilder method.
Here is what I have
#Path("/accounts)
public class AccountResourceService {
#Context
UriInfo uriInfo
//here 'type' can be checking or saving account
#GET
#PATH("{type}/user/{id}")
#Produces(MediaType.APPLICATION_JSON)
public class getUserInfo(final #PathParam("type") String type, #PathParam("id"), int id)
{
//return user-specific resource for the given id
}
#POST
#PATH("{type}/users")
#Produces(MediaType.APPLICATION_JSON)
public class CreateUser(final #PathParam("type") String type, AccountCreateRequest request)
{
if type.equals("checking"){
User user = createAccount(request);
URI uri = uriInfo.getAbsolutePathBuilder().path(user.getId().toString()).build();
System.out.println("created uri is " + uri.toString);
return Response.created(uri).build();
}
else {
//do something else
}
}
}
The uri I am returning in POST method above is
http://localhost:8080/accounts/checking/users/1 //note users
But the expected uri is
http://localhost:8080/accounts/checking/user/1 //not user
how can I get this to work?
Just to put all the comments into an answer
From a design perspective, I say you just get rid of the user resource path, and make it users/{id}. This is common and an accepted way. users is a collection resource. When you go to /users, you get the collection of users. When you go to users/234, you get the user with id 234, in that collection of users.
But sine you can change this, you can just build the uri with some string manipulation. Get the getAbsolutePath() from the UriInfo, then just remove the s. Then you can create a new UriBuilder with that string. As seen in the below example
#Path("/accounts")
public class AccountsResource {
#POST
#Path("/{type}/users")
#Consumes(MediaType.APPLICATION_JSON)
public Response createUser(#PathParam("type") String type,
#Context UriInfo uriInfo) {
String newUri = uriInfo.getAbsolutePath().toString();
newUri = newUri.substring(0, newUri.length() - 1);
UriBuilder builder = UriBuilder.fromPath(newUri);
URI uri = builder.path("1234").build();
return Response.created(uri).build();
}
}
This will return /accounts/checking/user/1234