I know how to from-login on a javaee web application and to protect URI resource from non-authenticated users. Works.
Now, I thought about using all the Java EE security structure that is already there, simply because I want to avoid to duplicate code and make it worse. I want to avoid to create #Entity beans that are already available. Thus I want to secure my EJBs, Backing Bean, CDI beans and URI Resource. All with the same concept. i.e. I need:
Role --> javax.managagement.relation.Role
Group --> java.security.acl.Group???
User --> java.security.Principal
At max, I want to extend existing implementation and use a more specific implementation. E.g. User --> User with firstname, lastname, etc.
Is there already an interface User in the Java EE security or even an implementation?
Also, if a user is identified with a form-based login, can I check the user's permission also in an EJB (e.g. #Stateless)? E.g. with #RolesAllowed("admin"). Rephrasing: Does the login status prevail also for the EJB context and not only in the web context? (I mean, it's the same container, it should, right?)
There is class java.security.Principal (e.g. javax.servlet.http.HttpServletRequest#getUserPrincipal). It has getName method. You should create custom login module for your application server if you want extend Principal object with new fields.
Related
I need to implement Authentication & Authorization using spring boot oauth2 with keycloak as a provider.
I also need to support muti-tenancy. I tried example with authentication using spring-boot-starter-auth2-client to authenticate, but not able to add multi-tenancy.
When I used spring-boot-starter-auth2-client, I need to configure hardcode keycloak urls(specific to one tenant) in properties and not able to support multi-tenancy.
I also analyze spring-boot-starter-auth2-resouce-server, but not clear. I understand that resouce server use for validation of token and expiry.
Note: I don't want to use keycloak adapter library which is provided by keycloak.
Could you please help me -
Where need to use spring-boot-starter-oauth2-client and spring-boot-starter-oauth2-resouce-server?
Is spring-boot-starter-oauth2-resouce-server also use to authentication?
How to authenticat user using spring-boot-starter-oauth2-client and pass to spring-boot-starter-oauth2-resouce-server for authorization.
How to implement multi-tenacy e.g. take tenant id from url and redirect user to tenant specific keycloak login page.
I tried some example but won't succeed, working example will be helpful with -
Spring Webflux + spring-boot-starter-oauth2-client+ spring-boot-starter-oauth2-resouce-server + multi-tenancy + keycloak as a provider.
Thanks & Regards,
Pravin Nawale
tried some example found on internet, but didn't work.
This question should not be answered because:
it is actually a container for many questions
quite a few are way too wide or lack precision.
But as it seems to be a first question... (break it down next time, give more details and edit your question when you get comments asking precisions)
1. Where need to use spring-boot-starter-oauth2-client and spring-boot-starter-oauth2-resouce-server?
This one is important to start with as I suspect you lack OAuth2 background, specifically regarding involved parties and how it is implemented with spring-security:
spring-boot-starter-oauth2-client is to be used with OAuth2 clients:
apps serving UI with oauth2Login (#Controllers with methods returning template names)
apps consuming REST APIs with auto-configured Spring client: WebClient, #FeignClient, RestTemplate
spring-boot-starter-oauth2-resouce-server is to be used with resource-servers: apps serving REST APIs (#RestController or #Controller with #ResponseBody)
Now, if your app has controllers for both the resources and the UI to manipulate it (with Thymeleaf or any other server-side rendering engine), then define two different security filter-chains: one for each, ordered, and with securityMatcher in the first in order to limit the routes it applies to (the second being used as fallback for unmatched routes). Sample in this answer (the sample is for servlet, but it's the exact same principles): Use Keycloak Spring Adapter with Spring Boot 3
2. Is spring-boot-starter-oauth2-resouce-server also use to authentication?
OAuth2 requests should be authorized with an Authorization header containing a Bearer access-token.
The client is responsible for acquiring such an access-token from the authorization-server before sending requests to resource-server.
Your question is not quite clear but here are a few statements which could answer:
resource-server should return 401 (unauthorized) and not 302 (redirect to login) when authorization is missing or invalid => do not configure oauth2Login in resource-server filter-chain. Again, this is client business
resource-server is responsible for resources access-control: check that access-token is valid, that the user has required authorities, etc.
3. How to authenticat user using spring-boot-starter-oauth2-client and pass to spring-boot-starter-oauth2-resouce-server for authorization.
This question is not focused enough to get a single answer: what kind of client? what kind of request? context?
I see three main cases here:
the UI is rendered on Spring server with Thymeleaf, JSF, and alike => use spring's oauth2Login and refer to its documentation to overrides defaults and implement your authorization-server selection logic
the UI is rendered in the browser (Angular, React, Vue, ...) and you are ok to make it an OAuth2 client => find a certified client lib for your framework and implement the logic in the client (angular-auth-oidc-client, for instance, supports multi-tenancy)
the UI is rendered in the browser, but you prefer to implement the Backend For Frontend pattern to hide tokens from browser, then choose a BFF (like spring-cloud-gateway with tokenRelay filter) and refer to its doc for implementing your logic in it
If that can be of any help, I have:
here a tutorial for configuring an app with a Thymeleaf UI client and REST API
there a sample repo with an Angular workspace (app configured as OIDC client + API client lib generated from OpenAPI spec) and spring-boot resource-server (using servlet, but this makes no difference to the client).
4. How to implement multi-tenacy e.g. take tenant id from url and redirect user to tenant specific keycloak login page
Note
One of key principles of OAuth2 is that identities (tokens) are emitted (issued) by trusted 3rd parties (authorization-servers) => you must configure the list of issuers your resource-servers can trust (and clients can fetch tokens from). This list is static (loaded with conf at startup).
Accept identities from various issuers on the resource-server
This is done by overriding the default ReactiveAuthenticationManagerResolver<ServerWebExchange> in your SecurityWebFilterChain configuration: http.oauth2ResourceServer().authenticationManagerResolver(authenticationManagerResolver)
I provide with thin wrappers around spring-boot-starter-oauth2-resource-server which support multi-tenancy just by defining properties. Complete sample there:
Instead of spring-boot-starter-oauth2-resource-server (which is a transient dependency):
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webflux-jwt-resource-server</artifactId>
</dependency>
Instead of all your resource-server Java conf (unless you want access control from configuration and not with method-security, in which case, you'd have to define an AuthorizeExchangeSpecPostProcessor bean here). Of course, you'll have to add here a client filter-chain with a restrictive securityMatcher if you also serve UI client with oauth2Login:
#EnableReactiveMethodSecurity
#Configuration
public class SecurityConfig {
}
Instead of spring.security.oauth2.resourceserver properties:
com.c4-soft.springaddons.security.issuers[0].location=https://localhost:8443/realms/realm-1
com.c4-soft.springaddons.security.issuers[0].authorities.claims=realm_access.roles,resource_access.client-1.roles,resource_access.client-2.roles
com.c4-soft.springaddons.security.issuers[1].location=https://localhost:8443/realms/realm-2
com.c4-soft.springaddons.security.issuers[1].authorities.claims=realm_access.roles,resource_access.client-1.roles,resource_access.client-2.roles
# Comma separated list of routes accessible to anonymous
com.c4-soft.springaddons.security.permit-all=/api/v1/public/**,/actuator/health/readiness,/actuator/health/liveness
# Fine-grained CORS configuration can be set per path as follow:
com.c4-soft.springaddons.security.cors[0].path=/api/**
com.c4-soft.springaddons.security.cors[0].allowed-origins=https://localhost,https://localhost:8100,https://localhost:4200
# this are defaults and can be omitted
com.c4-soft.springaddons.security.cors[0].allowedOrigins=*
com.c4-soft.springaddons.security.cors[0].allowedMethods=*
com.c4-soft.springaddons.security.cors[0].allowedHeaders=*
com.c4-soft.springaddons.security.cors[0].exposedHeaders=*
If you don't want to use "my" wrappers, just copy from the source, it is open.
Redirect the user to the right authorization-server from client UI
As explained at point 3., this depends on the kind of client, used framework and if BFF pattern is applied or not
5. I tried some example but won't succeed, working example will be helpful with - Spring Webflux + spring-boot-starter-oauth2-client + spring-boot-starter-oauth2-resouce-server + multi-tenancy + keycloak as a provider
With all the elements above and linked resources, you should have enough to find your own path
I have two set of users one is anonymous and another is valid users (authenticated using cas server). So for anonymous I don't have ticket but for users I have the ticket. But I want to make the resource available to both with some nifty feature will be provided to valid users. My resources are available as REST services. Therefore between two calls (say /foo and /bar. here /foo must be called before /bar) I have to check whether the calling user is same or not?
Therefore I would like to generate a ticket for anonymous user also. so that in /bar, I can check same anonymous user has actually request /bar.
Can anyone suggest how can I solve the above problem using apache shiro.
Also as I have very little knowledge about Apache shiro, I would like to know which one is better apache shiro or spring security (in case of REST services developed using jersey 2)
I configured the GlassFish JDBC realm with form based authentication in my Java EE app so, everything is ok.
But I want to get the user's info (user_id) and I want to keep it in a list during his session. After his session is timed out or a log out occurred, I will remove it from this list.
Should I change the auth method?
Unfortunately the Java EE security APIs are not rich enough to provide detailed info about the user that is logged-in.
The only thing you can ask for is the name that the user used to login. You can do this via HttpServletRequest#getUserPrincipal#getName or it's alternative HttpServletRequest#getRemoteUser.
There are a few workarounds:
In a Servlet Filter, check if this "list" you talk of is empty and either of the above methods returns a non null value. If this condition holds, query your user details manually based on the username and put them into this "list". (I'm not really sure why you specifically use a list for this, but that aside)
Indeed change the auth method to a programmatic variant. This means you build your own form, dialog, or whatever. Then in your backing code (backing bean if using JSF, otherwise a Servlet or whatever) load the user details, and call HttpServletRequest#login with the username from those details. If this call succeeds immediately put your extended user info in your "list" again.
(advanced method) Use a custom auth module (e.g. via JASPIC) and let this auth module delegate to code in your application. This application based code then returns the username and roles to the container and simultaneously puts the user details into the HTTP session. The advantage of this method is that you have the user login/load code in one place, and it's also done once. With the JDBC realm the code (query) is in two places and is also done twice.
I suggest trying option 1 or 2 first. If you want to pursue the advanced method, check out http://jdevelopment.nl/open-source/java-ee-kickoff-app for an example.
If it bothers you that Java EE doesn't have an easier and more powerful mechanism to do this out of the box, please consider voting for this issue: https://java.net/jira/browse/JAVAEE_SPEC-9
Let me preface this by admitting that this is my first webapp and first experience with JSF, so I've probably made some poor design decisions.
Here's what I'm trying to do:
I have a webapp using JSF 2.0, which is accessible through a Facebook canvas. This webapp allows a user to view/manipulate data from a database of sensor readings. On the very first time the Facebook user accesses my app, I ask the user to enter login credentials for the database, then send the user to the home page. Thereafter, the user should always go straight to the home page, since I associate the user's FB id with the database user profile.
Current implementation:
I have the Facebook canvas URL going to a servlet. This servlet checks the signed_request parameter passed by Facebook to get the user ID, and then looks in the database to see if the user has already completed the provisioning process. If the user has done so, he is redirected to the application home page.
The problem:
Most of my logic to do these checks currently exists within a managed bean (session-scoped). To use the bean within the servlet, I'm manually instantiating the bean and adding it to the session, since the JSF framework hasn't had a chance to create it yet. As my system is getting more complicated, this is causing problems due to dependencies between the various beans. Also, it seems like a generally bad approach to the problem.
Solutions? From my web searching, it sounds like there might be several ways to do this. One way would be to set the canvas to a JSF landing page, where a managed bean would grab the signed_request parameter and validate that the user has completed the provisioning step. From there, the bean would forward to the proper page. Another possibility might be to have an eager bean that does the same thing, but this seems "wrong".
What's the best way to resolve this and adhere to "proper" JSF paradigms?
Thanks in advance!
There are a number of different ways that this can be handled. The JSF landing page is one idea and the eager bean are some ways that this can be handled.
If you ignore the fact that you are integrating with Facebook then ultimately you are trying to solve an authentication and authorization problem. Facebook is handling your authentication, and telling your web application what the identity of a user is, and it is your web app's job to remember that person's identity throughout the session, and authorize this person to visit the requested page.
I have implemented it before where I had all of my managed beans extend a BaseBean class that on creation and initialization checked for the existence of a specific SessionScoped bean that contained the user identitification information. If this bean did not exist or was not authorized to access this bean then I would redirect. The problem with this approach was that it authorized only the use of managed beans, and not pages.
Another approach I had was to utilize a servlet filter that would essentially check every page request and look for the session scoped bean that contained the currently authenticated user. If this wasn't found then I would look for the specific request parameters and authenticate and create the session bean, and if that didn't exist would redirect to an Unauthorized page.
This approach worked well until I realized that Authentication and Authorization of Java web applications is a well understood and near universal problem. After a little bit of looking and research I discovered that security frameworks like Spring Security 3 can indeed be integrated into JSF and handle nearly all of the complexity of complex authentication and authorization. You could very easily integrate a custom Facebook authentication handler for Spring Security and control access by user role to the individual page level, all from XML configuration. It is highly worth looking into if you have the time to learn something new.
I have a scenario where I am trying to combine spring security with jersey for my REST API.
My need is rather complicated (I think) and it is as follows:
Spring security is being used to intercept urls and forcing basic authentication in order to access a REST resource. This seems to be ok as I am using http client to test this.
However what I want to do is somehow access the User object that is loaded to check some additional permissions that hang off the user (a map object with boolean flags to indicate if object properties are visible or not). The code that does the loading works, but after spring authenticates how do I then access the User object in the actual REST Resource method itself?? Is this possible?
So the steps are:
1) Client makes a REST API call
2) Spring intercepts URL checks username and password supplied in the http header
3) The rest resource method is then accessed if valid credentials are present
But before step 3, I want to somehow pass on the loaded User object to the actual Resource method itself so I can further apply some logic to restrict what the user can see based on the permissions that I have loaded??? Is this possible? I think I have seen some code somewhere that checks for User Roles before a method is accessed using Spring and REST but if anyone has any links or ideas that would be excellent.
Please help if you can. thank you so much.
I solved this by using a request-scoped proxy which was constructed by a bean factory.
This allows you to simply inject your currently authenticated user into any spring managed bean, and in my case my Jersey Resources fell into that category. I injected my user into the tier below the resources, but it's all the same.
Someone else elegantly blogged the full solution here.