andymel
andymel

Reputation: 5666

Problem saving custom attribute for keycloak users

Context
I have a php website. Keycloak is used for auth. This part works fine. I now try to save user related state to keycloak directly via its REST API (to not need another user db).

The Problem
When I try to do the request PUT /admin/realms/{realm}/users/{user-id} (from the rest-api docs) I get

{
  "error":"unknown_error", 
  "error_description":"For more on this error consult the server log at the debug level."
}

The Keycloak logs

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'attributes': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')

To build the PUT request I use PHP curl. My value for CURLOPT_POSTFIELDS is

json_encode([
    "attributes" => [
        "test" => ["foo"]
    ]
])

which produces the following request body {"attributes":{"test":["foo"]}}. This should be a UserRepresentation (from the docs).

Unfortunately I can't find any other hints about what I do wrong in the docs or keycloak logs. Any idea?

Update When I came back from my weekend it simply worked. Unfortunately I don't know what the problem was. In addition I decided against saving attributes to my users in keycloak as it seems like I can only override the whole user object. As I have spent way too much time with making this feature work I will instead save my data into my own db, referenced by the keycloak userid.

Upvotes: 1

Views: 354

Answers (1)

Austin
Austin

Reputation: 13

I am not a PHP developer, but I achieved the same result in a Java project. I was able to save and update users to Keycloak via the REST Admin endpoints using the model below.

Keycloak version 20.0.3 used

public class KeycloakUser {

  private String id;
  private String username;

  private String email;

  private boolean enabled;

  private String firstName;

  private String lastName;

  private boolean emailVerified;

  private Map<String, String> attributes;

  private List<Credential> credentials;

  private List<String> requiredActions;
}

From you JSON encoding, You can try this instead {"attributes":{"test":"foo"}}. Make the value of the attributes a dictionary/map of Strings as both the keys and the `values' respectively.

Upvotes: 1

Related Questions