How to assign an OidcClient to a specific RestClient in Quarkus? - quarkus

I have multiple OidcClients (quarkus.oidc-client.<NAME>.auth-server-url, ...) as well as multiple RestClients (quarkus.rest-client.<NAME>.url, ...) configured.
Now I want each OidcClient to handle a specific RestClient, by which I mean automatically fetching and refreshing tokens and adding them as Bearer Token to the header.
Quarkus handles this automatically when only one OidcClient exists for multiple RestClients, but for multiple clients I'm a bit lost.
The most natural way for me would be something like
#Path("/endpoint")
#NamedOidcClient("client-1")
#RegisterRestClient(configKey="client-1")
public interface RestClient {
...
but that's not working of course. I'm surely not the first one to have this problem, but I haven't been able to find anything that made it work (maybe using OidcClientFilterwould somehow do the trick?)
Any help would be appreciated, thanks!

Related

Is it necessary to use the form to transfer data to the server?

I'm new to backend programming. I chose the laravel framework. Already learned the basics. During the study, the question arose: is it necessary to use the form to transfer data to the server ?. For example: the deletion route looks like this to me
Delete.
If I leave it, will it be a mistake? Maybe advise an article or something. Thanks in advance
Short answer is no, it's not necessary, but you should (if you're bound to HTML only).
The HTTP standard has different methods for different purposes. Using an anchor tag will always make a HTTP GET request to the link/server, which is not ideal, GET request should never change the remote (server) state, that's a job other methods (POST, PUT, DELETE, PATCH), you should try to use the method that better describe what you're trying to do: in your case I suppose you're trying to delete a complaint, so a DELETE or POST is what you're looking for.
The only way to use make a non GET request in plain HTML* is to use <form>. Also if you're planning to use a method different from POST you should take a look at Laravel's #method here
Mind that if you can and want to use JavaScript to perform your request you totally can, dropping the requirement to have use form (docs and docs).

how to pass object on Spring's REST Template using get

I am using a Spring REST template to pull data using POST and everything is working fine.
ResponseEntity<MyObject> resp= restTemplate.postForEntity("url", inputParam, MyObject.class);
But now since I am not doing any POST operation, I want to change it to GET. I can do this by adding all input params as url parameters and do:
ResponseEntity<MyObject> resp= restTemplate.getForEntity("url",MyObject.class);
But the problem is, inputParam has alot of parameters, so preparing the url manually is not the best solution. Also GET requests have length restrictions.
Is there any other better solution for handling this?
First of all, I think your second line should say getForEntity().
Secondly, there are numerous URL builder class options if you google around (including ones from Spring). So, I would use a URL building class to prepare the URL rather than manually doing it yourself which can get messy.
https://www.baeldung.com/spring-uricomponentsbuilder
https://square.github.io/okhttp/3.x/okhttp/okhttp3/HttpUrl.html
https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/UriBuilder.html
Length Restriction
There's a good SO entry here noting length restrictions of common browsers; so if its going through a browser then I'd stick to POST if you're potentially over the 2000 lower limit they suggest.
Technically there shouldn't be a limit according to https://www.w3.org/2001/tag/doc/get7#myths.
I think on a lot of back-end technologies there is no limit. So, if this is API-only and not going through a browser (like back-end to back-end) then you may be able to ignore those limits. I'd recommend looking into that specifically though and testing it with your back-end.
UniRest
Also, as a personal recommendation, I have found UniRest to be an amazingly useful REST client which makes most of my code much cleaner :). If you have time, maybe try giving that a shot.
http://unirest.io/java.html

Couchdb conceptual problems

As I understand, to update any object with couchdb. I have to send the whole object back since it is actually "inserting" a new revision for the same id. This is all neat and works quite well.
But then I have a problem, I'm not so sure how should I handle that. I have an object that can't be sent to my user completely. I have to hide certain informations such as password hash.
The data is sent to the client, the revision is sent too. Now when I try to update my object I have one problem. Since some data is missing, the update will erase the attributes that are missing from my user.
That said, the easiest way I have is to get the object from couchdb, check if id and rev matches. If it does match, merge the object with the missing attributes. It will work pretty well and I can support deleting attributes too.
Then using this technique, I could add my objects to a cache that will reduce the time to query frequent objects from the database. If the object can be updated, then clear the cache for that id. If the object is newer, then I'll have to handle the error or merge the object.
Is there any better "good way" to handle this problem?
edit
After thinking about it during the night, I think I found a much much better solution. Instead of having my username and password inside my profile. I'll separate the identification object from the use profile.
In other words, I'll have to split up the object as much as possible to keep things isolated... On the plus side, I can add multiple authentication for one profile without messing with the profile itself. I can return profiles and anything necessary without returning any secret object.
It will complicate a bit the logic of insertion but it should be quite easy...
Get 1 id from couchdb using the uuid api "_uuids"
Insert password authentications (username, password, profile_id) using that uuid
If succeed, insert profile using the uuid that we got at 1
If anything wrong happen, rollback and tell the users what's wrong.
Also the nice thing about this method is that I can add access_token for oauth2 using the profile id and the logic will be almost the same as password, the auth type will differ but any auth type should work almost the same.
Yeah, extracting the secret stuff from the profile documents sounds like the way to go.

Combining GET and POST in Sinatra (Ruby)

I am trying to make a RESTful api and have some function which needs credentials. For example say I'm writing a function which finds all nearby places within a certain radius, but only authorised users can use it.
One way to do it is to send it all using GET like so:
http://myapi.heroku.com/getNearbyPlaces?lon=12.343523&lat=56.123533&radius=30&username=john&password=blabla123
but obviously that's the worst possible way to do it.
Is it possible to instead move the username and password fields and embed them as POST variables over SSL, so the URL will only look like so:
https://myapi.heroku.com/getNearbyPlaces?lon=12.343523&lat=56.123533&radius=30
and the credentials will be sent encrypted.
How would I then in Sinatra and Ruby properly get at the GET and POST variables? Is this The Right Way To Do It? If not why not?
If you are really trying to create a restful API instead if some URL endpoints which happen to speak some HTTP dialect, you should stick to GET. It's even again in your path, so you seem to be pretty sure it's a get.
Instead of trying to hide the username and password in GET or POST parameters, you should instead use Basic authentication, which was invented especially for that purpose and is universally available in clients (and is available using convenience methods in Sinatra).
Also, if you are trying to use REST, you should embrace the concept of resources and resoiurce collections (which is implied by the R and E of REST). So you have a single URL like http://myapi.heroku.com/NearbyPlaces. If you GET there, you gather information about that resource, if you POST, you create a new resource, if you PUT yopu update n existing resource and if you DELETE, well, you delete it. What you should do before is th structure your object space into these resources and design your API around it.
Possibly, you could have a resource collection at http://myapi.heroku.com/places. Each place as a resource has a unique URL like http://myapi.heroku.com/places/123. New polaces can be created by POSTing to http://myapi.heroku.com/places. And nearby places could be gathered by GETing http://myapi.heroku.com/places/nearby?lon=12.343523&lat=56.123533&radius=30. hat call could return an Array or URLs to nearby places, e.g.
[
"http://myapi.heroku.com/places/123",
"http://myapi.heroku.com/places/17",
"http://myapi.heroku.com/places/42"
]
If you want to be truly discoverable, you might also embrace HATEOAS which constraints REST smentics in a way to allows API clients to "browse" through the API as a user with a browser would do. To allow this, you use Hyperlink inside your API which point to other resources, kind of like in the example above.
The params that are part of the url (namely lon, lat and radius) are known as query parameters, the user and password information that you want to send in your form are known as form parameters. In Sinatra both of these type of parameters are made available in the params hash of a controller.
So in Sinatra you would be able to access your lon parameter as params[:lon] and the user parameter as params[:user].
I suggest using basic or digest authentication and a plain GET request. In other words, your request should be "GET /places?lat=x&lon=x&radius=x" and you should let HTTP handle the authentication. If I understand your situation correctly, this is the ideal approach and will certainly be the most RESTful solution.
As an aside, your URI could be improved. Having verbs ("get") and query-like adjectives ("nearby") in your resource names is not really appropriate. In general, resources should be nouns (ie. "places", "person", "books"). See the example request I wrote above; "get" is redundant because you are using a GET request and "nearby" is redundant because you are already querying by location.

Django client side query construction

I'm making a pretty standard AJAXy (well, no XML actually) web page. The browser makes a bunch of API queries that return JSON to run the site. The problem is, I need to add to the API interface each time the page needs to do something new. The new API interface is usually little more than a database query followed by mapping the returned objects to JSON.
What I'd like to do is to get rid of all that server-side duplication and just have the page make database requests itself (using the model interface), but in a way that is safe (i.e. just read only ones). I think this would amount to an interface for constructing Q objects using JSON or something like that, and then send that up to the server, run the query, and return the results. Before I go making my own half-broken architecture for this, I'm wondering if this has already been done well. Also, is this even the best way to go about eliminating this duplication?
Thanks
Search multiple fields of django model without 3rd party app
Django SQL OR via filter() & Q(): Dynamic?
Generate a django queryset based on dict keys
Just replace with operator.and_ where appropriate.

Resources