1

I am developing a web site.

frontend (SPA / vue.js) <-> REST backend (Spring Boot 3.2.1, Java 21)

I chose the keycloak IDP for the authorization server so as not to write a custom implementation of registration and authorization from scratch. This is my first time working with keycloak.

I use the spring-addons software and implemented the BFF design based on the example.

frontend <-> Spring Gateway (Client ouath2) <-> Spring REST Backend (oauth2 resource server)

I'm facing a problem, I don't understand how to bind user from keycloak to my Hibernate entity.

Simple example:

@Entity(name = "post")
public class Post {
    
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Access(AccessType.PROPERTY)
    private Integer id;

    // another fields

    @Column(name = "content")
    private String content;

    @Column(name = "author_id", insertable = false, updatable = false)
    private Integer authorId; // how to ??? Keycloak user id is GUID...

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", referencedColumnName = "id")
    private KeycloakUser author; // how to ??? KeycloakUser - example

    // constructors / getters / setters omitted

}

The question is how do I assign their authors to my entities so that later using JPA I can extract them on request, for example findById ?

I found a solution in the fact that I need to maintain a separate database of users of my application, two implementation options:

  1. A filter that checks the existence of the current authorized user and if he is not registered in the application DB, then register him;

  2. SPI, an event system that could be used to intercept a new user registration event and add it to the application's user database.

So far, both options look doubtful to me personally, I would like to learn about the best practices for solving such a problem, if possible with examples.

1 Answer 1

2

The answer is "you should probably not".

Maybe, you should think in a multi-service architecture where the OAuth2 authorization server (Keycloak in your case) is the service responsible for user data. Other services store no more than an immutable identifier for users in Keycloak (sub claim is a natural candidate, but you could use preferred_username too, if it can't change over time).

A service needing more than this ID would just read the access token claims when accessing the current user data, or use Keycloak's "admin" API to get the current values for any other user.

If you duplicate user data, you'll inevitably run into synchronisation issues and inconsistencies.

You can browse this project where I do just like that

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks a lot for the reply, I'll mark it as accepted. I would like to clarify one question, how do you feel about the fact that the identifier of the owner/author of the entity is a String, and not the usual id? How can this affect the system in the future? I also wanted to express my special thanks for creating spring-addons, you saved me the headache of configuring oauth2
A database ID really doesn't have to be a Long and it doesn't have to be auto-generated by the database itself. A UUID String for instance is perfectly acceptable. As a general consideration, when you use an external service, the good thing is that you don't have to care about its internal implementation. In this case, how it handles IDs is none of your business. All that you care is that this service provides with such an identifier and that it is constant in time for a given user.
I understand your answer, but it makes implementing some features from really complicated to impossible. Like ordering the list of my database entities, by user name that created them. Or searching entities by author e-mail. What would be a simple database JOIN + ORDER BY, becomes a complicated task.
For the 2nd need, I'd have the frontend first query the users service to retrieve the ID of the user with the given email, and then query the entities service with this user ID. I don't see the point of sorting entities by creator name. But I guess that in such a case, I'd first query the entities (with good enough criteria to have a limited entities in the result), then query the users service to get the names for the user IDs in the entities result, and last sort the entities in the frontend.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.