Is there any way to use FORM and BASIC authentication together in my webapplication? I have a RESTful interface in it and I'd like to allow scripts to use it with the simple BASIC auth method but I'd like to have the FORM based auth for web clients as well. I'd like the webapp respond with 302 Moved Temporarily redirecting to the login page for unauthorized requests, but if it finds that the client is sending the BASIC authentication's HTTP headers with username and password, then accept them just like in BASIC authentication.
I see that this is not possible with a single web.xml configuration but wondered if anyone else has some solution for this.
Can you use a filter?
Inspect the request for your headers. If present do the login process and add session data etc. to the request. If it fails then either ignore it or redirect.
If I configured container auth then my code was never invoked without authentication. So the answer is no. Jenkinks CI and similar software use FORM based authentication for a restricted set of web resources and make use of Spring Security where things are more flexible.
Related
I'm trying to call a 3rd party endpoint that requires authorization using Java spring rest Api, so I need to execute an Authorization Code Grant Flow.
I understand the flow where I need to first get the code then exchange the code for a JWT and finally use the JWT to be able to do the secure call.
What's not making sense to me is how am I suppose to set up a redirect URI when I'm using solely working with a backend rest api with no UI. Usually the user is redirected to a login page where they either login with a username/password or 3rd party accounts (google/facebook...)
After alot of googling, all the searches ended with guides to secure my own endpoints rather than access a secure endpoint from my spring boot service
Edit: It's worth mentioning that I'm using solely a backend with no front end (or MVC) whatsoever, after #Partha's comment I did the following:
First, I added a new login endpoint, when accessed via browser(this won't work with swagger/postman) it should redirect the user to the Authorization Server:
#GetMapping
public void login(HttpServletResponse httpServletResponse) {
httpServletResponse.setHeader("Location", getAuthServerEndpoint());
httpServletResponse.setStatus(302);
}
Where I built the endpoint to have all the data needed (client_id,redirect_uri...) so it looks something like
https://idpserver.bla/oauth/authorize?client_id=xyz&redirect_uri=http://localhost:8080/token&response_type=code&scope=xyz
Now it sends me to the Login page of the auth Server, after I login, I expect it to redirect me to localhost/token (which is a get request that would retrieve the code and do a post request to get a jwt and save it) but instead, I'm receiving a invalid redirect uri and I'm really not sure if this is an issue from my implementation or the server's
EDIT2: I did a dumb mistake by NOT adding http://localhost:8080/token as a redirect url in the Auth Server since I assumed I didn't need to
Not really sure how are you trying.. idea here is .. your api server should have a get endpoint /login. In your controller of /login , you should redirect to IDP say http://idpserver.bla?client_id=xxx&grant_type=code&nonce=yyy&redirect_uri=http://localhost:8080/token ( note, its redirect, not make an api request ). So, with this, when you hit http://localhost:8080/login in ur browser, you should see it being redirected to IDP. now you enter ur credentials, IDP validates that and redirect back to http://localhost:8080/token?code=XYZABC or something similar. Your controller code of /token API should read the code from url param. and make a call (this is api call, not redirect) to IDP to exchange the code for a token ( idToken / accessToken) based on your scope. And using the token you should be able to access protected resources. Hope that helps
Depending if you are using MVC or Webflux a different approach will be required:
MVC: include a "security filter" to do that. You will be able to see an example in the following links:
MVC Securiry Manager
MVC Security Filter
MVC Security Configuration
Webflux: configure your own security manager. You will be able to see an example in the following links:
Webflux Securiry Manager
Webflux Securiry Context
Webflux Security Configuration
As you can see in both ones, an external service is called (using RestTemplate in MVC and WebClient in Webflux), to get the required authorization information and decide if the "logged user" pass the required security logic.
You can adapt it in the way you need.
I would like to use pac4j in a Java application to create a Tomcat filter or Tomcat valve. The filter or valve must support OpenID Connect using standard OAUTH2 authorization code flows. Even better would be to build on top of j2e-pac4j to do this, but I cannot use the OAUTH2 filter in j2e-pac4j. My filter or valve needs to modify the request object by adding an HTTP header. The web app behind the filter/valve requires the HTTP header, and it's third party so I can't change this.
I will use Open ID Connect so I can get the JWT, but other than using the JWT and its contents and perhaps the userinfo endpoint of Open ID Connect, I am simply doing a standard OAUTH2 flow. Here's the complication: The server I will redirect to for authorization supports multiple tenants. This means that the URL I redirect to will have the tenant name in the URL. This means that instead of a URL like
https://authorization.server.com/oauth/authorize
(Note, leaving off ?response_type=code&scope=openid&client_id=myclientname&state=nonce&redirect_uri=... for the sake of clarity.) I will be required to redirect to a URL like one of:
https://authorization.server.com/tenantname/oauth/authorize
https://authorization.server.com/oauth/tenantname/authorize
https://authorization.server.com/oauth/authorize?realm=tenantname
How do you do this with pac4j, or better yet, j2e-pac4j? I've been told that pac4j will not support this, where every client potentially uses a different redirect URL for authorization.
My task is to use a send request and then to get some XML.
example:
request: /api/ext/data.xml
response: some XML
The application uses Spring MVC, so I just wrote controller method, and everything works OK, but I also need to implement authorization. This app does not use Spring security.
What should I do? Should I use session to save User authorization data?
You should still look at Apache Shiro and/or Spring Security. However Spring Security (and container security for that matter) are not so friendly for REST API security. For Spring you will need to implement a custom AuthenticationEntryPoint to avoid the redirect on 403. Shiro might be a little easier for REST API.
If you want to do it yourself w/o dependencies or complexities you should look into writing a Servlet Filter and/or leverage container security. A compromise might be this SecurityFilter project. However if you need Roles, ACLs etc... you should seriously reconsider Shiro or Spring Security.
And what about implementing your own HmacSha1 model (signed requests) as Amazon Web Services do?
Basics: Client signs the request with a Secret access key (SAK) and expire data, obtaining an hmac code.
Then client sends via POST the request plus some headers like hmac code and expire data and whatever you need. The server then gets your request in the controller (or interceptor), signs it with your SAK and expire time, and compares obtaining hmacs to validate user.
I am building a RESTful Webservice using Apache Jersey. Now I want that you need an authentication for some requests to it. Using the typical REST-approach the Authentication should be done via HTTP-Authentication. But a post here mentions that a better way how this can be done is by using cookies. I think there are some valid points in the discussion. (How) Can I make my Jersey Authentication work with Cookies? Do I need another framework for it?
Jersey uses the authentication mechanism declared in the enclosing web application's web.xml, practically either HTTP Authentication (over SSL) or Form-based Cookie authentication.
If you want to used cookie-based session authentication, users must authenticate with the web service first to create a session which can be used to check their identity for future calls. The servlet spec provides a standardized way to authenticate using cookies and session using a web form, which however, is not compatible to a web service type of application. So you would probably want to cook up some custom solution to let users submit their credentials via POSTing an XML or JSON document. A problem with this method is that if a user performs a call to a resource without first authenticating or after the session has expired, they will need to be redirected or receive some type of error code. Not impossible but it adds complexity to your web service.
At this point you have to wonder if using HTTP Auth is not the better choice for web service style apps. We recently built a web service using Jersey and HTTP Auth as the authentication mechanism. We then build a Javascript front end on top of it. The Javascript client always submits the Authentication headers to the web service so that the user is never confronted with the HTTP Auth authentication window from the browser. Perhaps the best of both worlds.
I'm trying to create a user login page for my jersey webapp on tomcat that behaves like all the other pages on the web. That is, the user sees a nice login page opposed to a popup (like BASIC tomcat authentication) and the passwords are hashed before comparing to the DB entries. Is tomcat authentication the right way to do this?
It seems that I want to use DIGEST authentication for md5 hashing but FORM authentication to get a page rather than a popup. Perhaps there are java libraries to do this instead, and I should simply not use tomcat for this.
Check out Apache Shiro or Spring Security.
When using the form submission approach, BASIC versus DIGEST does not come into play at all since it isn't using HTTP Authentication. It simply sends the user id and password via an HTTP POST as parameters to a URL that is predefined by the Servlet specification, allowing the Servlet container to process them. Security of the data using this method is achieved through the use of SSL.