I am quite new in Spring Cloud Feign and trying to send HTTP header which is required by service provider. Here is the code snippet
#FeignClient(name = "authentication", url = "http://localhost:3000/api")
public interface AuthenticationService {
#PostMapping(value = "/login")
JsonNode login(#RequestHeader("Origin") String origin, #RequestBody LoginParams parameters);
}
When I try to send Origin header then server does not receive this header. But other headers like referer or x-access-token are received at server successfully.
I have also tried using RequestInterceptor and was not successful to send Origin as header.
#Component
public class HeaderInterceptor implements RequestInterceptor {
#Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.removeHeader("origin");
requestTemplate.header("origin", "http://amjad.localhost:3000/");
}
}
Any hint or help would be much appreciated.
cheers!
I had similar issue with OpenFeign. "Origin" header was blocked by defult, because it was using old Java http client.
After change to OkHttp Client, "Origin" was sent.
Related
I have an web application providing an REST API endpoints, secured with spring security and SSO Keycloak.
My web application works fine with protection on and I can access REST API endpoints using web browser, after authentication on keycloak and redirect back to endpoint. I am getting expected JSON response, which mean user and role should be configured correctly.
But when i want to call a provided REST API endpoint from another web application or using Postman, i have every time an error 401 error: unauthorized.
In the header of the request I am putting:
"Authorization": "Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgO...." token.
I am able to fetch this token from keycloak in consumer web application and also when I am making a request using postman.
My Keycloak configuration in my spring security config:
#KeycloakConfiguration
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
/**
* Registers the KeycloakAuthenticationProvider with the authentication manager.
*/
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
/**
* Defines the session authentication strategy.
*/
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.authorizeRequests()
.antMatchers("/api/v1/**").hasRole("USER")
.antMatchers("/admin/**", "/app/**").hasRole("ADMIN")
.anyRequest().permitAll();
}
}
My keycloak.json file:
{
"realm": "realm-name",
"auth-server-url": "https://auth.server.com/auth/",
"ssl-required": "external",
"resource": "resource-name",
"verify-token-audience": true,
"credentials": {
"secret": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
"use-resource-role-mappings": true,
"confidential-port": 0
}
My method in the controller of the api:
#RestController
#RequestMapping("/api/v1")
public class WakeMeUpController {
#RequestMapping(value = "/test", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
public String testMeUp() {
return "I am tested!";
}
}
This is a part of my client configuration in keycloak:
keycloak Client screen
Rest keycloak config is how it is coming by default.
Thx for your help!
Thank you. The problem was into audience configuration in keycloak.
For a client, you need to configure new Mapping under Client -> <client_name> -> Mappers and add another Mapping with mapper type 'Audience' and appropriate 'Included Client audience' (i choose client id i have used to make request)
Also another problem that i have faced after i solve this one, was that user was authenticated but was forbidden the access to endpoint.
Explicitly adding role into client configuration itself and assigning this role to the user solve it and it is working.
From huge help was setting spring logging to DEBUG
logging.level.org.springframework.security=DEBUG
And also XXX-Authentication header in server response that gives better description what the issue is.
I use Restlet integration with Jetty in my project. I would need to remove the "Server" header from the response as it discloses server information. But since I use Restlet integration with Jetty (restlet, jetty, org.restlet.ext.jetty.jar) the HttpConfiguration object is instantiated inside Restlet and not in my code. So I am not able to set "_sendServerVersion" as false and hence not able to remove the server header from the response. How to remove the server header from the response in this case ?
The best way to create a Filter and remove the header through the Filter:
public class ServerFilter extends Filter {
public ServerFilter(Context context) {
super(context);
}
#Override
protected void afterHandle(Request request, Response response) {
response.getHeaders().set("Server", null);
super.afterHandle(request, response);
}
}
Then use it like:
ServerFilter serverFilter = new ServerFilter(getContext());
serverFilter.setNext(router);
return serverFilter;
See: https://javadocs.restlet.talend.com/2.4/jee/api/index.html for documentation
I've made a REST API and I'd like to do a post request to one of the endpoints from my ESP8266, but I can't manage to do so.
The code inside the loop so far:
HTTPClient http; //Declare object of class HTTPClient
http.begin("http://localhost:5000/api/users/5b1e82fb8c620238a85646fc/arduinos/5b243dc666c18a2e10eb4097/data");
http.addHeader("Content-Type", "text/plain");
http.addHeader("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjViMWU4MmZiOGM2MjAyMzhhODU2NDZmYyIsImlhdCI6MTUyOTEwMTc5MiwiZXhwIjoxNTI5MTE2MTkyfQ.2O6knqriuFoEW9C2JQKRlM3D0DNnzqC7e7gpidy3pWU");
http.end();
The problem is that I don't know how to set the body of the request.
It should be a json with a single key called "value". For instance:
{
"value":101
}
Anyone knows how to do it? Also it's probable that I should use the ip instead of "localhost".
Thanks in advance.
Use ArduinoJson Library here. Then you can build your HTTP body.
StaticJsonBuffer<300> JSONbuffer; //Declaring static JSON buffer
JsonObject& JSONencoder = JSONbuffer.createObject();
JSONencoder["value"] = value_var;
char JSONmessageBuffer[300];
JSONencoder.prettyPrintTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
HTTPClient http; //Declare object of class HTTPClient
http.begin("API end point here"); //Specify request destination
http.addHeader("Content-Type", "application/json"); //Specify content-type header
int httpCode = http.POST(JSONmessageBuffer); //Send the request
String payload = http.getString(); //Get the response payload
Then use the above sample code to encapsulate JSON and send it to the API endpoint.
I receive request via a router :
#Bean
public RouterFunction<ServerResponse> routerFunction() {
return nest(path(API_PATH), route(GET("/"), indexHandler::getIndex));
}
handle by a method :
public Mono<ServerResponse> getIndex(ServerRequest request) {
...
}
I need to extract the url use to request the service, I have different cases, sometimes request are direct to service, sometimes request go through proxy (and add X-Forwarded-Path,X-Forwarded-Path headers).
Is there a helper method, to extract this details from ServerRequest object ?
I'm trying to get some client data inside the UserAuthenticationSecurityCheck.validateCredentials method.
The IP Address is the most important for it.
In the other adapters, I'm using the HttpServletRequest:
#Context
protected HttpServletRequest request;
But this request object is always null in the UserAuthenticationSecurityCheck.
How can I get client data (IP Address or the headers) in this class?
You cannot inject the HttpServletRequest into a security check object(by design - not a bug). Once the user is authenticated, then you can make another Adapter Call, from where you can get the desired details. Unfortunately this is not documented anywhere (not to my knowledge at least).
I had a similar issue with AdapterAPI class as described here.
You can get request in security adapter but not from #Context.
Just override authorize method:
#Override
public void authorize(Set<String> scope, Map<String, Object> credentials, HttpServletRequest request, AuthorizationResponse response) {
//TODO use request object
super.authorize(scope, credentials, request, response);
}