How to get user id, and user UUID/GUID from Keycloak?

Viewed 4756

I'm using Keycloak inside docer and hosted on https://accounts.example.com.

I'm using React as my client library and after login, user goes into https://user.example.com.

This React client uses .NET Core API located at https://api.user.example.com.

I use keycloak.js to manage access in React panel.

Now let's say user wants to create a ticket. I send this ticket info to the API:

{
    title: 'Urgent backup',
    priority: 'urgent',
    description: 'Please backup my files immediately'
}

In our database, we have this design:

create table Tickets
(
    Id bigint not null primary identity(1, 1),
    UserGuid uniqueidentifier not null, -- How should I fill this column?
    Title nvarchar(200) not null,
    PriorityId int not null,
    Description nvarchar(max) not null
)

The problem is, API should extract a permanent data from user.

I can't store email or username in that column of course. And I can't even rely on username or email because Keycloak's admin panel allows this setting to be configured:

enter image description here

Thus the best option is to give user a GUID or UUID in Keycloak, and retrieve it in open id token.

I searched but I can't find how to do this.

Can you help?

2 Answers

By default your acccess token should have a subject (sub) claim with a value of the user's id in Keycloak. That is a UUID. You can extract that ID from the token and use it.

Maybe ASP.NET core will do this automatically and provide the subject claim as the username for you.

I am not sure where exactly is the issue ,Keycloak already provide the API to get/update/delete user

Get users Returns a list of users, filtered according to query parameters:

GET /{realm}/users

In Query Parameters you can filter according to email/first/lastName/username

and it will give result something like this if you want to fetch all user

[
     {
        "id":"569f67de-36e6-4552-ac54-e52085109818",
        "username":"user1",
        "enabled":true,
        ...
     },
     {
        "id":"90afb701-fae5-40b4-8895-e387ba34902jh",
        "username":"user2",
        "enabled":true,
        ....
     }
  ]

If you want to fetch individual user ,you can get it that also with below API

GET /{realm}/users/{id}

If you see the first rest query ,you can query as per your requirement with Query Parameters and get the result and then id can be use for your second table.

Edit -

By default, the User ID can be obtained directly from the principal

String userId = accessToken.getSubject();

in .Net Core I found this

public static T GetLoggedInUserId<T>(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        var loggedInUserId = principal.FindFirstValue(ClaimTypes.NameIdentifier);

        if (typeof(T) == typeof(string))
        {
            return (T)Convert.ChangeType(loggedInUserId, typeof(T));
        }
        else if (typeof(T) == typeof(int) || typeof(T) == typeof(long))
        {
            return loggedInUserId != null ? (T)Convert.ChangeType(loggedInUserId, typeof(T)) : (T)Convert.ChangeType(0, typeof(T));
        }
        else
        {
            throw new Exception("Invalid type provided");
        }
    }
Related