Jhipster Oauth2 + Keycloak User identity duplicated - spring

I am creating a new application with jhipster Oauth2.
Jhipster version: 7.2.0
I would wonder
Why did every microservices got duplicated user entity ?
Why do we need to sync with Keycloak user via UserService.syncUserWithIdP on every microservices ?
Example JDL:
application {
config {
baseName gateway
packageName com.gateway
applicationType gateway
authenticationType oauth2
buildTool maven
clientFramework react
prodDatabaseType postgresql
serviceDiscoveryType eureka
testFrameworks [cypress,cucumber]
}
entities Blog, Post, Tag, Product
}
application {
config {
baseName blog
packageName com.blog
applicationType microservice
authenticationType oauth2
buildTool maven
databaseType sql
devDatabaseType h2Disk
prodDatabaseType postgresql
enableHibernateCache true
serverPort 8081
serviceDiscoveryType eureka
clientFramework react
testFrameworks [cucumber]
jhiPrefix blog
}
entities Blog, Post, Tag
}
application {
config {
baseName store
packageName com.store
applicationType microservice
authenticationType oauth2
buildTool maven
databaseType sql
devDatabaseType h2Disk
prodDatabaseType postgresql
enableHibernateCache true
serverPort 8082
serviceDiscoveryType eureka
clientFramework react
testFrameworks [cucumber]
jhiPrefix store
}
entities Product
}
entity Blog {
name String required minlength(3)
handle String required minlength(2)
}
entity Post {
title String required
content TextBlob required
date Instant required
}
entity Tag {
name String required minlength(2)
}
entity Product {
title String required
price BigDecimal required min(0)
image ImageBlob
}
relationship ManyToOne {
Post{blog(name)} to Blog
}
relationship ManyToMany {
Post{tag(name)} to Tag{post}
}
paginate Post, Tag with infinite-scroll
paginate Product with pagination
microservice Product with store
microservice Blog, Post, Tag with blog
dto * with mapstruct
service * with serviceClass
I tried to search for explanation via https://www.jhipster.tech/security/#oauth2 but no luck at the moment.
Any help or support would be appreciated.
Thank you so much and Have a good day.

Related

Using a custom identity provider in Quarkus

In my current project, we store user login info inside a MongoDB collection. We would like to implement an authentication mechanism that checks the credentials from a request against the information stored in said MongoDB. There is a tutorial for doing this with JPA + Postgres but there is no information on using MongoDB in the same capacity. I suspect that I would need to write a custom IdentityProvider for this case. I tried using the JPA identity provider as a base, but it looks like the security-jpa source code contains only an abstract identity provider, while the actual provider is generated automatically using black magic. Has anyone ever had success adapting the existing Quarkus security architecture to MongoDB or anything else that is not covered by security-jpa?
After some research, I was able to get a custom IdentityProvider to work. Here's a very simple demo (without any MongoDB logic):
#ApplicationScoped
public class DemoIdentityProvider implements IdentityProvider<UsernamePasswordAuthenticationRequest> {
private static final Map<String, String> CREDENTIALS = Map.of("bob", "password124", "alice", "hunter2");
#Override
public Class<UsernamePasswordAuthenticationRequest> getRequestType() {
return UsernamePasswordAuthenticationRequest.class;
}
#Override
public Uni<SecurityIdentity> authenticate(UsernamePasswordAuthenticationRequest request,
AuthenticationRequestContext authenticationRequestContext) {
if (new String(request.getPassword().getPassword()).equals(CREDENTIALS.get(request.getUsername()))) {
return Uni.createFrom().item(QuarkusSecurityIdentity.builder()
.setPrincipal(new QuarkusPrincipal(request.getUsername()))
.addCredential(request.getPassword())
.setAnonymous(false)
.addRole("admin")
.build());
}
throw new AuthenticationFailedException("password invalid or user not found");
}
}
Note that in order to access QuarkusSecurityIdentity, the quarkus-security extension needs to be included as dependency in pom.xml:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security</artifactId>
</dependency>
Furthermore, quarkus.http.auth.basic=true needs to be added to application.properties for the identity provider be used with basic auth.

Graphql for aggregation using Spring

My application has REST API built and we are planning to use GraphQL. Would like to know if there is any documentation or any online reference briefing the integration of GraphQL Apollo with Spring on server side. Any help please.
Your question way too broad to be answered. Any GraphQL client will work with any GraphQL server, and the server can be implemented with any framework stack, as GraphQL is only the API layer.
For a minimal (but pretty complete) Spring Boot example with graphql-java, using graphql-spqr, see https://github.com/leangen/graphql-spqr-samples
In short, you create a normal controller, where you create the GraphQL schema and initialize the runtime, and expose an endpoint to receive queries.
#RestController
public class GraphQLSampleController {
private final GraphQL graphQL;
#Autowired
public GraphQlSampleController(/*Inject the services needed*/) {
GraphQLSchema schema = ...; //create the schema
graphQL = GraphQL.newGraphQL(schemaFromAnnotated).build();
}
//Expose an endpoint for queries
#PostMapping(value = "/graphql", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
#ResponseBody
public Object endpoint(#RequestBody Map<String, Object> request) {
ExecutionResult executionResult = graphQL.execute((String) request.get("query"));
return executionResult;
}
}
This is the bare minimum. For a complete tutorial, using graphql-java-tools but without Spring, check out the Java track on HowToGraphQL.

How to generate dynamic query in #Query annotation from spring boot

My json which stored mongodb,
{
"deviceId": "testdevice",
"deviceData": {
"device_owner": "Anand",
"device_type": "xxxx"
"device_desc": "xxxx"
...
}
}
Here deviceData is device specific.It may vary based on devices. I want to generate dynamic way to filter data based on device data , i.e, deviceData.OBJECT=VALUE. I am trying to retrieve the value from spring boot app.
My spring boot DAO class
#Query({'device':?0, 'deviceData.filterString'})
Page findByDeviceData(String deviceId, String filterString,Pageable pageable);
Can any one help how to achieve this
Thanks in advance.

Spring OAuth 2 + Spring Data Neo4j multi-tenancy

I'm going to implement multi-tenancy support in my Spring OAuth 2 + Spring Data Neo4j project.
I have configure my OAuth2 Authorization Server with a few different clients with a different clientId.
Also, I have added a base TenantEntity to my Spring Data Neo4j models:
#NodeEntity
public abstract class TenantEntity extends BaseEntity {
private String tenantId;
public String getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
}
All of my existing Spring Data Neo4j entities must now extend this TenantEntity.
Right now I'm going to rewrite all of my Neo4j queries in order to support this tenantId parameter.
For example current query:
MATCH (d:Decision)<-[:DEFINED_BY]-(c:Criterion) WHERE id(d) = {decisionId} AND NOT (c)<-[:CONTAINS]-(:CriterionGroup) RETURN c
I going to rewrite to following:
MATCH (d:Decision)<-[:DEFINED_BY]-(c:Criterion) WHERE id(d) = {decisionId} AND d.tenantId = {tenantId} AND c.tenantId = {tenantId} AND NOT (c)<-[:CONTAINS]-(:CriterionGroup) RETURN c
In turn for tenantId I'm going to use OAuth2 clientId and store it together with every Neo4j entity.
Is it a correct approach in order to implement multi-tenancy or Spring OAuth2/Data Neo4j can propose something more standard for this purpose out of the box ?
Since Neo4j currently has no feature to support multi-tenancy, if you particularly need this, it must be worked-around as you have done. You solution looks reasonable.
Alternatively, licensing is by machine, so it is possible to use, for example, Docker and spin up multiple Neo4j instances each on a different port.

Grails 2.2.3 + Spring security core + Multi-tenant Single DB plugin

I am new to grails and I am trying to implement spring security core and Multi-tenant single db plugin.
I have implemented the spring security core first and implemented custom AuthenticationProvider and Authentication.
Then I have installed the multi-tenant single db plugin and ran the 'mt-spring-security' script that automatically created custom tenantResolver and tenantRepository. I have hard-coded the tenantId in tenantResolver for testing purpose.
I have added the #MultiTenant annotation in the domain classes.
#MultiTenant
class ClientUser implements Serializable {
long idclient_user
Userprofile user
Client client
int tenantId
...
}
In the AuthenticationProvider, the ClientUser data is not filtered for the current tenant. It is bringing the data the all the tenant.
class ClientAuthenticationProvider implements AuthenticationProvider {
Authentication authenticate(Authentication auth) throws AuthenticationException {
ClientAuthentication authentication = auth
String password = authentication.credentials
String username = authentication.name
String clientName = authentication.clientName
...
Userprofile.withTransaction { status ->
def user = Userprofile.findWhere(username: username)
def client = Client.findWhere(clientname: clientName)
def clientUser = ClientUser.findWhere(client: client, user: user) <-- NOT FILTERED FOR THE CURRENT TENANT. I HARD-CODED INVALID TENANTID IN THE TENANTRESOLVER AND EXPECTING IT TO FAIL BUT IT STILL FINDS THE USER.
if (!clientUser) {
throw new UsernameNotFoundException('User not found', username)
}
...
}
...
result
}
I am not sure how the multi-tenant and spring security works together. I am having a hard time understanding the Architecture/design.
If anyone could provided me with a sample implementation or point me in the right direction, it will be really helpful.
Thanks,
dinesh
The problem was that the multitenant filter was registered before the spring security filter so the tenantResolver was not called until after the Spring security authentication. I fixed this problem by setting the resolveTenantBeforeLogin to true in the config.groovy
In config.groovy, add this line
multiTenant.resolveTenantBeforeLogin=true
After i added this line, the tenantResolver is called first and then the authentication.

Resources