I need to authentication SOAP header and give the response accordingly in my web service. The authentication header will verify the userId and password information.
If authenticated, then SOAP body of the request will be processed, else Invalid Authentication message will be returned
Below is my controller
package com.ws.controller;
#Endpoint
public class MyWSEndpoint
#Autowired(required=true)
private WSService service;
#PayloadRoot(localPart = "myWSRequest", namespace = Constants.TARGET_NAMESPACE)
public #ResponsePayload MyWSResponse getInfo(#RequestPayload MyWSRequest request) throws Exception
{
MyWSResponse response = new MyWSResponse();
response=service.getResponse();
return response;
}
}
i'm using Spring + SOAP
Please advise if i do right or better approach to solve.
Any working samples or projects will be much appreciated
Related
my main issue is this:
When the soap message is encrypted, the PayloadRootAnnotationMethodEndpointMapping is unable to map the soap message because The security interceptor did not have yet the time to decipher it. The solution is to replace #PayloadRoot with #SoapAction.
When a soap message is received, spring-ws calls first the PayloadRootAnnotationMethodEndpointMapping then SoapActionAnnotationMethodEndpointMapping
#Endpoint
public class assignedSubscriberNumberNotify {
private static final String NAMESPACE_URI = "http://test.aek.seavus.com/";
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "ToOperatorChangeInASSNNotify")
#SoapAction("http://www.test.si/toOperatorChangeInASSNNotify")
#ResponsePayload
public void toOperatorChangeInASSNNotify(#RequestPayload ToOperatorChangeInASSNNotify request){
}
}
How can I decrypt request if client is unable to add SoapAction to the header?
tnx
miha
I have a question that might be really simple but I have been stuck at it for a while now. I have a program that receives requests and then forwards them in the correct instance of an third party application.
I keep on getting 401/Unauthorized and I have been told that all I need to do to make it work is that "I will get a request from the client with an authentication header and that all I need to do to get rid of the 401 response and get 200 is to add that authentication header to my request. I dont understand how I can get this header in the first place, or add it to my request.
Any pointer, link, or answer would be greatly appreciated.
Thank you
#RestController #Slf4j
#RequestMapping(Endpoints.PROVIDER.ROOT)
#PreAuthorize("#permissions.checkIfAdmin()")
public class AdminController {
#PostMapping(Endpoints.ADMIN.ACTIONS)
public ResponseEntity<ActionResponse> actions(#RequestBody ActionRequest actionsRequest) {
Autowire HttpServletRequest
#Autowired
HttpServletRequest request;
And fetch header through method request.getHeader("Authorization")
Note - Authorization is the name of the header I am trying to fetch.
Below is an example of similar issue. I am reading authorization header from my current request and passing it as header parameter to another request
public class UserDetailsService
{
#Autowired
WebClient.Builder webClientBuilder;
#Autowired
HttpServletRequest request;
#Value("${common.serverurl}")
private String reqUrl;
Logger log = LoggerFactory.getLogger(UserDetailsService.class);
public UserReturnData getCurrentUser()
{
log.info("Making API Call to fetch current user");
try
{
UserReturnData userDetails = webClientBuilder.build()
.get()
.uri(reqUrl+"user/me")
.header("Authorization", request.getHeader("Authorization"))
.retrieve()
.bodyToMono(UserReturnData.class)
.block();
return userDetails;
}
catch(Exception e)
{
log.info("Error API Call to fetch current user " + e);
return null;
}
}
Problem
I'm trying to create an app that uses Auth0 SPA + React on the frontend to auth users without ever having to deal with passwords. Then, I'd like to secure any endpoints I create using an Auth server that I'm required to create using the Spring Framework.
Just to clarify, the flow would be
Frontend ->
Auth through Auth0 ->
Redirect to users dashboard on frontend ->
Make HTTP request to endpoint sending JWT returned from Auth0 ->
Endpoint makes request to my Auth Server sending JWT returned from Auth0 ->
Auth server either either returns 401 or user object based on JWT ->
Endpoint grabs data specific to that user from DB ->
Returns data to frontend
I've managed to get my frontend to work just fine using the Quickstart Guide that Auth0 provides but I'm having a lot of trouble figuring out how to get my Auth Service to verify the user.
I believe I've come to the conclusion that I need to create an "API" on Auth0 and grab an access token and use that to validate the JWT, which in this case is just the access token and not the JWT that my frontend contains. I've also got this part working but there doesn't seem to be a way to know who the user is. When testing this "API", after sending a valid request I am returned
{
"iss": "https://${username}.auth0.com/",
"sub": "${alphanumericCharacters}#clients",
"aud": "${ApiIdentifier}",
"iat": ${issuedAt},
"exp": ${expiresAt},
"azp": "${alphanumericCharacters}",
"gty": "client-credentials"
}
While it's good to know I'm on the right track I can't seem to figure out what to do with this response to find the user.
Expected
I expect to be able to identify a specific user after validating an access_token from my Auth Service
Code
I don't have much code to show but I'll provide what I can from my Auth Service
SecurityConfiguration.java
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Value("${auth0.audience}")
private String audience;
#Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
private String issuer;
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.mvcMatchers("/api/validate")
.authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
#Bean
JwtDecoder jwtDecoder() {
NimbusJwtDecoderJwkSupport jwtDecoder = (NimbusJwtDecoderJwkSupport)
JwtDecoders.fromOidcIssuerLocation(issuer);
OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(audience);
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuer);
OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
jwtDecoder.setJwtValidator(withAudience);
return jwtDecoder;
}
}
AudienceValidator.java
public class AudienceValidator implements OAuth2TokenValidator<Jwt> {
private final String audience;
public AudienceValidator(String audience) {
this.audience = audience;
}
public OAuth2TokenValidatorResult validate(Jwt jwt) {
OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null);
if (jwt.getAudience().contains(audience)) {
return OAuth2TokenValidatorResult.success();
}
return OAuth2TokenValidatorResult.failure(error);
}
}
ValidateController.java
#RestController
#RequestMapping("/api/validate")
public class ValidateController {
#GetMapping
public boolean validate() {
return true; // only returns if successfully authed
}
}
After reading through the docs I've found my solution.
It turns out that I don't need to create an "API" on Auth0 but instead need to use my Applications endspoint(s) from Auth0. Auth0 provides many endpoints based on your account that you can take advantage of from any of your applications (CLI, Server, Client, etc.) as long as you can:
Make an HTTP Request
Provide credentials
So the way to get a users information is explained here.
Data flow
Using my projects auth/data flow it's pretty much:
Using #auth0/auth0-spa-js on the frontend, you can grab a users access token after a successful auth by using the getTokenSilently() method.
Send up HTTP request to your Rest Service
Rest Service sends that token to your Auth Service
Auth Service sends GET request to https://myAuth0Username.auth0.com/userinfo with the Authorization: Bearer ${access_token} header. Example
If successfully authed from Auth0
Returns your users information such as "name", "email", etc.
Else
Returns a 403 Forbidden HTTP Status
Auth Service then returns user object to Rest Service
Rest Service then does necessary logic for that endpoint (DB query, another HTTP request, etc.)
Example Auth Service endpoint to validate tokens and return a user
ValidateController.java
package x.SpringTodo_Auth.Controllers;
import x.SpringTodo_Auth.Models.User;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
#RestController
#RequestMapping("/api/validate")
public class ValidateController {
#GetMapping
public Object validate() {
// Create and set the "Authorization" header before sending HTTP request
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + access_token);
HttpEntity<String> entity = new HttpEntity<>("headers", headers);
// Use the "RestTemplate" API provided by Spring to make the HTTP request
RestTemplate restTemplate = new RestTemplate();
Object user = restTemplate.exchange("https://myAuth0Username.auth0.com/userinfo", HttpMethod.POST, entity, User.class);
return user;
}
}
User.java (This is the class passed to the restTemplate.exchange(...) method as the last argument
package x.SpringTodo_Auth.Models;
public class User {
private String sub;
private String given_name;
private String family_name;
private String nickname;
private String name;
private String picture;
private String locale;
private String updated_at;
private String email;
private boolean email_verified;
// Getters/setters (or you can use Lombok)
}
I have a front-end react application, where i make a request to a REST Jax-RS backend server.
Here is the request being sent
deletePost = (post) =>{
return deleter(config.restUrl + `posts/${post}`)
}
Here i get the standart URL for my backend, with a 'deleter' function, which is just a standardized fetch delete method (which has also worked with other entities as well).
Here is my Jax-RS resource:
#DELETE
#Consumes(APPLICATION_JSON)
#Produces(APPLICATION_JSON)
#Path("/{id: [0-9]+}")
public Response deletePost(#HeaderParam("authorization") String token, #PathParam("id") Integer id) throws ResourceNotFoundException, AuthenticationException
{
AuthenticationContext authenticationContext = authenticationFacade.authenticateBearerHeader(token);
Post post = postFacade.delete(authenticationContext, id);
return Response.ok(gson.toJson(PostDTO.basic(post))).build();
}
The problem is that it gives me an error saying that the form is HTML/text:
MessageBodyWriter not found for media type\u003dtext/html, type\u003dclass com.group3.sem3exam.rest.dto.PostDTO, genericType\u003dclass com.group3.sem3exam.rest.dto.PostDTO
Since it's implying that it is the PostDTO that has the error, I went to check the basic method, which converts the entity into a Data Transfer Object, to be posted back to the client side.
public static PostDTO basic(Post post)
{
return new PostDTO(
post.getId(),
post.getContents(),
post.getCreatedAt(),
null,
ImageDTO.list(post.getImages(), ImageDTO::withoutUser)
);
}
Here it just calls the method which returns a new instance of the object.
I have not seen this error before, and I'm not sure how to handle it?
Try
return Response.status(Status.OK).entity(new Gson().toJson(PostDTO.basic(post))).build();
I've created a self hosted Java applicataion and I would like to use Google sign in to log in into. I followed the follwong example:
https://developers.google.com/identity/sign-in/web/
That of course work, but now I'm getting a little confuse on how I can authorize the calls on the server. In the backend I'm using Grizzly+Jersey.
As described on the Google Sig-In documentation, you can use Google API Client Library for Java in order to check the authentication token on server side.
Client side
After a user successfully signs in, get the user's ID token:
function onSignIn(googleUser) {
var idToken = googleUser.getAuthResponse().id_token;
...
}
And send the idToken to the server in every request using the standard HTTP Authorization header.
Server side
You can use a filter to perform authentication and/or authorization.
To bind filters to your REST endpoints, JAX-RS provides the meta-annotation #NameBinding and can be used as following:
#NameBinding
#Retention(RUNTIME)
#Target({TYPE, METHOD})
public #interface Secured { }
The #Secured annotation will be used to decorate a filter class, which implements ContainerRequestFilter, allowing you to handle the request, get and validate the token.
The ContainerRequestContext helps you to extract information from the HTTP request.
The #Provider annotation marks an implementation of an extension interface that should be discoverable by JAX-RS/Jersey runtime during a provider scanning phase.
#Secured
#Provider
#Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Get the token header from the HTTP Authorization request header
String token =
requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// Check if the token is present
if (token == null || token.isEmpty()) {
throw new NotAuthorizedException("Token must be provided");
}
// Validate the token
validateToken(token);
}
private void validateToken(String token) {
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier
.Builder(new NetHttpTransport(), new GsonFactory())
.setAudience(Arrays.asList(CLIENT_ID))
.build();
GoogleIdToken idToken = verifier.verify(token);
if (idToken != null) {
Payload payload = idToken.getPayload();
System.out.println("User ID: " + payload.getSubject());
} else {
throw new NotAuthorizedException("Invalid token.");
}
}
}
To bind the filter to your endpoints methods or classes, annotate them with the #Secured annotation created above. For the methods and/or classes which are annotated, the filter will be executed.
#Path("/example")
public class MyEndpoint {
#GET
#Path("{id}")
#Produces("application/json")
public Response myUnsecuredMethod(#PathParam("id") Long id) {
// This method is not annotated with #Secured
// The security filter won't be executed before invoking this method
...
}
#DELETE
#Secured
#Path("{id}")
#Produces("application/json")
public Response mySecuredMethod(#PathParam("id") Long id) {
// This method is annotated with #Secured
// The security filter will be executed before invoking this method
...
}
}
In the example above, the security filter will be executed only for mySecuredMethod(Long) because it's annotated with #Secured.