Bypass basic authentication for only frontend application - java

I have a frontend application written in React and a backend application written in SpringBoot. I have implemented basic authentication in the backend application(for all endpoints) using Spring Security. So now a username and password are required to access every endpoint.
Requirement :
I don't want to pass a username and password from the frontend application to access backend application endpoints so basically, I want to bypass basic authentication for my frontend application.
If someone wants to access any endpoint outside my frontend app for example Postman, RestTemplate, etc then a username and password are required.
For example -
if the request is coming from www.abc.com (frontend app URL) then basic authentication should be bypassed for all endpoints but if the request is coming from www.xyz.com, Postman, RestTemplate, or any other client then basic authentication should not be bypassed.
I know how to bypass authentication on a specific endpoint within the backend application but I don't know how to bypass authentication for the requester, I did research over the internet as well but not found something useful. Looking for working code to fulfill the requirement.

If you use some kind of reverse proxy (e.g. nginx) to serve your frontend, you can set the basic authentication parameters there.
e.g.
location / {
...
proxy_pass http://127.0.0.1:8080;
proxy_set_header Authorization "Basic TOKEN";
}
where TOKEN = base64(username:password)

Related

How to secure angular/spring app with keycloak?

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.

How to get all users from an authorization server using OIDC in spring?

I've got a spring-boot app that authenticates with OIDC (oauth2) and I'm trying to get a list of all the users from the authorization server - how should I implement this using spring?
Spring Security OAuth2 doesn't have an API for expressing a user repository. It does have a UserDetailsService interface, but you'll note that it only has the loadUserByUsername method.
If you are building an OAuth 2 authorization server, you could take a look at Spring Data and Spring MVC to expose a query endpoint (using Spring Security to secure that endpoint).
If you are building an OAuth 2 resource server or client that is talking to a third-party authorization server, you could take a look at RestTemplate or WebClient to formulate whatever proprietary query your authorization server wants since like #Ronald said, there is no OAuth 2.0 standard for querying users.
When a user signs in into his identity provider his personal information can be accessed by the claims the identity token contains. Or by approaching the userinfo endpoint.
There is no endpoint which returns all the users from the authorization server according to the OIDC standard.

Keycloak public client and authorization

We are using keycloak-adapter with Jetty for authentication and authorization using Keycloak.
As per Keycloak doc for OIDC Auth flow:
Another important aspect of this flow is the concept of a public vs. a confidential client. Confidential clients are required to
provide a client secret when they exchange the temporary codes for
tokens. Public clients are not required to provide this client secret.
Public clients are perfectly fine so long as HTTPS is strictly
enforced and you are very strict about what redirect URIs are
registered for the client.
HTML5/JavaScript clients always have to be public clients because
there is no way to transmit the client secret to them in a secure
manner.
We have webapps which connect to Jetty and use auth. So, we have created a public client and it works awesome for webapp/REST authentication.
The problem is as soon as we enable authorization, client type gets converted to Confidential from Public and it does not allow the reset it as Public. Now, we are in soup. We cannot have public clients due to authorization and we cannot connect webapps to confidential client.
This seems to be contradictory to us. Any idea why client needs to be confidential for authorization? Any help on this how can we overcome this issue?
Thanks.
As far as I understood, you have your frontend and backend applications separated. If your frontend is a static web-app and not being served by the same backend application (server), and your backend is a simple REST API - then you would have two Keycloak clients configured:
public client for the frontend app. It would be responsible for acquiring JWT tokens.
bearer-only client, which would be attached to your backend application.
To enable authorization you would create roles (either realm or client scoped, start on the realm level as it's easier to comprehend). Every user would then be assigned a role/s in the Keycloak admin UI. Based on this you should configure your keycloak adapter configuration (on the backend).
All things considered, in order to talk to your REST API, you would attach a JWT token to each HTTP request in the Authorization header. Depending on your frontend framework, you can use either of these:
Keycloak js adapter
Other bindings (angular, react)
P.S. For debugging I have just written a CLI tool called brauzie
that would help you fetch and analyse your JWT tokens (scopes, roles, etc.). It could be used for both public and confidential clients. You
could as well use Postman and https://jwt.io
HTH :)
I think you are referring to the "Authorization Enabled" switch in the admin console of Keycloak, when creating a client. If you go over the question mark next to the label, you'll see the hint "Enable/Disable fine grained authorization support for a client.
Create client in Keycloak admin console (v 6.0.1)
This is meant for when you create a client for a backend application that serves as a resource server. In that case, the client will be confidential.
If you want to create a client for a frontend app, to authenticate a user and obtain an JWT, then you don't need this.
See also: https://www.keycloak.org/docs/latest/authorization_services/index.html
After much deliberation, we found that authorisation is not required to be enabled on public client really when you connect to it. When any request come to public client, it only does the authentication part. Authorization part is done when actual request lands on the resource server (in our case, Jetty) using the confidential client (as Jetty has knowledge of confidential client configured in it).

Serverside Authenticate Keycloak user programmatically in Java with Bearer token

I want to authenticate a User in my Java REST endpoint using Keycloak and a Bearer token.
The workflow I want to achieve is the following:
The client logs to Keycloak with Username and Password.
Keycloak returns a Bearer token (a JWT one if I'm not wrong, how can I check?).
The client performs an Http request with 'Authorization' : 'Bearer <token>' header.
The REST endpoint (written in Java) checks if the received token is correct and authenticates the User receiving a Principal from Keycloak (if I understand correctly).
Once authenticated, the endpoint will check if User has permission to access that REST api and send back a response.
1, 2, 3 and 5 are already implemented and working but i can't find a way to implement 4.
I have already tried different ways:
My Java endpoint is running in a EAR published on WildFly 10.x so I used a security-constraint in my web.xml and configured Keycloak via keycloak.json.
This works fine but I need to leave some REST endpoints public (accessible even without an 'Authorization' header) in the same web context and as far as I know there is no way to filter only some requests in my security-constraint.
I tried implementing a BearerTokenRequestAuthenticator with absolutely no success and even if I could I don't think I would receive a Principal as result of my authentication request.
Right now i have already implemented a way to filter the requests and the ones that require authentication are intercepted by a ServiceSecurityInterceptor class I implemented.
At some point in that class I check if the 'Authorization' header contains a Basic or Bearer :
User loggedUser = null;
if (authorizationType.equals("Basic")) {
// ... decode Base64 username and password ...
loggedUser = userManagerBean.login(username, password);
} else if (authorizationType.equals("Bearer")) {
String token = ...; // Get token from header
// ... Here is where I need to send the token to Keycloak and receive a Principal with the username ...
loggedUser = userManagerBean.login(username):
}
I read in some places that I probably need a public key from my Keycloak realm but once I have it, what should I do?
A few months ago we have introduced Keycloak. The trick is to let Keycloak do the work for you. I guess you are using OpenId connect? Have a look at these Java-Adapters. Maybe this one could handle the url pattern matching for you.
For my self I prefer to use Spring boot security with keycloak. The Keycloak Spring Boot Adapter integrates well with Java applications. You just have to do some config in the Java app and on Keycloak server. The Authentication process is handled automatically by KeyCloak and Keycloak Adapter. With Spring boot you can als create a ear package for your WildFly Server. The KeyCloakPrincipial is automatically created within Springs security context (SecurityContextHolder.getContext().getAuthentication().getPrincipal())

Java: Authenticate user from JAAS protected Restful API (Jersey) on Glassfish

I have implemented a Restful API for my simple application using Jersey, this API (Restful webservice) is protected by JAAS (Java Authentication and Authorization Service).
Now if user try to access a URL something like example.com/api/user/info/1, A popup(BASIC-Authentication) appears in browser to take input for username and password on successful login user is able to see the result (success).
so far so good.
Now I was thinking about the 3rd party application that will access my Restful web service. must authenticate before accessing any endpoint. (I know if an un-authenticated user will try to access my endpoint URLs JAAS will intercept that).
I am also aware that if I provide username and password in the request header, JAAS will automatically authenticate that as well.
Confusions:
1 - I do not want to embed username and password onto each request (I am not suer why, but I just don't want it (Please share your comments)) so that if I am accessing secure endpoint get authenticated automatically. I just want to authenticate a user and generate a token and then use that token in rest of the communication.
2 - I want to provide some endpoint for 3rd party applications to deliberately initiate the authentication process.
example.com/api/authenticate but the username and password still in header. and when endpoint's relative method is called it extract username and password from that request's header. I am aware of 2 annotations #QueryParam and #FormParam, but I want something like #HeaderParam.
Why? I think that is more secure way. (Is that right?)
#Path("authenticate")
public String authenticate( ) {
}
3 - I tried multiple techniques to login programmatically but none seems to work on Glassfish, so is it right its not possible on Glassfish? I am using Realm based JAAS.
4 - I am looking for some way once I have authenticated the user prorgammatically, add some information to the session. and in any other request get that information from session. (I am using Jersey based classes for endpoints and EJBs for business logic) - I know in EJBs through context we can lookup principal and then from that we can retrive the user record from database etc. but is there any thing Jersey Endpoint classes can add to the session and get them back in any other endpoint class?
5 - Is it enough for 3rd party application to save cookies returned by my Webservice and embed them in next request to have long lasting session for JAAS authenticated user (so that authentication process may not be required on each request)

Categories

Resources