Creating instance vs injecting with annotation in java rest api - java

I have an authentication resource, where I want to authenticate users, as they log in via my front-end application.
I have a facade object, which i use to authenticate the user, and create a token as such
#GET
#Path("login")
#Produces(APPLICATION_JSON)
public Response authenticateUser(#FormParam("email") String email, #FormParam("password") String password) {
try {
//skal måske ændres til bruger
User user = authenticationFacade.authenticateUser(email, password);
String token = authenticationFacade.generateAuthenticationToken(user);
return Response.ok(gson.toJson(user)).header(AUTHORIZATION, "Bearer " + token).build();
but i have a few doubts, about how to create my authentication facade, i have seen people use this convention:
#Inject
private AuthenticationFacade authenticationFacade;
and I have seen somebody, just instantiate the object:
private AuthenticationFacade authenticationFacade = new AuthenticationFacade();
In this context, what difference would it make, and what would be the best practice?

Related

Oauth 2 spring RestTemplate login with refresh token

What I wanna achieve
So I have a client application in java (JavaFX + Spring-boot hybrid-application). You can have a look at it here https://github.com/FAForever/downlords-faf-client . So till now we stored username/ password if the user wished to be kept logged in which is obviously a pretty bad idea. So now I wanna store the refreshtoken and then log the user in with that.
What it looks like now
See here
ResourceOwnerPasswordResourceDetails details = new ResourceOwnerPasswordResourceDetails();
details.setClientId(apiProperties.getClientId());
details.setClientSecret(apiProperties.getClientSecret());
details.setClientAuthenticationScheme(AuthenticationScheme.header);
details.setAccessTokenUri(apiProperties.getBaseUrl() + OAUTH_TOKEN_PATH);
details.setUsername(username);
details.setPassword(password);
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(details);
restOperations = templateBuilder
// Base URL can be changed in login window
.rootUri(apiProperties.getBaseUrl())
.configure(restTemplate);
What I found so far
I found out that restTemplate.getAccessToken().getRefreshToken() will give me the refreshtoken I want to save and later so to keep the user logged in.
What I can not figure out
I can not find a way to create a OAuth2RestTemplate with an refresh token only. Is that even possible? Can someone point me in the right direction? Maybe link me some articles to read? Is this the right place to read?
I do not think this is possible with an OAuth2RestTemplate, but you can reimplement the desired parts yourself. I'd like to share an example with your for OAuth password login to Microsofts flavour of OAuth2 (Azure Active Directory). It does miss the piece of fetching a new token from an existing refresh token yet, but I added a comment where you need to add it.
A simple way to mimic OAuthRestTemplates behavior is a custom ClientHttpRequestInterceptor which delegates the token fetching to a dedicated Spring service component, that you append to your RestTemplate:
#RequiredArgsConstructor
#Slf4j
public class OAuthTokenInterceptor implements ClientHttpRequestInterceptor {
private final TokenService tokenService;
#NotNull
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().add("Authorization", "Bearer " + tokenService.getRefreshedToken().getValue());
return execution.execute(request, body);
}
}
This interceptor can be added to your primary RestTemplate:
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
interceptors.add(globalOAuthTokenInterceptor);
restTemplate.setInterceptors(interceptors);
The token service used in the interceptor holds the token in a cache and on request checks for the expiry of the token and if required queries a new one.
#Service
#Slf4j
public class TokenService {
private final TokenServiceProperties tokenServiceProperties;
private final RestTemplate simpleRestTemplate;
private OAuth2AccessToken tokenCache;
public TokenService(TokenServiceProperties tokenServiceProperties) {
this.tokenServiceProperties = tokenServiceProperties;
simpleRestTemplate = new RestTemplateBuilder().
build();
}
public OAuth2AccessToken getRefreshedToken() {
if (tokenCache == null || tokenCache.isExpired()) {
log.debug("Token expired, fetching new token");
tokenCache = refreshOAuthToken();
} else {
log.debug("Token still valid for {} seconds", tokenCache.getExpiresIn());
}
return tokenCache;
}
public OAuth2AccessToken loginWithCredentials(String username, String password) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("grant_type", "password");
map.add("resource", tokenServiceProperties.getAadB2bResource());
map.add("client_id", tokenServiceProperties.getAadB2bClientId());
map.add("username", username);
map.add("password", password);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
return simpleRestTemplate.postForObject(
tokenServiceProperties.getAadB2bUrl(),
request,
OAuth2AccessToken.class
);
}
private OAuth2AccessToken refreshOAuthToken() {
return loginWithRefreshToken(tokenCache.getRefreshToken().getValue());
}
public OAuth2AccessToken loginWithRefreshToken(String refreshToken) {
// add code for fetching OAuth2 token from refresh token here
return null;
}
}
In this code example you would once login using username and password and afterwards all further logins would be using the refresh token. If you want to use the refresh token directly, you use the public method, otherwise it will be done internally.
Since the login code is specifically written for login to Microsoft AAD, you should recheck the MultiValueMap parameters.
TokenServiceProperties are straightforward:
#Data
public class TokenServiceProperties {
private String aadB2bUrl;
private String aadB2bClientId;
private String aadB2bResource;
}
Adapt them if needed.
The whole solution has one minor drawback: Instead of one RestTemplate that you usually fetch via depency injection, you now need a second one (a "simple" one) to fetch the OAuth token. In this example we create it in the constructor of the TokenService. However this is in general bad style as it makes it harder for unit testing etc. You could also think about using qualified beans or using a more basic http client in the TokenService.
Another important thing to note: I am using the spring-security-oauth2 package here. If you did not configure Spring Security in your project, this will trigger Spring Security auto-configuration which might not be desired - you can solve this by excluding undesired packages, e.g. in gradle:
implementation("org.springframework.security.oauth:spring-security-oauth2") {
because "We only want the OAuth2AccessToken interface + implementations without activating Spring Security"
exclude group: "org.springframework.security", module: "spring-security-web"
exclude group: "org.springframework.security", module: "spring-security-config"
exclude group: "org.springframework.security", module: "spring-security-core"
}

How to configure Spring Boot OAuth2.0 server with custom UserDetailsService and password validation?

I am trying to configure a Spring Boot OAuth2.0 server on my existing schema. To authenticate a user with my schema, I need to retrieve an encrypted password from my users table and pass it to an external service for validation.
I was able to define a custom UserDetailsService as below, but the default behavior authenticates based on a comparison of the password in the returned UserDetails object and the password from the request.
How can I customize this behavior so that I can use my custom UserDetailsService, but offload the password validation to the external service?
#Component("userDetailsService")
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
#Autowired
private DataSource dataSource;
#Override
public UserDetails loadUserByUsername(final String login) {
String sql = "select encrypted_password from users where login_name = ?";
String encryptedPassword = null;
try {
Connection con = dataSource.getConnection();
PreparedStatement statement = con.prepareStatement(sql));
statement.setString(1, login);
try (ResultSet results = statement.executeQuery()) {
if (results.next()) {
encryptedPassword = results.getLong("encrypted_password");
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return new User(login, encryptedPassword, Arrays.asList(new SimpleGrantedAuthority("simpleAuth")));
}
}
I probably don't have enough details to go off from your question, but I will make some assumptions and give you the best answer I can.
Assumption: User has to login using some sort of credential that you are then doing a loadUserByUsername(loginCreds).
If you don't want to use that specific UserDetails object, you can create an CustomAuthenticationFilter that is configured in your WebSecurity class by using http.addFilterBefore(new CustomAuthenticationFilter(), UsernamePasswordAuthenticationFilter)
From there, you can customize your entire authentication flow. You can choose to create a CustomAuthenticationToken that in turn gets authenticated via CustomAuthenticationProvider. Within this provider, you can do your password check with your 3rd party validation. If it passes, you can load your user object as you have there.

Configuring Authentication Header in Jersey API Client Side

There is following way to configure the authentication header in Jersey API .
//Universal builder having different credentials for different schemes
HttpAuthenticationFeature feature = HttpAuthenticationFeature.universalBuilder()
.credentialsForBasic("username1", "password1")
.credentials("username2", "password2").build();
final Client client = ClientBuilder.newClient();
client.register(feature);
But not able to figure out how to pass extra parameter to authentication header for e.g. IntegatorKey, SendBehalfOf. those are specific REST service call.
In My Case to call REST service need to pass following parameter as part of authentication header.
Username
Password
IntegatorKey
SendBehalfOf
How should I achieve this using the Jersey API ?
You didn't provide enough information in your question. It's hard guessing what you are trying to achieve. You really should consider updating your question with more details.
Having a look at the superficial information you provided, I guess you are trying to access the DocuSign REST API. If so, you could create a ClientRequestFilter, as following:
public class DocuSignAuthenticator implements ClientRequestFilter {
private String user;
private String password;
private String integatorKey;
private String sendBehalfOf;
public DocuSignAuthenticator(String username, String password,
String integatorKey, String sendBehalfOf) {
this.username = username;
this.password = password;
this.integatorKey = integatorKey;
this.sendBehalfOf = sendBehalfOf;
}
#Override
public void filter(ClientRequestContext requestContext) throws IOException {
requestContext.getHeaders().add(
"X-DocuSign-Authentication", getAuthenticationHeader());
}
private String getAuthenticationHeader() {
StringBuilder builder = new StringBuilder();
builder.append("<DocuSignCredentials>");
builder.append("<SendOnBehalfOf>");
builder.append(sendBehalfOf);
builder.append("</SendOnBehalfOf>");
builder.append("<Username>");
builder.append(username);
builder.append("</Username>");
builder.append("<Password>");
builder.append(password);
builder.append("</Password>");
builder.append("<IntegratorKey>");
builder.append(integatorKey);
builder.append("</IntegratorKey>");
builder.append("</DocuSignCredentials>");
return builder.toString();
}
}
And register it when creating a Client instance:
Client client = ClientBuilder.newClient().register(
new DocuSignAuthenticator(username, password, integatorKey, sendBehalfOf));

is it available save the user session on web server?

This code is only for a user.
I'm looking for the way to make this for multiple user.
Please, give me some tips.
To run the batch job, I know that some variables (is_authorized, requestToken and accessToken) should be removed. I tried to use spring-social-tumblr(on github)but it was not easy to use ConnectionRepository. so I tried to use signpost.
After signing with signpost, how could I set the user access token for multi-user?
Is it right to use OAuthConsumer class?
#Controller
public class TumblrProfileController {
private OAuthService service;
private Token requestToken; //should be removed for multiuser
private Token accessToken; // same above
private static final String PROTECTED_RESOURCE_URL = "http://api.tumblr.com/v2/user/info";
#Autowired
private JobLauncher jobLauncher;
#Autowired
private Job job;
#Inject
private ConnectionRepository connectionRepository;
Logger log = LoggerFactory.getLogger(this.getClass());
private boolean is_authorized = false;
#RequestMapping(value = "/tumblr/webrequest", method = RequestMethod.GET)
public String home(OAuthConsumer user, Model model) {
final String PROTECTED_RESOURCE_URL = "http://api.tumblr.com/v2/user/info";
service = new ServiceBuilder().provider(TumblrApi.class).apiKey("clientKey") .apiSecret("secretKey").callback("http://localhost:8080/pen/tumblr/login").build();
log.info("Fetching the Request Token...");
// Obtain the Request Token
requestToken = service.getRequestToken();
log.info("Now go and authorize Scribe here:");
String redirectUrl = service.getAuthorizationUrl(requestToken);
log.info(redirectUrl);
return "redirect:" + redirectUrl;
}
#RequestMapping(value = "/tumblr/login", method = RequestMethod.GET)
public String login(#RequestParam(required = false) final String oauth_verifier) {
Verifier verifier = new Verifier(oauth_verifier);
// Trade the Request Token and Verfier for the Access Token
log.info("Trading the Request Token for an Access Token...");
accessToken = service.getAccessToken(requestToken, verifier);
log.info("Got the Access Token!");
log.info("(if your curious it looks like this: " + accessToken + " )");
// Now let's go and ask for a protected resource!
log.info("Now we're going to access a protected resource...");
OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
service.signRequest(accessToken, request);
Response response = request.send();
log.info("Got it! Lets see what we found...");
log.info(response.getBody());
log.info("Thats it man! Go and build something awesome with Scribe! :)");
run();
is_authorized = true;
return "tumblr/feed";
}
public void run() {
try {
if(! is_authorized ) return;
OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
service.signRequest(accessToken, request);
Response response = request.send();
log.info("[2nd Call ]Got it! Lets see what we found...");
log.info(response.getBody());
} catch (Exception e) {
e.printStackTrace();
}
}
Although I've not used Spring Social Tumblr (it's a community-led project), the process shouldn't be much (or any) different than using Spring Social with Facebook or Twitter.
Note that in this code, you're doing too much work. You're going to the trouble of redirecting to Tumblr for authorization and then handling the redirect to exchange the request token and verifier for an access token. Certainly, those things must be done, but with Spring Social there's absolutely no reason why you have to do those things. That's what ConnectController is for. ConnectController handles all of that, creates and persists the connection, and (generally speaking) you never have to muck about with OAuth directly. And, it has no problem working with multiple users.
May I recommend that you look at the Spring Social Showcase example at https://github.com/spring-projects/spring-social-samples/tree/master/spring-social-showcase to see how it's done? That example connects with Facebook, Twitter, and LinkedIn, but there's really no reason why it couldn't connect to Tumblr in the same fashion. For a much simpler approach that leverages Spring Boot and automatic configuration, you might also have a look at https://github.com/spring-projects/spring-social-samples/tree/master/spring-social-showcase-boot. (Note, however, that Spring Boot doesn't have autoconfig for Tumblr, so there'd still be some manual config required.)

Jersey HTTP authentication:How Can I Access and the HTTP authentication in jersey restful url?

I am Writting a Restful webservice with Jersey, this is the sample code:
#GET
#Produce(MediaType.APPLICATION_JSON)
public String findItems(){
...
}
and the url of findItem is localhost:8080/items
the method should verify the http authentication info(digest or basic) of this url before excutes, how to access authentication from the a url request first?
I would not put this in the controller itself, but in a com.sun.jersey.spi.container.ContainerRequestFilter around the resource classes you wish to protect, but should give you the basic idea.
#Context
private HttpServletRequest request;
#GET
#Produce(MediaType.APPLICATION_JSON)
public String findItems(){
String auth = request.getHeader("authorization");
if (auth != null) {
String basic_prefix = "Basic ";
if (auth.startsWith(basic_prefix)) {
String auth_data = new String(Base64.decode(auth.substring(basic_prefix.length())));
String [] user_and_key = auth_data.split(":", 2);
// user and password available here
} else {
// reject access
}
} else {
// reject access
}
}
Usually the authentication is handled by the container, you just have to add the corresponding constraint to web.xml to indicate what Uris should be protected and what kind of auth is required. Then in jersey you can get the roles and principal info from the SecurityContext you can inject to your resource.

Categories