Tracking of who created or changed an entity in microservices - java

Usually in spring boot applications, we can use jpa audit to do the tracking.
Spring Boot Jpa Auditing
While in microservices architecture, I'd try to avoid involving security in core microservice. Instead, we can do authentication/authorization at api gateway.
While, if the core service didn't get the current login user, we have to find an way to pass the current operator to core services. It could be an user identifier header on the request. Or Maybe we can pass token to core services to let it fetch the login user from auth server.
I am wondering if anyone has handled such case and give out some suggestion.

If I understand the question correctly ...
You have an API gateway in which authentication/authorisation is implemented
On successful negotiation though the API gateway the call is passed on to a core service
The core services perform some auditing of 'who does what'
In order to perform this auditing the core services need the identity of the calling user
I think the possible approaches here are:
Implement auditing in the API gateway. I suspect this is not a runner because the auditing is likely to be more fine grained than can be implemented in the API gateway. I suspect the most you could audit in the API getway is something like User A invoked Endpoint B whereas you probably want to audit something like User A inserted item {...} at time {...} and this could only be done within a core service.
Pass the original caller's credentials through to the core service and let it authenticate again. This will ensure that no unauthenticated calls can reach the core service and would also have the side effect of providing the user identity to the core service which it can then use for auditing. However, if your API gateway is the only entrypoint for the core services then authenticating again within a core service only serves to provide the user identity in which case it could be deemed overkill.
Pass the authenticated user identity from the API gateway to the core service and let the core service use this in its auditing. If your API gateway is the only entrypoint for the core services then there is no need to re-authenticate on the core service and the provision of the authenticated user identity could be deemed part of the core service's API. As for how this identity should be propagated from the API gateway to the core service, there are several options depending on the nature of the interop between API gateway and core service. It sounds like these are HTTP calls, if so then a request header would make sense since this state is request scoped. It's possible that you are already propagating some 'horizontal state' (i.e. state which is related to the call but is not a caller supplied parameter) such as a correlationId (which allows you to trace the call though the API getway down into the core service and back again), if so then the authenticated user identify could be added to that state and provided to the core service in the same way.

DO you have code Example. I have tried to pass token from zuul to other module. But I always got null in header in another module.

Related

Keycloak and SpringBoot

I started playing with Keycloak, but I have a question. While reading articles, I always found examples where a client (let's say Angular) is logging in on Keycloak, it gets a bearer and then it send the bearer to the SpringBoot application. The backend, so, validates that the bearer is valid and, if so, it allows you accessing the desired endpoint.
But it's not enough in my opinion. I don't need just to login, I would need the entire functionality - let's say I have a backend application and I need a user. I could have a basic todo-application, how do I know for which backend user I am actually accesing an endpoint?
Straight question: how can I bind my own backend user (stored in the DB from backend) to the one from Keycloak?
What is the best way to do it? The only thing that I found online and into the Keycloack documenation is that I could move the logic of logging in from client (Angular) to backend (SpringBoot). Is this the way to go?
Imagine like I'm creating my manual /login endpoint on backend on which I would then call the Keycloak server (Keycloak REST client?) and I would pass myself (as a backend) the bearer to the client.
Please help me with an explanation if I'm right or wrong, what's the best practice, maybe help me with an online example, because I just found out the too easy ones.
OpenID tokens are rich
Keycloak is an OpenID provider and emits JWTs. You already have the standard OpenID info about user identity in the token (matching requested scopes), plus some Keycloak specific stuff like roles plus whatever you add with "mappers".
All the data required for User Authentication (identity) and Authorization (access-control) should be embedded in access-tokens.
How to bind user data between Keycloak and your backend
In my opinion, the best option is to leave user management to Keycloak (do not duplicate what is already provided by Keycloak). An exception is if you already have a large user database, then you should read the doc or blog posts to bind Keycloak to this DB instead of using its own.
Spring clients and resource-servers configuration
I have detailed that for Spring Boot 3 in this other answer: Use Keycloak Spring Adapter with Spring Boot 3
In addition to explaining configuration with Spring Boot client and resource-server starters, it links to alternate Spring Boot starters which are probably easier to use and more portable (while building on top of spring-boot-starter-oauth2-resource-server).
I Also have a set of tutorials from most basic RBAC to advanced access-control involving the accessed resource itself as well as standard and private OpenID claims from the token (user details) there.
Tokens private claims
For performance reason, it is a waste to query a DB (or call a web-service) when evaluating access-control rules after decoding a JWT: this happens for each request.
It is much more efficient to put this data in the tokens as private claims: this happens only once for each access-token issuance.
Keycloak provides with quite a few "mappers" you can configure to enrich tokens and also allows you to write your own. Sample project with a custom Keycloak mapper here. This is a multi-module maven project composed of:
a custom "mapper" responsible for adding a private claim to the tokens
a web-service which exposes the data used to set the value of this claim
a resource-server reading this private claim to take access-control decisions
The simplest way to do it is to consider that the job of storing users will be delegated to your Keycloak server. But you can implement some roles and checks manually with in-memory or any database of your preference too.
I invite you to follow some documentation about OAuth 2 and Keycloak, to make requests to get a valid token for a time period and to make others request inside that time period to get datas. You can use CURL to make requests or web/software tools like Postman.
Be careful, a lot of Keycloak Adapters are deprecated ones since some months.
I would echo BendaThierry's comments. Look into OAuth2 and Keycloak. The Bearer token you receive from Keycloak will have user information in it (typically in the Claims). This way you can have user preferences or features in your backend without needing to manage the authorization and authentication that Keycloak does.
There are lots of great resource include Spring's website tutorials (like https://spring.io/guides/tutorials/spring-boot-oauth2/) and Baeldung (https://www.baeldung.com/).

Should we expose REST API as an OAuth 2 resource server?

I have a spring boot application exposing several REST API endpoints. I want to enable google oauth authentication (authorization code grant) on it. I am guessing what is correct way to do this out of following options:
Have separate application as OAuth 2 client (i.e. with spring-boot-starter-oauth2-client dependency and make the existing app a resource server (i.e. with spring-boot-starter-oauth2-resource-server dependency)
a. This Udemy's course keeps two application separate: resource server, OAuth 2 client. Then it seem to need a proxy REST endpoint in oauth
2 client project corresponding to every REST endpoint in resource server. REST end point in OAuth 2 client retrieves access token and adds it to every request to corresponding REST endpoint in resource server.
b. This stackoverflow threads talks about making same application both OAuth2 client as well as resource server
Make the existing app OAuth 2 client. (that is include spring-boot-starter-oauth2-client dependency) and simply require user to be authenticated to access REST endpoint URLs.
I have following doubts:
Q1. Should REST API always be exposed as resource server? And if yes, then is approach 2 not-so-recommended way? (as it does not expose existing REST API as resource server but as a part of OAuth client with restricted access to those APIs)?
Q2. If approach 2 is not fine, then which of approaches (1.a) and (1.b) are preferred or when to prefer one above other? (I believe (1.a) is more suitable when we want single OAuth client as a point of access for several different resource servers.)
In OAuth2 world, a REST API is a resource-server by definition.
In your scenario, Google currently is an authorization-server. You could hide it behind a Keycloak instance or something else capable of user identity federation if you need to extend to other identity providers (Github, Facebook, etc.) or want some roles definition, but as Google serve JWT access-tokens, you can use it for you resource-server security (if google IDs are enough for your security rules).
In both cases (Google directly or with an OIDC authorization-server in the middle), you can find sample configuration here (or there if you prefer to stick to spring-boot-starter-oauth2-resource-server but it requires more Java conf as you can see in tutorials).
I personnaly don't like to merge client(s), resource-server(s) and authorization-server(s). My clients are generally mobile and web with client-side rendering (Angular), but even for spring clients I'd keep it separate.
There is a special case, thought: when a resource-server delegates some of its processing to another, then, by definition, it is a client too. In that case, it is possible that security requirements and mechanisms are pretty different:
is your API authenticating in its own name (using client credentials flow)? In that case, you might use spring-boot-starter-oauth2-client to negotiate access-token to be used when issuing requests to other service.
is your API issuing requests in the name of authenticated user and does the other service know about the authorization-server which issued user authentication? In that case, you can forward the token you received
is the service you are consuming not OAuth2 at all? (just requires basic auth header for instance)

Using a managed identity with Azure Service Bus

I want to use a managed identity to connect to Azure Service Bus. In the docs they mention the DefaultAzureCredentialBuilder. I don't really get how this would use my managed identity to authenticate to the Service Bus.
Does anyone know this?
DefaultAzureCredential is a chained credential; internally it considers multiple authorization sources, including managed identities. More information can be found in the Azure.Identity overview.
Service Bus can use any of the Azure.Identity credentials for authorization. DefaultAzureCredentialBuilder is demonstrated only because it allows for success in a variety of scenarios.
If you'd prefer to restrict authorization to only a managed identity, you can do so by using ManagedIdentityCredentialBuilder rather than the default credential. An example of creating the can be found here. It can then be passed to Service Bus in the same manner as the default credential.

Add Oauth2 scopes (Keycloak implementation) to request header before client Authorization request fires (Sring boot + Keycloak)

I'm using keycloak as an auth server, my client app is a sring-boot one with the keycloak client adapter dependency.
One challenge I have not yet tackled, is the insertion of specific scopes on the request header before an authorization request executes (towards the auth server - keycloak auth endpoint).
Right now I've tested my endpoints (using access-tokens with limited capabilities by the use of scopes ) via curl and/or postman and they behave as expected, so I know they work. But I don't know when/how can I append them as a "scope" request header when using spring boot (mainly because that's all plumbing code that runs under the hood in spring boot).
I assume I would need to use some kind of interceptor/filter that gives me access to that request object just before "executing", but I haven't been able to find a concrete example.
Any suggestion/guidance or pointing towards relevant documentation would be greatly appreciated.
thanks in advance.
UPDATE:
Since my last post; I've tested several combinations to achieve this, and sadly none have worked, it is quite amazing that something as basic to oAuth2 like injecting scopes on the authorization request, isn't supported easily out of the box by the spring boot keycloak adapter. I've tried following approaches:
1 - Using a custom implementation of Sping "ClientHttpRequestInterceptor" . This doesn't help because this interceptor provides access to the front-channel requests (or requests reaching the app through the front-controller), it doesn't provide access to the back-channel request (of which the auth-request is part of).
2 - "ClientHttpRequestInterceptor" is usually also used in conjunction with a "RestTemplate" custom implementation. The problem here is that this would work only to those requests executed through an instance of the RestTemplate, and this is not what happens with the back-channel requests used by the spring-adapter
3 - Using Configuration objects based on springsecurity. spring-security offers usefull filters for configuration components that could help here (#Configuration, #EnableWebSecurity, #ComponentScan(basePackageClasses = KeycloakSecurityComponents.class OR #KeycloakConfiguration); This global type of configuration basically mix your spring boot keycloak adapter app with springsecurity code, and while this works fine for most cases, if you happen to use/need "policies" (By using the "keycloak.policy-enforcer-config" type of configs), then your policies will stop working, and whole set of new issues will arise.
FROM: https://oauth.net/2/scope/
OAuth Scopes
tools.ietf.org/html/rfc6479#section-3.3
Scope is a mechanism in OAuth 2.0 to limit an application's access to
a user's account. An application can request one or more scopes, this
information is then presented to the user in the consent screen, and
the access token issued to the application will be limited to the
scopes granted.
The OAuth spec allows the authorization server or user to modify the
scopes granted to the application compared to what is requested,
although there are not many examples of services doing this in
practice.
OAuth does not define any particular values for scopes, since it is
highly dependent on the service's internal architecture and needs.
It is clearly stated that scopes can be requested by the application to receive tokens with limited access, yet all on-line documentation to achieve this with the keyclock adpaters (and particularly spring boot) is almost(completely?) non existant.
some redhat's keycloak expert could offer suggesstion?

Implementation of Spring Security 3.1 across multiple domains, service bus and applications

I am trying to find a good way to implement Spring Security 3.1 across all my applications and my service bus.
Service Bus:
REST-services talking with the DB. This is also where all the user information is coming from.
Other applications (war's):
I want to be able to have multiple application stationed at different servers, all authenticating users and talking with the Service Bus through Spring's RestTemplate.
The problem is that the user SessionContext created by Spring Security on the Service Bus is useless when the login call is made via RestTemplate from another domain.
Also I dont want to keep sending the username and password for every call that I'm making to service bus, and then have that look it up in the DB every time.
One time per session should be enough.
I would love to hear your suggestions on how I could go about to implement this.
How do they do it in the Enterprice world?
I've been thinking about CAS, LDAP and even implementing it with Atlassian Crowd, but it seems like such an unnecessary effort.

Categories