@slickteam/nestjs-keycloak-admin 2.2.2 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +10 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/keycloak-admin.service.d.ts +27 -0
- package/dist/keycloak-admin.service.js +132 -0
- package/dist/keycloak-admin.service.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { UserRepresentation } from '@s3pweb/keycloak-admin-client-cjs';
|
|
2
|
+
import { KeycloakActionsEmailEnum, KeycloakAdminService } from './keycloak-admin.service';
|
|
3
|
+
declare function checkIfExistRealmRoleOfUser(user: {
|
|
4
|
+
realm_access: {
|
|
5
|
+
roles: string[];
|
|
6
|
+
} | undefined;
|
|
7
|
+
}, roleName: string): boolean;
|
|
8
|
+
declare class KeycloakAdminModule {
|
|
9
|
+
}
|
|
10
|
+
export { KeycloakAdminModule, KeycloakAdminService, KeycloakActionsEmailEnum, UserRepresentation, checkIfExistRealmRoleOfUser, };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.KeycloakActionsEmailEnum = exports.KeycloakAdminService = exports.KeycloakAdminModule = void 0;
|
|
10
|
+
exports.checkIfExistRealmRoleOfUser = checkIfExistRealmRoleOfUser;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const config_1 = require("@nestjs/config");
|
|
13
|
+
const keycloak_admin_service_1 = require("./keycloak-admin.service");
|
|
14
|
+
Object.defineProperty(exports, "KeycloakActionsEmailEnum", { enumerable: true, get: function () { return keycloak_admin_service_1.KeycloakActionsEmailEnum; } });
|
|
15
|
+
Object.defineProperty(exports, "KeycloakAdminService", { enumerable: true, get: function () { return keycloak_admin_service_1.KeycloakAdminService; } });
|
|
16
|
+
function checkIfExistRealmRoleOfUser(user, roleName) {
|
|
17
|
+
return user.realm_access?.roles.includes(roleName) ?? false;
|
|
18
|
+
}
|
|
19
|
+
let KeycloakAdminModule = class KeycloakAdminModule {
|
|
20
|
+
};
|
|
21
|
+
exports.KeycloakAdminModule = KeycloakAdminModule;
|
|
22
|
+
exports.KeycloakAdminModule = KeycloakAdminModule = __decorate([
|
|
23
|
+
(0, common_1.Module)({
|
|
24
|
+
imports: [config_1.ConfigModule.forRoot()],
|
|
25
|
+
providers: [keycloak_admin_service_1.KeycloakAdminService],
|
|
26
|
+
exports: [keycloak_admin_service_1.KeycloakAdminService],
|
|
27
|
+
})
|
|
28
|
+
], KeycloakAdminModule);
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;AAwBE,kEAA2B;AAxB7B,2CAAwC;AACxC,2CAA8C;AAG9C,qEAA0F;AAiBxF,yGAjBO,iDAAwB,OAiBP;AAFxB,qGAfiC,6CAAoB,OAejC;AAbtB,SAAS,2BAA2B,CAAC,IAAuD,EAAE,QAAgB;IAC5G,OAAO,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC;AAC9D,CAAC;AAOD,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;CAAG,CAAA;AAG1B,kDAAmB;8BAHf,mBAAmB;IALxB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,qBAAY,CAAC,OAAO,EAAE,CAAC;QACjC,SAAS,EAAE,CAAC,6CAAoB,CAAC;QACjC,OAAO,EAAE,CAAC,6CAAoB,CAAC;KAChC,CAAC;GACI,mBAAmB,CAAG"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ConfigService } from '@nestjs/config';
|
|
2
|
+
import { KeycloakAdminClient, UserRepresentation } from '@s3pweb/keycloak-admin-client-cjs';
|
|
3
|
+
export declare enum KeycloakActionsEmailEnum {
|
|
4
|
+
VERIFY_EMAIL = "VERIFY_EMAIL",
|
|
5
|
+
UPDATE_PROFILE = "UPDATE_PROFILE",
|
|
6
|
+
CONFIGURE_TOTP = "CONFIGURE_TOTP",
|
|
7
|
+
UPDATE_PASSWORD = "UPDATE_PASSWORD",
|
|
8
|
+
TERMS_AND_CONDITIONS = "TERMS_AND_CONDITIONS"
|
|
9
|
+
}
|
|
10
|
+
export declare class KeycloakAdminService {
|
|
11
|
+
private configService;
|
|
12
|
+
readonly KEYCLOAK_ADMIN_CLIENT_ID: string;
|
|
13
|
+
private readonly KEYCLOAK_ADMIN_CLIENT_SECRET;
|
|
14
|
+
private readonly KEYCLOAK_REALM;
|
|
15
|
+
readonly _client: KeycloakAdminClient;
|
|
16
|
+
constructor(configService: ConfigService);
|
|
17
|
+
private auth;
|
|
18
|
+
getAccessToken(): Promise<string>;
|
|
19
|
+
findAllUsers(): Promise<UserRepresentation[]>;
|
|
20
|
+
findUserByEmail(email: string): Promise<UserRepresentation[]>;
|
|
21
|
+
findUserByUsername(username: string): Promise<UserRepresentation[]>;
|
|
22
|
+
findUserById(id: string): Promise<UserRepresentation | undefined>;
|
|
23
|
+
createUser(email: string, firstName?: string | undefined, lastName?: string | undefined, username?: string | undefined, attributes?: Record<string, unknown>): Promise<UserRepresentation>;
|
|
24
|
+
updateAttributesOfUser(id: string, user: UserRepresentation, attributes: Record<string, unknown>): Promise<void | never>;
|
|
25
|
+
updateUserPassword(userId: string, newPassword: string): Promise<void | never>;
|
|
26
|
+
executeActionsEmail(sub: string, clientId: string | undefined, lifespan: number | undefined, redirectUri: string | undefined, actions: KeycloakActionsEmailEnum[] | undefined): Promise<void | never>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.KeycloakAdminService = exports.KeycloakActionsEmailEnum = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const config_1 = require("@nestjs/config");
|
|
15
|
+
const keycloak_admin_client_cjs_1 = require("@s3pweb/keycloak-admin-client-cjs");
|
|
16
|
+
const jwt_decode_1 = require("jwt-decode");
|
|
17
|
+
const logger = new common_1.Logger('KeycloakAdminService');
|
|
18
|
+
var KeycloakActionsEmailEnum;
|
|
19
|
+
(function (KeycloakActionsEmailEnum) {
|
|
20
|
+
KeycloakActionsEmailEnum["VERIFY_EMAIL"] = "VERIFY_EMAIL";
|
|
21
|
+
KeycloakActionsEmailEnum["UPDATE_PROFILE"] = "UPDATE_PROFILE";
|
|
22
|
+
KeycloakActionsEmailEnum["CONFIGURE_TOTP"] = "CONFIGURE_TOTP";
|
|
23
|
+
KeycloakActionsEmailEnum["UPDATE_PASSWORD"] = "UPDATE_PASSWORD";
|
|
24
|
+
KeycloakActionsEmailEnum["TERMS_AND_CONDITIONS"] = "TERMS_AND_CONDITIONS";
|
|
25
|
+
})(KeycloakActionsEmailEnum || (exports.KeycloakActionsEmailEnum = KeycloakActionsEmailEnum = {}));
|
|
26
|
+
let KeycloakAdminService = class KeycloakAdminService {
|
|
27
|
+
configService;
|
|
28
|
+
KEYCLOAK_ADMIN_CLIENT_ID;
|
|
29
|
+
KEYCLOAK_ADMIN_CLIENT_SECRET;
|
|
30
|
+
KEYCLOAK_REALM;
|
|
31
|
+
_client;
|
|
32
|
+
constructor(configService) {
|
|
33
|
+
this.configService = configService;
|
|
34
|
+
const keycloakUrl = this.configService.getOrThrow('KEYCLOAK_URL');
|
|
35
|
+
this.KEYCLOAK_ADMIN_CLIENT_ID = this.configService.getOrThrow('KEYCLOAK_ADMIN_CLIENT_ID');
|
|
36
|
+
this.KEYCLOAK_ADMIN_CLIENT_SECRET = this.configService.getOrThrow('KEYCLOAK_ADMIN_CLIENT_SECRET');
|
|
37
|
+
this.KEYCLOAK_REALM = this.configService.getOrThrow('KEYCLOAK_ADMIN_REALM');
|
|
38
|
+
this._client = new keycloak_admin_client_cjs_1.KeycloakAdminClient({
|
|
39
|
+
baseUrl: keycloakUrl,
|
|
40
|
+
realmName: this.KEYCLOAK_REALM,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async auth() {
|
|
44
|
+
await this._client.auth({
|
|
45
|
+
grantType: 'client_credentials',
|
|
46
|
+
clientId: this.KEYCLOAK_ADMIN_CLIENT_ID,
|
|
47
|
+
clientSecret: this.KEYCLOAK_ADMIN_CLIENT_SECRET,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async getAccessToken() {
|
|
51
|
+
let accessToken;
|
|
52
|
+
try {
|
|
53
|
+
accessToken = await this._client.getAccessToken();
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
}
|
|
57
|
+
if (!accessToken) {
|
|
58
|
+
logger.debug('Get an access token');
|
|
59
|
+
await this.auth();
|
|
60
|
+
}
|
|
61
|
+
let newAccessToken = accessToken ?? this._client.accessToken;
|
|
62
|
+
if (newAccessToken === undefined) {
|
|
63
|
+
throw new Error(`Can't have access_token on keycloak by client_secret method`);
|
|
64
|
+
}
|
|
65
|
+
const decodedTokenExpTime = (0, jwt_decode_1.jwtDecode)(newAccessToken)?.exp ?? 0;
|
|
66
|
+
const nowTmSecond = Math.ceil(Date.now() / 1000) + 2;
|
|
67
|
+
if (decodedTokenExpTime < nowTmSecond) {
|
|
68
|
+
logger.debug('Renew a new access token');
|
|
69
|
+
await this.auth();
|
|
70
|
+
newAccessToken = this._client.accessToken;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
logger.verbose(`Remain time for this access token : ${decodedTokenExpTime - nowTmSecond} seconds`);
|
|
74
|
+
}
|
|
75
|
+
return newAccessToken;
|
|
76
|
+
}
|
|
77
|
+
async findAllUsers() {
|
|
78
|
+
await this.getAccessToken();
|
|
79
|
+
logger.verbose('findAllUsers()');
|
|
80
|
+
return this._client.users.find();
|
|
81
|
+
}
|
|
82
|
+
async findUserByEmail(email) {
|
|
83
|
+
await this.getAccessToken();
|
|
84
|
+
logger.verbose(`findUserByEmail(email=${email})`);
|
|
85
|
+
return this._client.users.find({ email });
|
|
86
|
+
}
|
|
87
|
+
async findUserByUsername(username) {
|
|
88
|
+
await this.getAccessToken();
|
|
89
|
+
logger.verbose(`findUserByUsername(username=${username})`);
|
|
90
|
+
return this._client.users.find({ username });
|
|
91
|
+
}
|
|
92
|
+
async findUserById(id) {
|
|
93
|
+
await this.getAccessToken();
|
|
94
|
+
logger.verbose(`findUserById(id=${id})`);
|
|
95
|
+
return this._client.users.findOne({ id: id });
|
|
96
|
+
}
|
|
97
|
+
async createUser(email, firstName = undefined, lastName = undefined, username = undefined, attributes = {}) {
|
|
98
|
+
await this.getAccessToken();
|
|
99
|
+
logger.verbose(`createUser(email=${email}, firstName=${firstName}, lastName=${lastName}, username=${username})`);
|
|
100
|
+
return this._client.users.create({ username, email, firstName, lastName, attributes, enabled: true, emailVerified: true });
|
|
101
|
+
}
|
|
102
|
+
async updateAttributesOfUser(id, user, attributes) {
|
|
103
|
+
await this.getAccessToken();
|
|
104
|
+
await this._client.users.update({ id }, {
|
|
105
|
+
...user,
|
|
106
|
+
attributes,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async updateUserPassword(userId, newPassword) {
|
|
110
|
+
await this.getAccessToken();
|
|
111
|
+
await this._client.users.resetPassword({
|
|
112
|
+
id: userId,
|
|
113
|
+
credential: { type: 'password', value: newPassword, temporary: false },
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
async executeActionsEmail(sub, clientId, lifespan, redirectUri, actions) {
|
|
117
|
+
await this.getAccessToken();
|
|
118
|
+
await this._client.users.executeActionsEmail({
|
|
119
|
+
id: sub,
|
|
120
|
+
clientId,
|
|
121
|
+
lifespan,
|
|
122
|
+
redirectUri,
|
|
123
|
+
actions,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
exports.KeycloakAdminService = KeycloakAdminService;
|
|
128
|
+
exports.KeycloakAdminService = KeycloakAdminService = __decorate([
|
|
129
|
+
(0, common_1.Injectable)(),
|
|
130
|
+
__metadata("design:paramtypes", [config_1.ConfigService])
|
|
131
|
+
], KeycloakAdminService);
|
|
132
|
+
//# sourceMappingURL=keycloak-admin.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keycloak-admin.service.js","sourceRoot":"","sources":["../src/keycloak-admin.service.ts"],"names":[],"mappings":"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"}
|