Authenticate Google App users with Google OAuth2 API - java

I'm wondering if I can use the google client api (java) to authenticate the users of a google apps domain to my application.
The target application is a web application using a REST backend (jersey).
The documentation isn't very clear (or I misunderstood it), and the samples in the documentation refers to deprecated classes... Does someone knows if it's possible and the best way to do it.
A code sample would be appreciate.

Google Apps accounts should work fine with the APIs.
The only exception to this is if the service is disabled by the domain administrator. For example, if the Google+ feature is disabled by the domain administrator, you're not going to be able to access that user's Google+ data.
No code change is necessary, so you should be able to use the code from any of the samples in the client library repository or the product specific samples like this one for Google+.
The Google+ starter project implements the OAuth flow first by extending AbstractAuthorizationCodeServlet in com.google.api.sample.OAuth2AuthorizationCodeServlet
public class OAuth2AuthorizationCodeServlet
extends AbstractAuthorizationCodeServlet {
/**
* If the user already has a valid credential held in the
* AuthorizationCodeFlow they are simply returned to the home page.
*/
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendRedirect("/");
}
/**
* Returns the URI to redirect to with the authentication result.
*/
#Override
protected String getRedirectUri(HttpServletRequest request)
throws ServletException, IOException {
return ConfigHelper.REDIRECT_URI;
}
/**
* Returns the HTTP session id as the identifier for the current user.
* The users credentials are stored against this ID.
*/
#Override
protected String getUserId(HttpServletRequest request)
throws ServletException, IOException {
return request.getSession(true).getId();
}
#Override
protected AuthorizationCodeFlow initializeFlow() throws ServletException,
IOException {
return Util.getFlow();
}
}
And then by completing the flow in com.google.api.sample.Oauth2CallbackServlet by extending AbstractAuthorizationCodeCallbackServlet:
public class OAuth2CallbackServlet
extends AbstractAuthorizationCodeCallbackServlet {
#Override
protected void onSuccess(HttpServletRequest request,
HttpServletResponse response, Credential credential)
throws ServletException, IOException {
response.sendRedirect("/");
}
#Override
protected void onError(HttpServletRequest req, HttpServletResponse resp,
AuthorizationCodeResponseUrl errorResponse)
throws ServletException, IOException {
resp.sendError(SC_INTERNAL_SERVER_ERROR, "Something went wrong :(");
}
#Override
protected String getRedirectUri(HttpServletRequest request)
throws ServletException, IOException {
return ConfigHelper.REDIRECT_URI;
}
#Override
protected AuthorizationCodeFlow initializeFlow()
throws IOException {
return Util.getFlow();
}
#Override
protected String getUserId(HttpServletRequest request) throws ServletException, IOException {
return request.getSession(true).getId();
}
}

Related

Can you force a function not to return to the previous stack and just SendRedirect in a Java Servlet?

I'm trying to write error handling for a hibernate related project, I'm still new so there should be a better solution than this, but the way I did it was by creating a separate layer for running the hibernate queries
Now when handling hibernate exceptions in that layer I need to somehow sendRedirect without going back to the rest of the code as sendRedirect would throw an exception (forward and include could work but I would rather sendRedirect)
I tried to prevent the rest of the code to know about how I handle exceptions in that layer, but now I wonder if this was a good approach
Code sample of what I tried but doesn't seem to work as expected
#WebServlet("/signup")
public class RegistrationController extends HttpServlet {
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String email = request.getParameter("email");
String password = request.getParameter("password");
if (email != null && password != null) {
User user = new User(email, hashedPassword);
UserRepo userRepo = UserRepo.getInstance();
userRepo.create(user);
response.sendRedirect(UrlMappingConstants.getInstance().getControllerUrl(PageNames.SIGN_IN_PAGE));
}
}
}
And when something goes wrong in userRepo.create I call this in the catch
public void handleError() {
try {
ThreadLocalContext.forward(ServiceNames.ERROR_REDIRECT);
} catch (IOException | ServletException ioException) {
ioException.printStackTrace();
}
}
And all that does is redirect to error page
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect(UrlMappingConstants.getInstance().getControllerUrl(PageNames.TEST_JSP));
}

Download file to specific location through Java Servlets

I have the following servlet :
#WebServlet(urlPatterns = "/download")
public class FileDownload extends HttpServlet {
private static final long serialVersionUID = 1L;
public FileDownload() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v7.8.8/npp.7.8.8.Installer.exe");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
If I am hiting localhost:8080/download automatically file is getting downloaded to chrome's download location. I need to download it at particular folder. How can I do that ?
Actually I need to install this file automatically through the code by another service. So that's why I need to download this file to a particular location, like common C:/users so that i can pick it up to install
Please help!
Thanks in Advance

Java Spring boot - OnceRequestPerFilter allow only controller requestmappings

I'm currently implementing audit trail in my project, I tried using HandlerInterceptor and it seems it won't work in my project, so i looked for another way and I discovered that it's possible with OncePerRequestFilter.
Here's the code of my OncePerRequestFilter class:
#Component
#Order
public class LogFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String method = request.getMethod();
String username = SecurityContextHolder.getContext().getAuthentication().getName();
String url = request.getRequestURL().toString();
// Log the info you need
// ...
filterChain.doFilter(request, response);
}
}
The only problem so far that I see with my current configuration of OncePerRequestFilter is it also includes the resources such as css / javascripts.
example these links will be also go to the filter:
http://localhost:8000/project/css/style.css
http://localhost:8000/project/3277a64fcca0dbde907d8684aed8f170.png
http://localhost:8000/project/js/script.js.map
What i want is to filter only the controller request mappings, and ignore the resources
example:
http://localhost:8000/project/accounts/client-users
http://localhost:8000/project/accounts
This code is a workaround to ignore resource file. not sure if it's the best practice tho.
#Component
#Order
public class LogFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String method = request.getMethod();
String username = SecurityContextHolder.getContext().getAuthentication().getName();
String url = request.getRequestURL().toString();
filterChain.doFilter(request, response);
}
protected boolean shouldNotFilter(HttpServletRequest request)
throws ServletException {
String url = request.getRequestURL().toString();
return isResourceUrl(url);
}
private boolean isResourceUrl(String url) {
boolean isResourceUrl = false;
List<String> resourceRequests = Arrays.asList(
"/css/", "/js/", "/scss/", "/fonts/", "/emails/",
".css", ".js", ".scss", ".eot", ".svg", ".ttf", ".woff", ".otf", ".ico", ".png");
for (String resourceRequest : resourceRequests) {
if (url.contains(resourceRequest)) {
isResourceUrl = true;
}
}
return isResourceUrl;
}
}
Use something like this:
#Override
public void configure(final WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(
"/example/docs",
"/swagger-resources/**",
"/swagger-ui.html");
}

error 500 on google app engine

I am trying to create a servlet on the Google App Engine. I have done this sucsessfully a few times in the past, but now I get an "Internal Server Error" when running it from the cloud.
It works on Eclipse on development mode, though.
My servlet is called AsyncServer and the code is:
public class AsyncServer extends HttpServlet {
static final long serialVersionUID=0L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/plain");
PrintWriter writer = resp.getWriter();
writer.write("Hello");
writer.flush();
writer.close();
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}
I use the following address to call it on the local development server:
http://127.0.0.1:8888/test4/AsyncServer
and I get "Hello", as expected.
When deployed to the Google servers under the ID fa100-1130
I use the following address
http://fa100-1130.appspot.com/test4/AsyncServer
I get an http error 500
Currently entering the URL mentioned in your question and returns an affirmative respesta:
http://fa100-1130.appspot.com/test4/AsyncServer
run the development and performs deploy again
bye :) #locoalien

how to prevent servlet from being invoked directly through browser

I was working on a web project using java servlet and jsp pages. In one of the servlet we have RequestDispatcher method and which is calling another servlet.
#WebServlet("/Demo")
public class DemoServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.sendRedirect("testing"); //calling other servlet
}
}
#WebServlet("/testing")
public class TestingServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("Hello World");
}
}
So, now I wanted to prevent contextRoot/testing from being invoked directly from the browser but instead only let it invoked from the other servlet(Demo)
Please suggest me if there is any way to do that.
Couple of techniques exist:
Look at writing a HTTP Request Filter. You can then inspect the incoming request and the url and reject it if the pattern matches the servlet paths that you do not want to be invoked directly.
Another mechanism is to use the security constraints in your web.xml to allow access to various paths in your application only to authorized users/roles. Look at <security-constraint> tag in web.xml
Answer given by "Romin" is correct. You have to use Filters for this. what you can do is, you can set a new session variable whenever "/Demo" url is accessed and in the filter check for the condition that session exists, if it exists allow the url or else throw error. You could do something similar like this. In "Demo" servlet
#WebServlet("/Demo")
public class DemoServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
HttpSession session = request.getSession() //get new session
res.sendRedirect("testing"); //calling other servlet
}
}
In Filter class add the below code
#WebFilter("/login")
public class MyFilter implements Filter{
public void init(FilterConfig arg0) throws ServletException {}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpRequest request = (HttpRequest) req;
HttpResponse respone = (HttpResponse) res;
HttpSession session = request.getSession(false) //get the existing session object
if(null != session) {
chain.doFilter(req, resp);
} else {
"redirect to some error page or home page"
}
}
public void destroy() {}
}
One approach is to check the caller's ip using ServletRequest.getRemoteAddr() and rejects it if it's not called locally
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
if(!req.getRemoteAddr().equals("127.0.0.1")) { // reject }
}
However this method wouldn't work legitimate caller (eg: proxy) is also using the same ip.

Categories