Giter Club home page Giter Club logo

keycloak-nodejs-admin-client's Introduction

Keycloak

GitHub Release OpenSSF Best Practices GitHub Repo stars GitHub commit activity

Open Source Identity and Access Management

Add authentication to applications and secure services with minimum effort. No need to deal with storing users or authenticating users.

Keycloak provides user federation, strong authentication, user management, fine-grained authorization, and more.

Help and Documentation

Reporting Security Vulnerabilities

If you have found a security vulnerability, please look at the instructions on how to properly report it.

Reporting an issue

If you believe you have discovered a defect in Keycloak, please open an issue. Please remember to provide a good summary, description as well as steps to reproduce the issue.

Getting started

To run Keycloak, download the distribution from our website. Unzip and run:

bin/kc.[sh|bat] start-dev

Alternatively, you can use the Docker image by running:

docker run quay.io/keycloak/keycloak start-dev

For more details refer to the Keycloak Documentation.

Building from Source

To build from source, refer to the building and working with the code base guide.

Testing

To run tests, refer to the running tests guide.

Writing Tests

To write tests, refer to the writing tests guide.

Contributing

Before contributing to Keycloak, please read our contributing guidelines. Participation in the Keycloak project is governed by the CNCF Code of Conduct.

Other Keycloak Projects

License

keycloak-nodejs-admin-client's People

Contributors

agagancarczyk avatar almarro1 avatar ath88 avatar axenu avatar dependabot[bot] avatar edewit avatar egemenokten avatar fabu-khiarah avatar fritzforsit avatar jenny-s51 avatar jonkoops avatar karlhorky avatar keycloak-bot avatar kydenz avatar newexe avatar rpiotrow avatar schnitzel avatar sergiocruza avatar shellyxuehan avatar slimovic avatar ssilvert avatar stianst avatar tafaust avatar tbusillo avatar thomasdarimont avatar tvrg avatar vect-rlaplaud avatar vinh-thieu avatar wwwy3y3 avatar zagaria avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

keycloak-nodejs-admin-client's Issues

[Feature] Run tests against multiple relevant Keycloak versions

Is your feature request related to a problem? Please describe.
Currently, we only test against Keycloak version 7.0.1 as seen here https://github.com/keycloak/keycloak-nodejs-admin-client/blob/master/.travis.yml.

Describe the solution you'd like
Utilize travis test matrix to run against multiple versions of Keycloak.

Describe alternatives you've considered
I don't see any other way.

Additional context
Tests will take significantly longer, but I believe it'll be worth it. I'll supply a PR shortly.

Refactor RequiredActionAlias

We have the enum RequiredActionAlias defined as follow

export declare enum RequiredActionAlias {
    VERIFY_EMAIL = "VERIFY_EMAIL",
    UPDATE_PROFILE = "UPDATE_PROFILE",
    CONFIGURE_TOTP = "CONFIGURE_TOTP",
    UPDATE_PASSWORD = "UPDATE_PASSWORD",
    terms_and_conditions = "terms_and_conditions"
}

Since on Keycloack we have the ability to create our own custom required actions using SPI I feel this enum should be more generic otherwise we are gonna have typing issues.

What about something like this?

export declare enum StandardRequiredActionAlias {
  VERIFY_EMAIL = "VERIFY_EMAIL",
  UPDATE_PROFILE = "UPDATE_PROFILE",
  CONFIGURE_TOTP = "CONFIGURE_TOTP",
  UPDATE_PASSWORD = "UPDATE_PASSWORD",
  terms_and_conditions = "terms_and_conditions"
}

export declare type RequiredActionAlias = StandardRequiredActionAlias | string

This will allow us to do

client.users.executeActionsEmail({
   id: "123"
   actions: ["INVITE_USER", StandardRequiredActionAlias.CONFIGURE_TOTP]
 })
}

How to use identity provider?

Hello, I am using facebook and google to my website using keycloak.

I need your help how to use identity providers?

  1. How to create user with identity provider?
    I don't know how to create with identity provider. So, I created a user with username(test1) and password(test1) manually and added facebook identity provider to the created user.
    But I don't think this is the solution to create user with facebook.
    I'd like to know how to create user with facebook identity like signup with facebook on keycloak.

  2. How to login with identity provider?
    Even I created user by manually adding facebook identity provider, I can't do keycloak login with identity provider. How to use facebook identity for login?

Please help me.

Feature: Request offline token

Is your feature request related to a problem? Please describe.
Using the keycloak admin client on a backend server requires getting a new refresh token once in awhile.

Describe the solution you'd like
Keycloak supports requesting an offline token instead of a regular refresh token. This would allow a client to never need to refresh the refresh token.

Describe alternatives you've considered
An alternative is to re-authenticate once the keycloak-session has timed out. This is cumbersome.

Additional context
Adding the scope: 'offline_access' to the axios-post payload [1] fixes the problem. Perhaps the scope could just be extracted from the Settings-object.

[1] https://github.com/keycloak/keycloak-nodejs-admin-client/blob/master/src/utils/auth.ts#L45

Issue with the example provided to refresh the access token

I am trying the example in the README to refresh the access token using the openid-client but unfortunately I'm not able to get the client working.

To Reproduce
Steps to reproduce the behavior:

  1. Just run the example in the README
  2. After instantiating the client, I tried to console log the client and I'm getting { CLOCK_TOLERANCE: 0 }
  3. And of course there is no refreshToken

const client = new keycloakIssuer.Client({ client_id: 'admin-cli', client_secret: 'wwwy3y3', }); console.log(client.refreshToken); // undefined

Expected behavior
The client must contains other properties like the refreshToken.

Enviroment:

  • OS: [Ubuntu/Windows]
  • Keycloak Version: I tried 3.4.3 and 4.8.0
  • Library Version [1.9.0]
  • NodeJs: v8.15.0 and with 10.15.1 I'm getting this warning:

(node:47720) [DEP0079] DeprecationWarning: Custom inspection function on Objects via .inspect() is deprecated

Additional context
Am I missing something? Just not sure that the client_secret must contain a password or a real secret.
I know this is not fully related to this library, but it will be nice to make this example works.

findOne by username return array

Hi,

When i use findOne method with username param it's return array of UserRepresentation

const user = await kcAdminClient.users.findOne({ username: 'test' });

console.log(user);
[
  {
    "id": "4c1aabe8-8307-404d-818b-721ddc507d44",
    "username": "test",
    ...
  }
]

Is this the expected behavior?

When i use findOne with id param, return UserRepresentation Object

Tests fail against Keycloak 8+

Describe the bug
The test suite fails with this error against Keycloak 8.0.2 and newer.

  1) Users
       should remove totp:
     Error: Request failed with status code 404
      at createError (node_modules/axios/lib/core/createError.js:16:15)
      at settle (node_modules/axios/lib/core/settle.js:17:12)
      at IncomingMessage.handleStreamEnd (node_modules/axios/lib/adapters/http.js:244:11)
      at endReadableNT (_stream_readable.js:1145:12)
      at process._tickCallback (internal/process/next_tick.js:63:19)

To Reproduce
Check the logs here:
https://github.com/keycloak/keycloak-nodejs-admin-client/actions/runs/460584766

Expected behavior
The tests should pass

Screenshots
I posted the log above - should be sufficient

Additional context
Keycloak 9+ has the same issue, but there are additional failures. Lets tackle one at a time.

Update to Keycloak Admin REST API v9.0

Is your feature request related to a problem? Please describe.
Some features are missing while comparing this client with the v9.0 API documentation. For instance, while querying all groups of a realm, it is now possible to get the full group representation by using the briefRepresentation=false flag from the API, but not with this client.

Describe the solution you'd like
I don't know how this project intend to support different versions, but from what I've see we can just add optional fields queries options (like GroupQuery in my example).

Describe alternatives you've considered
For now I'll do custom HTTP calls for those that I need new features.

Additional context
GET groups v7
GET groups v9

Update feature is not working correctly.

If i want to change the user firstname, then i initially fetched the user details
user = client.users.find('RealmName', { username: username });
//above "find" is working.
user.firstname = "newFirstName"
client.users.update("RealmName", user);
//but "update" function is not working.

error TS1308: 'await' expression is only allowed within an async function.

After istalling the necesary dependecys and run the yarm command i have tried tu use the script on the readme file in the usage paragraph but i get the next errors.

../../src/prueba.ts:14:1 - error TS1308: 'await' expression is only allowed within an async function.

14 await kcAdminClient.auth({


../../src/prueba.ts:22:15 - error TS1308: 'await' expression is only allowed within an async function.

22 const users = await kcAdminClient.users.find();
              ~~~~~

../../src/prueba.ts:30:17 - error TS1308: 'await' expression is only allowed within an async function.

30 const groups =  await kcAdminClient.groups.find();
                ~~~~~

../../src/prueba.ts:34:1 - error TS1308: 'await' expression is only allowed within an async function.

34 await this.kcAdminClient.users.create({

I am completely new with scripts i now some java and C but i have never used scripts before. Probably its a simple mistake but i dont undertand enought to solve the problem.

If someone has the patient to tell to a script kiddie what is what i made wrong , i would be really grateful.

Authenticating with 'client_credentials' throws 400 error 'invalid_scope'

Describe the bug
Calling kcAdminClient.auth() with grantType: 'client_credentials' throws 400 error 'invalid_scope'

To Reproduce
Steps to reproduce the behavior:

  1. run kcAdminClient.auth()
await kcAdminClient.auth({
    clientSecret: xxx,
    grantType: 'client_credentials',
    clientId: xxx
});
  1. It'll throw 400 error with message
{ 
    error: 'invalid_scope',
    error_description: 'Invalid scopes: ' 
}

Expected behavior
Keycloak should authorise the client. In version 1.13.0 its working as expected, upgrading to 1.14.2 show this behaviour

Enviroment (please complete the following information):

  • OS: Ubuntu 19.04
  • Keycloak Version: 10.0.2
  • Library Version 1.14.2

Additional context
Hasn't tried username + password authentication

Usage with require?

When developing using Node 8, we don't have access to import.
Can you provide an example of using this lib with require ?
Thanks

ETA for missing KeyCloak features?

As mentioned in the README, several KeyCloak features are not currently supported:

- Attack Detection
- Authentication Management
- Client Attribute Certificate
- Client Initial Access
- Client Registration Policy
- Client Scopes
- Key
- Protocol Mappers
- Scope Mappings
- User Storage Provider

Is there an ETA available for these, or if there are plans to support them?

Groups are not included in Response from Keycloak, but in UserRepresentation

When I try to get information from all of my users, the groups property is undefined, so its is not resolved by the keycloak admin rest api response. Is there a way to add the group information to the user endpoint in the keycloak rest api, because it seems to be quite silly to do so much request to keycloak to get every group for each user one by one, when I want to receive the users which are in the realm. I couldn't find out something about this on the internet, so I decided to open an issue here, as this might be important to other users of keycloak-nodejs-admin-client as well.

Keycloak Catch with Exact Problem

Hi, I'm new user of Keycloak, and found this great package, so I use it.

So, I've use this package for some tasks, and only return default error response if there's an error/failed.

Is there any way to get the exact error or failed message, not only the http response but with "humanly" message.
In example, I create second user with already used username, and the Catch error give me this,

image

What I need is something like Catch error when I directly hit the url (without this package), just like this,
image

I thought this is only my unknown about this package, thanks for any help and answer

kcAdminClient.roles.create should create composite roles

Describe the bug
KcAdminClient should create a composite role if composite=true within the RoleRepresentation object.
And the roles defined in composites should be applied as associated roles.

To Reproduce

const realmRole = {
    name: 'manager',
    composite: true,
    composites: {
        realm: [
            'finance-manager',
        ]
    }
} as RoleRepresentation
await kcAdminClient.roles.create(realmRole)

Expected behavior
I expect a manager role to be present with the composite flag enabled.
And the finance-manager role to be a associated role of manager.

Instead only the manager role will be created as a non-composite role without association to the finance-manager role.

Enviroment (please complete the following information):

  • OS: Fedora 31 (Workstation Edition)
  • Node.js Version v12.16.1
  • NPM Version 6.13.4
  • TypeScript Version 3.8.3
  • Keycloak Version 9.0.0
  • keycloak-admin Library Version 1.13.0

ask email for reset password

Is your feature request related to a problem? Please describe.
I want to add email and not id in case of forgot password

Describe the solution you'd like
Having the possibility to add email and/or username in place of id from executeActionsEmail

Describe alternatives you've considered
None

Additional context
I use this api for android an ios application
so if the user start the application and do not remember is password
I can't have the id from keycloak without email or username

Username and password in credentials should be optional

Describe the bug
In the code segment, these two properties are required, but not needed for a grantType of client_credentials. Making them optional would prevent ide errors that can be misleading.

Expected behavior
If I am using a clientId and clientSecret, I shouldn't need to provide the username or password or avoid type errors by using any as a patch. In testing, the auth works without those two properties being set.

Code Lines

username: string;
password: string;

Screenshots
image

It would be great not to need the any above.

Add a user count helper

I want to paginate the data when fetching users, the problem is I have to get the total count of users to generate a metadata. Fetching all users and getting its count would defeat the purpose of my pagination.

The solution is obviously getting the count of the users. There is an API available in the docs where I can get the count of the users, but there is no available helper here in the package.

Login fails with 404

Describe the bug
Trying to authenticate with login and password. It fails because the constructed URL has a double slash //, because baseUrl ends with a slash.

The error:

RESTEASY003210: Could not find resource for full path: https://<redacted>/auth//realms/test-str/protocol/openid-connect/token
                                                                               ^ here

To Reproduce
Steps to reproduce the behavior:

  1. Write a script that logs into a Keycloak instance
  2. Append a / to the provided baseUrl
  3. Run the script again, observe a 404 error

Expected behavior
The client accepts any valid URL as baseUrl

Enviroment (please complete the following information):

  • OS: MacOS Catalina
  • Keycloak Version: uhh, the latest one?
  • Library Version: 1.13.0

Test fails on Keycloak 9+

Describe the bug
The tests fail with this error:

  1) Users
       count users with filter:

      AssertionError: expected 1 to equal 2
      + expected - actual

      -1
      +2
      
      at Suite.<anonymous> (test/users.spec.ts:82:25)
      at step (test/users.spec.ts:52:23)
      at Object.next (test/users.spec.ts:33:53)
      at fulfilled (test/users.spec.ts:24:58)
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (internal/process/task_queues.js:93:5)

See https://github.com/keycloak/keycloak-nodejs-admin-client/actions/runs/463447567

To Reproduce
Spin up a Keycloak 9 for testing and run the tests-suite.

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
See log verbatim above.

Enviroment (please complete the following information):

  • Keycloak Version 9
  • Library Version - master branch

Additional context
I have not looked into the actual error, but it also exists on Keycloak 10, 11 and 12.

Cannot create client role

Describe the bug
I working with keycloak-admin to create client roles through keycloak rest api. I got error 404 (Not Found)

To Reproduce
Steps to reproduce the behavior:

  1. What API did you use?
    call function

Clients.createRole: (payload?: RoleRepresentation & { realm?: string; }) => Promise<{ roleName: string; }>

function signature is image below
image

I called function this way
image

  1. What error message did you see?
    Got error 404 (not found) when function called
    image

  2. GIve us a minimum code example
    ` var role:RoleRepresentation ={}
    role.clientRole=true;
    role.name='testrole';
    role.description='test role description';
    role.containerId=clientId;

    kcAdminClient.clients.createRole(role);`

Expected behavior
Client role should created after function called

Screenshots
If applicable, add screenshots to help explain your problem.
image

Enviroment (please complete the following information):

  • OS: windows 10
  • Keycloak Version 9.0.3
  • Library Version 1.13.0

Additional context
I think client id is missed in Clients.createRole function's parameter.
I tried to solve error in node_modules folder like below.

image

image

Client role was created as expected.

Keycloak Authenticate with Facebook Token

Hi guys, I have a problem with Keycloak authentication with social providers.

Actually, I can do authentication with keycloak username and password.

But some users are registered with facebook accounts.

After getting facebook token from my backend, I'd like to authenticate keycloak by using this token like username and password.

Otherwise, is there any way to get keycloak user's password?

Authentication Management Api + Code Examples

Is your feature request related to a problem? Please describe.
I'm having issues finding the correct steps for creating an Authentication-Flow using the management-api. This is a more complicated part of the api and some official examples would be very useful besides the test files.

Describe the solution you'd like
This has just been recently added in #126 and the lack of examples is frustrating for many reasons, especially since there is a lot of effort in building integrations with Keycloak. (think bootstrapping a realm after deployment) - lots of gaps here!!

Describe alternatives you've considered
Besides using this officially supported keycloak client, I was able to generate a node client from openapi schemas, provided by the community and work with the AuthenticationApi which is very similar, but lacks examples and is hard to reverse-engineer.

Additional context
I have had a lot of hard time around the lack of support for the AuthenticationManagement - having a small example of loading an AuthenticationFlow + Subflows / Executions and Actions would bring a lot of clarity and bliss.

Thank you!

kcClient.clients.listPolicies only returns 100 records max

Describe the bug
kcClient.clients.listPolicies method only returns maximum 100 records.
I haven't tested findPermissions method yet, but I would expect it behaves the same since it is using same underlying API.

To Reproduce
Steps to reproduce the behavior:

  1. create more than 100 policies
  2. call kcClient.clients.listPolicies without passing search team and note the length of response is 100

Expected behavior
Expect that method to return all policies.
If there is API limitation, there should be method for getting paginated results.

Screenshots
If applicable, add screenshots to help explain your problem.

Enviroment (please complete the following information):

  • OS: MacOS
  • Keycloak 11.2
  • Library Version 1.14.5

npm release?

There's a security release 1.12.1 on Github page but it's not published to npm. Shouldn't it be published?

I want to add new endpoints

Is your feature request related to a problem? Please describe.
I need to logout all sessions and delete a specific user's session

Describe the solution you'd like
I would like to support these two new endpoint

  • POST /{realm}/logout-all
  • DELETE /{realm}/sessions/{session}

Describe alternatives you've considered
These endpoints aren't supported by this library.

Additional context
I would like to add this endpoints and create a PR. Is it ok for you?

Browser support

We could use this project for building a new admin console, currently we have a small wrapper around fetch and generate the types based of the java types. But instead we could use this, only thing that we need to do is have a way to construct it without a username and password but use the keycloak-js adapter instead.

clients.findByName is confusing

Describe the bug

public findByName = this.makeRequest<
{id: string; name: string},
PolicyRepresentation
>({

Just started using the client and keycloak in general so this is from a new user perspective.

My editor suggested that method and I thought I can search clients by name, since it is clients.findByName.

Apparently you get a Policy so I think the name should be findPolicyByName

Error message: "Request failed with status code 401"

const KcAdminClient = require('keycloak-admin').default

async function setupKeycloak(realmName = "**********") {
try {
// const keycloakAdmin = new KcAdminClient()
const keycloakAdmin = new KcAdminClient({
'baseUrl': "http://localhost:16160/auth",
'realmName': 'master'
})

// Authorize with username / password
await keycloakAdmin.auth({
  'username': "*******",
  'password': "*******",
  'grantType': 'password',
  'clientId': '*********'
})

if (realmName) {
  await keycloakAdmin.setConfig({
    'realmName': realmName
  })
}

// List all users
const users = await kcAdminClient.users.find();

console.log(users)

} catch (err) {
throw new Error('Keycloak Admin: ' + err)
}
}

setupKeycloak()

Screenshots
image

Enviroment (please complete the following information):

  • OS: Windows
  • Keycloak Version: 7.0
  • Library Version : 1.12.0

User Create with roles query

Hi,

Thanks for a fantastic library. Really helping save me some time getting integrated into keycloak.

I'm trying to create a new user and specify the client roles at run time.

However no matter what I try I can't quite get the mapping right for the client roles. I've also checked against the keycloak admin api at https://www.keycloak.org/docs-api/2.5/rest-api/index.html#_userrepresentation but still couldn't figure it out.

When looking at the following

https://github.com/Canner/keycloak-admin/blob/c5a32f24b8f666d9be8518bb9da905db96b03651/src/defs/userRepresentation.ts#L21

I can see that it should be clientRoles?: Record<string, any>; however I can't quite figure out how to map that.

The code I have so far is as follows

async function getBTPClient (adminClient) {
  const client = await adminClient.clients.find({'clientId': 'btp'})
  return client[0]
}

async function getClientRole (adminClient, clientId, roleName) {
  return adminClient.clients.findRole({
    id: clientId,
    roleName: roleName
  })
}

module.exports.createUser = keycloakErrorHandler(async (master, tenantName, data, options = {}) => {
  const adminClient = await keycloakAdminClient(tenantName)

  const client = await getBTPClient(adminClient)
  const role = await getClientRole(adminClient, client.id, data.role)

  // Create user
  await adminClient.users.create({
    // enabled required to be true in order to send actions email
    'username': data.email,
    'email': data.email,
    'firstName': data.firstName,
    'lastName': data.lastName,
    'enabled': data.active,
    'credentials': [{
      'type': 'password',
      'value': data.password,
      'temporary': false
    }],
    'clientRoles': {
       [client.id]: [role.id]
    }
  })

  // Retrieve the user id
  const user = await adminClient.users.find({'username': data.email})

  // // Assign the roles
  // await adminClient.users.addClientRoleMappings({
  //   id: user[0].id,
  //   clientUniqueId: client.id,

  //   // at least id and name should appear
  //   roles: [
  //     {
  //       id: role.id,
  //       name: role.name
  //     }
  //   ]
  // })
  // Return the structured User record
  return structuredUser(adminClient, user[0])
`})

I can get it to work by adding the roles in after the user creation but would rather do it at the same time.

I'm not overlay familier with typescript so suspect it's something simple that I'm missing but just can't see it.

Any pointers much appreciated.

Thanks

Paul

Feature: client scope mappings

Is your feature request related to a problem? Please describe.
I currently use kcadm.sh to automate creation/deletion of scope mappings:

# create
./kcadm.sh create -x "clients/<foo client id>/scope-mappings/clients/<bar client id>" --body "[{\"name\": \"<bar client role name>\"}]"

# list
./kcadm.sh get -x "clients/<foo client id>/scope-mappings/"

# delete
./kcadm.sh delete -x "clients/<...>/scope-mappings/clients/<...>" --body ...

In order to migrate to NodeJS I need an API to create and delete scope mappings.

Describe the solution you'd like
Have an API for scope mappings resource at /{realm}/client-scopes/{id}/scope-mappings (at least create and del).

Can't update user

Describe the bug
After created my user,i would like to update some information (lastname, firstname, email)
so I put the new information results its ok (200)
but user is not updating

To Reproduce
Steps to reproduce the behavior:

  1. Update the user (PUT /{realm}/users/{id})
  2. No error
app.put(`/:realm/users/:id`, async (req, res, next) => {
  //update user
  const { lastName, firstName, email } = req.body

  let data = await newKcAdminClient.users.update(
    {
      id: req.params.id,
      realm: req.params.realm,
      firstName: lastName,
      lastName: firstName,
      email: email,
      requiredActions: ["UPDATE_PROFILE"],
      emailVerified: true,
      enable: true
    });
  res.end();
});

Expected behavior
Just wanted to have the information user updated

Screenshots
postman example

Enviroment :

  • OS: win 10
  • Keycloak Version 9.0.3
  • Library Version "keycloak-admin": "^1.13.0"

Keycloak refresh token

I am using this plugin for my project and I have some issue with refresh token.

Describe the bug
How to refresh token using keycloak-admin-nodejs-client?

To Reproduce
Steps to reproduce the behavior:

  1. Authorization
const kcAdmin = new KcAdminClient({
    baseUrl: config.KC_BASE_URL,
    realmName: config.KC_REALM_NAME
});
await kcAdmin.auth({
                username: "...",
                password: "...",
                grantType: "password",
                clientId: "...",
                clientSecret: "..."
});
  1. Get access_token and refresh_token
access_token = kcAdmin.getAccessToken();
refresh_token = kcAdmin.refreshToken;
  1. access_token has 1 hour lifespan and refresh_token has 1 day lifespan. Now, access_token is expired but refresh_token is still available now.

How to get refreshed token? I can get refresh token by using original Keycloak REST API but I'd like to get refresh token by using keycloak-admin.

Please someone help me to get refresh token.

I am sorry, I know this isn't bug but I don't know how to get help from you.

KcAdminClient is not a constructor

Getting below error when using
const kcAdminClient = new KcAdminClient();
as described in readme
using node version -> v12.17.0
npm version -> 6.14.4
"keycloak-admin": "^1.13.0"

(node:29132) UnhandledPromiseRejectionWarning: TypeError: KcAdminClient is not a constructor
at load (file:///Users/lalrishav/WebstormProjects/devops/script.js:9:27)
at file:///Users/lalrishav/WebstormProjects/devops/script.js:28:1
at ModuleJob.run (internal/modules/esm/module_job.js:110:37)
at async Loader.import (internal/modules/esm/loader.js:179:24)
(node:29132) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:29132) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

[Enhancement] Return resource id when creating a resource

First thing i would like to thank you for this sdk, its really helpful!
When creating a resource (e.g user, group ,real etc..), the id of the newly created resource can be retrieved from the "Location" header in the response.
image

can you alter the create functions to return the id?

Ability to set realmName (and maybe other settings) after first authentication

Use cases

  1. The Keycloak root admin user wants to log in to the master realm and then do all further operations in a secondary realm-b realm, such as creating a group. It would be desirable to not have to pass realm-b for every call.
  2. The Keycloak root admin user wants to log in to the master realm and do most operations in the master realm, except for a single operation in a realm-c realm. This is apparently already covered by #3 (comment). I'll document this in the PR.

Prior Art

The keycloak-admin-client allows for use of a different realm via requiring the user to repeat the realm for every call:

// Create the user
return client.users.create(realmName, testUser).then((user) => {
  // ...
});

Proposed API

This is a rough first version of the proposed API. The final version may look different.

const realmNameA = 'master';
const connectionSettings = {
  baseUrl: 'http://keycloak:8080/auth',
  realmName: realmNameA,
};
const keycloakClient = new KeycloakAdminClient(connectionSettings);

// Authenticate with `master` realm
await keycloakClient.auth(userSettings);

// Set defaults for all further requests
const realmNameB = 'realm-b';
keycloakClient.setConfig({
  realmName: realmNameB,
  // ...other options...
});

// One-off operation to create a group on `realm-c`
const realmNameC = 'realm-c';
await keycloakClient.groups.create({name: 'editor'}, {
  realmName: realmNameC,
  // ...other options...
}));

Technical Background

1) First instantiation of Keycloak admin client

The following user code...

const realmNameA = 'master';
const connectionSettings = {
  baseUrl: 'http://keycloak:8080/auth',
  realmName: realmNameA,
};
const keycloakClient = new KeycloakAdminClient(connectionSettings);

...does the following things:

1.1) Sets the realmName property on the instance to original realmName ("realmNameA")
1.2) Passes that instance to the constructor of various resources
1.3) Passes the realmName further to the Resource constructor (via urlParams)
1.4) Passes the realmName further to the Agent constructor (via urlParams)
1.5) Sets the baseParams instance property, which will be used for URL parameters in all further requests
1.6) Further requests pass along the baseParams to the requestWithParams method
1.7) The urlParams are templated
1.8) And passed along to Axios

// Excerpt: src/client.ts
constructor(args?: ClientArgs) {
  // ...
  this.realmName = args && args.realmName || defaultRealm;  // 1.1
  // ...
  this.users = new Users(this);  // 1.2
  // more resources...
  // ...
}
// Excerpt: src/resources/groups.ts
export class Groups extends Resource<{realm?: string}> {
// ...
  constructor(client: KeycloakAdminClient) {
    super(client, {
      path: '/admin/realms/{realm}/groups',
      urlParams: {
        realm: client.realmName  // 1.3
      }
    });
  }
// Excerpt: src/resources/resource.ts
constructor(client: KeycloakAdminClient, settings: {
  path?: string, urlParams?: ParamType
} = {}) {
  this.agent = new Agent({
    client,
    ...settings  // 1.4
  });
}
// Excerpt: src/resources/agent.ts
constructor({
  client, path = '/', urlParams = {}
}: {
  client: KeycloakAdminClient,
  path?: string,
  urlParams?: Record<string, any>
}) {
  this.baseParams = urlParams;  // 1.5
  // ...
}
// ...
public request({
  method,
  path = '',
  urlParams = [],
  querystring = [],
  catchNotFound = false,
  keyTransform,
  payloadKey
}: RequestArgs) {
  return async (payload: any = {}) => {
    const selected = [...Object.keys(this.baseParams), ...urlParams];
    const mergedParams = {...this.baseParams, ...pick(payload, selected)};  // 1.6
    // ...
    return this.requestWithParams({
      // ...
      urlParams: mergedParams,  // 1.6
      // ...
    });
  };
}
// ...
private async requestWithParams(
  {
    method,
    path,
    payload,
    urlParams,
    queryParams,
    catchNotFound,
    payloadKey
  }:
  {
    method: string,
    path: string,
    payload: any,
    urlParams: any,
    queryParams?: Record<string, any> | null,
    catchNotFound: boolean,
    payloadKey?: string
  }) {
  const newPath = join(this.basePath, path);

  // parse
  const temp = template.parse(newPath);
  const parsedPath = temp.expand(urlParams);  // 1.7
  const url = `${this.baseUrl}${parsedPath}`;  // 1.7

  // prepare request configs
  const requestConfig: AxiosRequestConfig = {
    ...this.requestConfigs,
    method,
    url,  // 1.8
    headers: {
      Authorization: `bearer ${this.client.getAccessToken()}`
    }
  };
  // ...
  const res = await axios(requestConfig);
  // ...
}

2) Authentication via call of auth method

The following user code...

await keycloakClient.auth(userSettings);

...does the following things:

2.1) Passes realmNameA to getToken
2.2) Uses this to build the URL
2.3) The URL is passed along to Axios

// Excerpt: src/client.ts
public async auth(credential: Credential) {
  const {accessToken} = await getToken({
    baseUrl: this.baseUrl,
    realmName: this.realmName,  // 2.1
    credential,
    requestConfigs: this.requestConfigs
  });
  // ...
}
// Excerpt: src/utils/auth.ts
export const getToken = async (settings: Settings): Promise<TokenResponse> => {
  // ...
  const realmName = settings.realmName || defaultRealm;
  const url = `${baseUrl}/realms/${realmName}/protocol/openid-connect/token`;  // 2.2
  // ...
  const {data} = await axios.post(url, payload, configs);  // 2.3
  // ...
};

3) Call of resource methods

The following user code...

await keycloakClient.groups.create({name: 'editor'}));

...does the following things:

3.1) Call the agent's request method, using the existing instance properties

// Excerpt: src/resources/groups.ts
public create = this.makeRequest<GroupRepresentation, void>({
  method: 'POST'
});
// Excerpt: src/resources/resource.ts
public makeRequest =
< PayloadType = any,
  ResponseType = any>(args: RequestArgs): (payload?: PayloadType & ParamType) => Promise<ResponseType> => {
return this.agent.request(args);  // 3.1
}

Support for typecheck attributes in Roles

Is your feature request related to a problem? Please describe.
Non support of this leads to unsupported attributes types being able to be stored.
Describe the solution you'd like
This solution is to specify the attributes type along with its supported subtypes in the Role Representation description.

Maintenance / project status

Question to maintainers of this project. Is this project being actively maintained? It looks like there is quite some time since the last release, as well as commits. If this project is not being maintained at the moment, we should look at finding other maintainers or sunsetting the project.

Resource endpoints fail with 404 due to incorrectly constructed URLs

Thanks for this library which looks great! :)

I am having an issue running a simple quickstart to authenticate with keycloak and list clients:

#!/usr/bin/env node

import KcAdminClient from 'keycloak-admin';

async function main() {
    const kcAdminClient = new KcAdminClient({
        baseUrl: 'http://localhost:8081/keycloak/auth',
        realmName: 'realm'
    });

    await kcAdminClient.auth({
        username: 'username',
        password: 'password',
        grantType: 'password',
        clientId: 'admin-cli'
    });

    await kcAdminClient.clients.find()
        .catch(err => console.log(err));

}

main();

But on the clients.find() line I get an error

Error: Request failed with status code 404

Looking into the error object the request URL was

http://localhost:8081/keycloak/auth%5Cadmin%5Crealms%5Crealm%5Cclients

i.e. it seems the URL has been constructed and/or encoded incorrectly.

I am running the script via

ts-node index.ts

Have you seen this before? Is there a known fix and/or workaround?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.