I have a Spring-MVC (Spring 4) based server that provides a REST service to an outside client (IE, I do not have a view hosted on my server). A requirement has been added to add a login service to the REST which authenticates against a backend server.
My question is: How do I add a login request to the REST server in such a way that every request that goes to the server first goes through a check to see if the user has authenticated and if there is an active session, and returns an error if this is not the case? Preferably, this should be transparent to other requests, and should not require a code change at the other #RestController based classes.
Thanks
Related
I have a spring boot (backend) & angular (frontend) app that I'd like to secure with keycloak (for the authentication).
I have a very basic deployment, in which the executable jar created by spring also serves the client code (from angular).
I have seen several tutorials where the front and back are separated, and the front uses the code flow + pkce to delegate its authentication to keycloak, while the back is stateless and checks for presence of a jwt token certified by the keycloak instance.
However since I have a backend server, I'd like to avoid using a public client and instead rely on the back-channel token exchange on the server side. So the front should not have any knowledge of the keycloak instance.
Is that possible / is it a best practice ? Is there a front library that helps me to achieve that ? I've come across the library keycloak-angular, but it seems to be directed towards the first case, where the SPA connects directly to Keycloak instead of using a backend server.
In such a case you don't need a frontend library. In your frontend you should just handle user session (have a session cookie) and send the cookie every time to your backend. Then the backend server should use any oauth client to communicate with your keycloak server, and once it gets the tokens it can save them in a db together with a handle to your session.
Here's how this flow might look like:
request client -> backend server -> reply with a 302 to the keycloak authorization endpoint. Registered redirect_uri should be a uri exposed by the backend server
user performs authentication / consent, etc.
Keycloak redirects to redirect_uri with code
Backend receives code (as it listens on the redirect uri address), and exchanges it with Keycloak.
Backend receives access token and saves it in a DB together with session ID.
When clients makes another request to backend with their session, backend picks an access token from the DB and can call an API.
My apologies for my bad english.
I have the tool Apereo CAS using as login SSO. When i'm using with application statefuls this works very well. But i wanna call a API REST (stateless) for specific scenario and validate the logged user (and using your informations on the service). My backend API is developed with Spring Boot. Someone needed a similar situation?
Ps: This API will acess by frontend and services without frontend therefore I'll not be able to use cookies.
Sequence Diagram to exemplify my idea:
enter image description here
Thank's.
Your front-end application needs to ask the CAS server for proxy authentication.
One of the more common use cases of proxy authentication is the ability to obtain a ticket for a back-end [REST-based] service that is also protected by CAS. The scenario usually is:
User is faced with application A which is protected by CAS.
Application A on the backend needs to contact a service S to produce data.
Service S itself is protected by CAS itself.
Because frontend contacts service in the back-end via a server-to-service method where no browser is involved, the backend would not be able to recognize that an SSO session already exists. In these cases, front-end needs to exercise proxying in order to obtain a proxy ticket for the backend. The proxy ticket is passed to the relevant endpoint of the backend so it can retrieve and validate it via CAS and finally produce a response.
The trace route may look like this:
Browser navigates to front-end.
Front-end redirects to CAS.
CAS authenticates and redirects back to front-end with an ST.
Front-end attempts to validate the ST, and asks for a PGT.
CAS confirms ST validation, and issues a proxy-granting ticket PGT.
Front-end asks CAS to produce a PT for back-end API, supplying the PGT in its request.
CAS produces a PT for backend API.
Front-end contacts the service S endpoint, passing along PT in the request.
backend API attempts to validate the PT via CAS.
CAS validates the PT and produces a successful response.
Backend API receives the response, and produces data for front-end.
A receives and displays the data in the browser.
See this for details.
I have a web application that when user click on the a link it will generate security information and log on to an external application if the security information is authenticated.
At this point from security concern I don't want to expose the URL and request information on the web page, so instead I am seeking solutions to handle the process behind the scene
I know Apache Components can easily send post request within POJO, jersey client can do as well through web service. However the requirement here is also including to let browser automatically redirect to the 3rd app's front page if the login process succeeded.
My question is what could be the proper solution to handle the login process and go to the external application from web as well.
Say you have:
publicapp.com
secretapp.com
Set up an API in publicapp.com to POST the initial request to itself. When the user submits the initial login form it goes to say publicapp.com/login. This endpoint will pre-process the information then send a server to server request to secretapp.com/login.
If secretapp.com/login accepts the information it responds to publicapp.com with a success and publicapp.com redirects the client to secretapp.com/home, with a short term auth token encoded in a JWT. secretapp.com, swaps the short term token for a full auth token.
In the above scenario, the actual login endpoint is never made public. secretapp.com should also have IP whitelisting to only accepts login attempts from publicapp.com. You can also do a lot of filtering on publicapp.com to eliminate malicious requests without bothering secretapp.com.
I have a web application that contains ui based on jsf 2.0 and a set of rest apis.
The ui side of the application is accessed from a browser and rest apis are invoked from a mobile app.
For the authentication for the UI is managed by jsf , (no form nothing, jsf manages everything). Now, I want the user to be authenticated before he/she can access the rest apis.
Can I set up the web application to have Basic authentication so that I can set the username and password in the header when calling the rest apis?
You will need to have a security filter for your web application. (this can be done with spring security - Integrating Spring security with JSF 2 )
The user will have to pass a username and password to your application.
Then, you just need to configure your rest api to work with basic authentication. Since basic authentication is a HTTP feature, every time you call the rest service, you will need to pass the username/password in the request.
I am developing a Java web application using RESTful as web service. And now I want to apply Apache Shiro to secure my application. The mechanism is: after user logged in successfully, a token (combined from username, password and logged time) will be returned to client. Then every single REST request will attach this token to authenticate at server (no need to authorize). But now I dont know how to configure to accept this.
And by the way, could you please give me any sample about Shiro & RESTful integration? Thank you
If the REST application and the Java web application are the same Webapp, then you only need to check subject.isAuthenticated(). Use a session cookie without the password or username (it isn't a good idea to be passing around the password as it could be stolen).
Most of this behavior comes by default if both parts are in the same Webapp.
In your REST method you'd have something like:
Subject subject = SecurityUtils.getSubject();
if(subject == null || !subject.isAuthenticated()) {
return 401; // Not Authorized
}
Hope that helps.
In addition to the above response, you can send back a token (session-id) from your REST Server, post successful login. Your iOS/Android application will then need to store this, and send this with every REST request it makes. Here is sample of what your post login REST response can be:
session-start-timestamp: 1394683755389,
session-timeout: 1800000,
session-id: "068C8E0E289788A7ABC5FE47B2CC0D28"
The session-id will be maintained by your REST Server, and its TTL will be reset every time a new request with this id comes in.
On browsers, this id gets sent automatically. For your case, you would want to send it explicitly with each HTTP request (which is what REST request is)
Hope this helps