@strapi/plugin-users-permissions 5.49.0 → 5.50.1
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/.eslintrc.cjs +1 -0
- package/admin/src/pages/AdvancedSettings/index.jsx +1 -1
- package/admin/src/pages/Roles/pages/ListPage/index.jsx +1 -1
- package/admin/src/translations/ja.json +46 -7
- package/dist/admin/pages/AdvancedSettings/index.js +1 -1
- package/dist/admin/pages/AdvancedSettings/index.js.map +1 -1
- package/dist/admin/pages/AdvancedSettings/index.mjs +1 -1
- package/dist/admin/pages/AdvancedSettings/index.mjs.map +1 -1
- package/dist/admin/pages/Roles/pages/ListPage/index.js +1 -1
- package/dist/admin/pages/Roles/pages/ListPage/index.js.map +1 -1
- package/dist/admin/pages/Roles/pages/ListPage/index.mjs +1 -1
- package/dist/admin/pages/Roles/pages/ListPage/index.mjs.map +1 -1
- package/dist/admin/translations/ja.json.js +46 -7
- package/dist/admin/translations/ja.json.js.map +1 -1
- package/dist/admin/translations/ja.json.mjs +46 -7
- package/dist/admin/translations/ja.json.mjs.map +1 -1
- package/dist/server/controllers/auth.js +133 -114
- package/dist/server/controllers/auth.js.map +1 -1
- package/dist/server/controllers/auth.mjs +132 -113
- package/dist/server/controllers/auth.mjs.map +1 -1
- package/dist/server/controllers/validation/auth.js +6 -6
- package/dist/server/controllers/validation/auth.js.map +1 -1
- package/dist/server/controllers/validation/auth.mjs +6 -6
- package/dist/server/controllers/validation/auth.mjs.map +1 -1
- package/dist/server/controllers/validation/user.js +16 -9
- package/dist/server/controllers/validation/user.js.map +1 -1
- package/dist/server/controllers/validation/user.mjs +16 -9
- package/dist/server/controllers/validation/user.mjs.map +1 -1
- package/dist/server/routes/content-api/auth.js +16 -0
- package/dist/server/routes/content-api/auth.js.map +1 -1
- package/dist/server/routes/content-api/auth.mjs +16 -0
- package/dist/server/routes/content-api/auth.mjs.map +1 -1
- package/dist/server/routes/content-api/validation.js +29 -2
- package/dist/server/routes/content-api/validation.js.map +1 -1
- package/dist/server/routes/content-api/validation.mjs +29 -2
- package/dist/server/routes/content-api/validation.mjs.map +1 -1
- package/dist/server/services/jwt.js +8 -6
- package/dist/server/services/jwt.js.map +1 -1
- package/dist/server/services/jwt.mjs +8 -6
- package/dist/server/services/jwt.mjs.map +1 -1
- package/dist/server/services/users-permissions.js +8 -0
- package/dist/server/services/users-permissions.js.map +1 -1
- package/dist/server/services/users-permissions.mjs +8 -0
- package/dist/server/services/users-permissions.mjs.map +1 -1
- package/dist/server/strategies/users-permissions.js +8 -1
- package/dist/server/strategies/users-permissions.js.map +1 -1
- package/dist/server/strategies/users-permissions.mjs +8 -1
- package/dist/server/strategies/users-permissions.mjs.map +1 -1
- package/dist/server/utils/refresh-cookie-options.js +27 -0
- package/dist/server/utils/refresh-cookie-options.js.map +1 -0
- package/dist/server/utils/refresh-cookie-options.mjs +25 -0
- package/dist/server/utils/refresh-cookie-options.mjs.map +1 -0
- package/lint-staged.config.mjs +1 -0
- package/package.json +5 -5
- package/rollup.config.mjs +3 -3
- package/server/controllers/auth.js +162 -141
- package/server/controllers/validation/auth.js +6 -6
- package/server/controllers/validation/user.js +22 -9
- package/server/routes/content-api/auth.js +12 -0
- package/server/routes/content-api/validation.js +32 -2
- package/server/services/jwt.js +4 -3
- package/server/services/users-permissions.js +2 -0
- package/server/strategies/users-permissions.js +6 -1
- package/server/utils/refresh-cookie-options.js +20 -0
|
@@ -1,46 +1,85 @@
|
|
|
1
1
|
var ja = {
|
|
2
|
-
"BoundRoute.title": "
|
|
2
|
+
"BoundRoute.title": "バインドされたルート",
|
|
3
|
+
"components.Input.error.validation.email": "有効なメールアドレスではありません",
|
|
4
|
+
"components.Input.error.validation.json": "JSON形式と一致しません",
|
|
5
|
+
"components.Input.error.validation.max": "値が大きすぎます。",
|
|
6
|
+
"components.Input.error.validation.maxLength": "値が長すぎます。",
|
|
7
|
+
"components.Input.error.validation.min": "値が小さすぎます。",
|
|
8
|
+
"components.Input.error.validation.minLength": "値が短すぎます。",
|
|
9
|
+
"components.Input.error.validation.minSupMax": "最大値を超えることはできません。",
|
|
10
|
+
"components.Input.error.validation.regex": "値が正規表現と一致しません。",
|
|
11
|
+
"components.Input.error.validation.required": "この値は必須です。",
|
|
12
|
+
"components.Input.error.validation.unique": "この値はすでに使用されています。",
|
|
3
13
|
"EditForm.inputSelect.description.role": "新しい認証されたユーザーが選択された役割にアタッチされます。",
|
|
4
14
|
"EditForm.inputSelect.label.role": "認証されたユーザーのデフォルトの役割",
|
|
5
15
|
"EditForm.inputToggle.description.email": "ユーザーが異なる認証プロバイダで同じ電子メールアドレスを使用して複数のアカウントを作成できないようにします。",
|
|
6
16
|
"EditForm.inputToggle.description.email-confirmation": "有効(ON)にすると、新しい登録ユーザーに確認メールが送信されます。",
|
|
7
17
|
"EditForm.inputToggle.description.email-confirmation-redirection": "あなたのEメールを確認したら、リダイレクト先を選択してください。",
|
|
18
|
+
"EditForm.inputToggle.description.email-reset-password": "アプリケーションのパスワードリセットページのURL",
|
|
8
19
|
"EditForm.inputToggle.description.sign-up": "あなたの電子メールを確認した後、リダイレクト先を選択しました。",
|
|
9
20
|
"EditForm.inputToggle.label.email": "メールアドレスごとに1つのアカウント",
|
|
10
21
|
"EditForm.inputToggle.label.email-confirmation": "Eメールの確認を有効にする",
|
|
11
22
|
"EditForm.inputToggle.label.email-confirmation-redirection": "リダイレクトURL",
|
|
23
|
+
"EditForm.inputToggle.label.email-reset-password": "パスワードリセットページ",
|
|
12
24
|
"EditForm.inputToggle.label.sign-up": "申し込みを有効にする",
|
|
25
|
+
"EditForm.inputToggle.placeholder.email-confirmation-redirection": "例: https://yourfrontend.com/email-confirmation-redirection",
|
|
26
|
+
"EditForm.inputToggle.placeholder.email-reset-password": "例: https://yourfrontend.com/reset-password",
|
|
27
|
+
"EditPage.form.roles": "ロールの詳細",
|
|
28
|
+
"Email.template.data.loaded": "メールテンプレートを読み込みました",
|
|
29
|
+
"Email.template.email_confirmation": "メールアドレスの確認",
|
|
30
|
+
"Email.template.form.edit.label": "テンプレートを編集",
|
|
31
|
+
"Email.template.reset_password": "パスワードリセット",
|
|
32
|
+
"Email.template.table.action.label": "操作",
|
|
33
|
+
"Email.template.table.icon.label": "アイコン",
|
|
34
|
+
"Email.template.table.name.label": "名前",
|
|
35
|
+
"Form.advancedSettings.data.loaded": "高度な設定データを読み込みました",
|
|
13
36
|
"HeaderNav.link.advancedSettings": "高度な設定",
|
|
14
37
|
"HeaderNav.link.emailTemplates": "メールテンプレート",
|
|
15
38
|
"HeaderNav.link.providers": "プロバイダー",
|
|
39
|
+
"notification.success.submit": "設定が更新されました",
|
|
40
|
+
"page.title": "設定 - ロール",
|
|
41
|
+
"plugin.description.long": "JWTに基づいた完全な認証プロセスでAPIを保護します。このプラグインには、ユーザーのグループ間で権限を管理できるACL戦略もあります。",
|
|
42
|
+
"plugin.description.short": "JWTに基づく完全な認証プロセスでAPIを保護する",
|
|
43
|
+
"plugin.name": "ロールと権限",
|
|
16
44
|
"Plugin.permissions.plugins.description": "{name} 個のプラグインに対して許可されたすべてのアクションを定義する",
|
|
17
45
|
"Plugins.header.description": "ルートにバインドされたアクションのみが以下にリストされています",
|
|
18
46
|
"Plugins.header.title": "権限",
|
|
19
47
|
"Policies.header.hint": "アプリケーションのアクションまたはプラグインのアクションを選択し、コグアイコンをクリックしてバインドされたルートを表示します",
|
|
20
48
|
"Policies.header.title": "高度な設定",
|
|
21
49
|
"PopUpForm.Email.email_templates.inputDescription": "変数の使用方法がわからない場合は、{link}",
|
|
50
|
+
"PopUpForm.Email.link.documentation": "ドキュメントをご覧ください。",
|
|
22
51
|
"PopUpForm.Email.options.from.email.label": "送信者Eメール",
|
|
23
52
|
"PopUpForm.Email.options.from.email.placeholder": "kai@doe.com",
|
|
24
53
|
"PopUpForm.Email.options.from.name.label": "送信者名",
|
|
25
54
|
"PopUpForm.Email.options.from.name.placeholder": "Kai Doe",
|
|
26
55
|
"PopUpForm.Email.options.message.label": "メッセージ",
|
|
27
56
|
"PopUpForm.Email.options.object.label": "件名",
|
|
57
|
+
"PopUpForm.Email.options.object.placeholder": "%APP_NAME% のメールアドレスを確認してください",
|
|
28
58
|
"PopUpForm.Email.options.response_email.label": "応答メール",
|
|
29
59
|
"PopUpForm.Email.options.response_email.placeholder": "kai@doe.com",
|
|
60
|
+
"PopUpForm.header.edit.email-templates": "メールテンプレートの編集",
|
|
61
|
+
"PopUpForm.header.edit.providers": "プロバイダーの編集",
|
|
30
62
|
"PopUpForm.Providers.enabled.description": "無効にすると、ユーザーはこのプロバイダを使用できなくなります。",
|
|
31
63
|
"PopUpForm.Providers.enabled.label": "有効にする",
|
|
32
64
|
"PopUpForm.Providers.key.label": "クライアントID",
|
|
33
65
|
"PopUpForm.Providers.key.placeholder": "TEXT",
|
|
34
66
|
"PopUpForm.Providers.redirectURL.front-end.label": "フロントエンドアプリへのリダイレクトURL",
|
|
67
|
+
"PopUpForm.Providers.redirectURL.label": "{provider}アプリケーションの設定に追加するリダイレクトURL",
|
|
35
68
|
"PopUpForm.Providers.secret.label": "クライアントの秘密",
|
|
36
69
|
"PopUpForm.Providers.secret.placeholder": "TEXT",
|
|
37
|
-
"PopUpForm.Providers.subdomain.label": "
|
|
70
|
+
"PopUpForm.Providers.subdomain.label": "ホストURI(サブドメイン)",
|
|
38
71
|
"PopUpForm.Providers.subdomain.placeholder": "my.subdomain.com",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
72
|
+
"popUpWarning.button.cancel": "キャンセル",
|
|
73
|
+
"popUpWarning.button.confirm": "確認",
|
|
74
|
+
"popUpWarning.title": "確認してください",
|
|
75
|
+
"popUpWarning.warning.cancel": "変更をキャンセルしてもよろしいですか?",
|
|
76
|
+
"Providers.data.loaded": "プロバイダーを読み込みました",
|
|
77
|
+
"Providers.status": "ステータス",
|
|
78
|
+
"Roles.empty": "ロールがまだありません。",
|
|
79
|
+
"Roles.empty.search": "検索に一致するロールがありません。",
|
|
80
|
+
"Settings.roles.deleted": "ロールを削除しました",
|
|
81
|
+
"Settings.roles.edited": "ロールを編集しました",
|
|
82
|
+
"Settings.section-label": "ユーザーと権限プラグイン"
|
|
44
83
|
};
|
|
45
84
|
|
|
46
85
|
export { ja as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ja.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ja.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -5,8 +5,9 @@ var require$$0$1 = require('lodash');
|
|
|
5
5
|
var require$$0 = require('lodash/fp');
|
|
6
6
|
var require$$1 = require('@strapi/utils');
|
|
7
7
|
var index = require('../utils/index.js');
|
|
8
|
+
var refreshCookieOptions = require('../utils/refresh-cookie-options.js');
|
|
8
9
|
var auth$1 = require('./validation/auth.js');
|
|
9
|
-
var require$$
|
|
10
|
+
var require$$7 = require('grant');
|
|
10
11
|
|
|
11
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
|
|
@@ -14,7 +15,7 @@ var require$$0__default$2 = /*#__PURE__*/_interopDefault(require$$0$2);
|
|
|
14
15
|
var require$$0__default$1 = /*#__PURE__*/_interopDefault(require$$0$1);
|
|
15
16
|
var require$$0__default = /*#__PURE__*/_interopDefault(require$$0);
|
|
16
17
|
var require$$1__default = /*#__PURE__*/_interopDefault(require$$1);
|
|
17
|
-
var require$$
|
|
18
|
+
var require$$7__default = /*#__PURE__*/_interopDefault(require$$7);
|
|
18
19
|
|
|
19
20
|
var auth;
|
|
20
21
|
var hasRequiredAuth;
|
|
@@ -30,8 +31,10 @@ function requireAuth() {
|
|
|
30
31
|
const { concat, compact, isArray } = require$$0__default.default;
|
|
31
32
|
const utils = require$$1__default.default;
|
|
32
33
|
const { getService } = index.__require();
|
|
34
|
+
const { buildRefreshCookieOptions } = refreshCookieOptions.__require();
|
|
33
35
|
const { validateCallbackBody, validateRegisterBody, validateSendEmailConfirmationBody, validateForgotPasswordBody, validateResetPasswordBody, validateEmailConfirmationBody, validateChangePasswordBody } = auth$1.__require();
|
|
34
36
|
const { ApplicationError, ValidationError, ForbiddenError } = utils.errors;
|
|
37
|
+
const { buildSessionMetadata, sanitizeSessionEntry, sortSessionsForDisplay } = utils;
|
|
35
38
|
const sanitizeUser = (user, ctx)=>{
|
|
36
39
|
const { auth } = ctx.state;
|
|
37
40
|
const userSchema = strapi.getModel('plugin::users-permissions.user');
|
|
@@ -43,6 +46,82 @@ function requireAuth() {
|
|
|
43
46
|
const { deviceId } = requestBody || {};
|
|
44
47
|
return typeof deviceId === 'string' && deviceId.length > 0 ? deviceId : undefined;
|
|
45
48
|
};
|
|
49
|
+
const buildSessionMetadataFromContext = (ctx)=>buildSessionMetadata({
|
|
50
|
+
userAgent: ctx.request.headers['user-agent']
|
|
51
|
+
});
|
|
52
|
+
const sendRefreshAuthResponse = async (strapi1, ctx, user, { metadata } = {})=>{
|
|
53
|
+
const deviceId = extractDeviceId(ctx.request.body);
|
|
54
|
+
const tokenOptions = {
|
|
55
|
+
type: 'refresh',
|
|
56
|
+
...metadata ? {
|
|
57
|
+
metadata
|
|
58
|
+
} : {}
|
|
59
|
+
};
|
|
60
|
+
const refresh = await strapi1.sessionManager('users-permissions').generateRefreshToken(String(user.id), deviceId, tokenOptions);
|
|
61
|
+
const access = await strapi1.sessionManager('users-permissions').generateAccessToken(refresh.token);
|
|
62
|
+
if ('error' in access) {
|
|
63
|
+
throw new ApplicationError('Invalid credentials');
|
|
64
|
+
}
|
|
65
|
+
const upSessions = strapi1.config.get('plugin::users-permissions.sessions');
|
|
66
|
+
const requestHttpOnly = ctx.request.header['x-strapi-refresh-cookie'] === 'httpOnly';
|
|
67
|
+
if (upSessions?.httpOnly || requestHttpOnly) {
|
|
68
|
+
const cookieName = upSessions.cookie?.name || 'strapi_up_refresh';
|
|
69
|
+
const isProduction = process.env.NODE_ENV === 'production';
|
|
70
|
+
ctx.cookies.set(cookieName, refresh.token, buildRefreshCookieOptions(upSessions, isProduction));
|
|
71
|
+
return ctx.send({
|
|
72
|
+
jwt: access.token,
|
|
73
|
+
user: await sanitizeUser(user, ctx)
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return ctx.send({
|
|
77
|
+
jwt: access.token,
|
|
78
|
+
refreshToken: refresh.token,
|
|
79
|
+
user: await sanitizeUser(user, ctx)
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
const reissueTokensAfterPasswordChange = async (strapi1, ctx, user)=>{
|
|
83
|
+
const deviceId = extractDeviceId(ctx.request.body);
|
|
84
|
+
await strapi1.sessionManager('users-permissions').invalidateRefreshToken(String(user.id));
|
|
85
|
+
const newDeviceId = deviceId || crypto.randomUUID();
|
|
86
|
+
const refresh = await strapi1.sessionManager('users-permissions').generateRefreshToken(String(user.id), newDeviceId, {
|
|
87
|
+
type: 'refresh'
|
|
88
|
+
});
|
|
89
|
+
const access = await strapi1.sessionManager('users-permissions').generateAccessToken(refresh.token);
|
|
90
|
+
if ('error' in access) {
|
|
91
|
+
throw new ApplicationError('Invalid credentials');
|
|
92
|
+
}
|
|
93
|
+
return ctx.send({
|
|
94
|
+
jwt: access.token,
|
|
95
|
+
refreshToken: refresh.token,
|
|
96
|
+
user: await sanitizeUser(user, ctx)
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
const revokeLogoutSessions = async (strapi1, ctx, userId, { scope, deviceId, body })=>{
|
|
100
|
+
const sessionManager = strapi1.sessionManager('users-permissions');
|
|
101
|
+
const upSessions = strapi1.config.get('plugin::users-permissions.sessions');
|
|
102
|
+
if (scope === 'all') {
|
|
103
|
+
await sessionManager.invalidateRefreshToken(userId);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (deviceId) {
|
|
107
|
+
await sessionManager.invalidateRefreshToken(userId, deviceId);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
let currentSessionId = ctx.state.session?.id;
|
|
111
|
+
const cookieName = upSessions?.cookie?.name || 'strapi_up_refresh';
|
|
112
|
+
const refreshToken = ctx.cookies.get(cookieName) || (typeof body.refreshToken === 'string' ? body.refreshToken : undefined);
|
|
113
|
+
if (refreshToken) {
|
|
114
|
+
const validation = await sessionManager.validateRefreshToken(refreshToken);
|
|
115
|
+
if (validation.isValid) {
|
|
116
|
+
currentSessionId = validation.sessionId;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (currentSessionId) {
|
|
120
|
+
await sessionManager.revokeSessionById(userId, currentSessionId);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
await sessionManager.invalidateRefreshToken(userId);
|
|
124
|
+
};
|
|
46
125
|
auth = ({ strapi: strapi1 })=>({
|
|
47
126
|
async callback (ctx) {
|
|
48
127
|
const provider = ctx.params.provider || 'local';
|
|
@@ -100,38 +179,8 @@ function requireAuth() {
|
|
|
100
179
|
}
|
|
101
180
|
const mode = strapi1.config.get('plugin::users-permissions.jwtManagement', 'legacy-support');
|
|
102
181
|
if (mode === 'refresh') {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
type: 'refresh'
|
|
106
|
-
});
|
|
107
|
-
const access = await strapi1.sessionManager('users-permissions').generateAccessToken(refresh.token);
|
|
108
|
-
if ('error' in access) {
|
|
109
|
-
throw new ApplicationError('Invalid credentials');
|
|
110
|
-
}
|
|
111
|
-
const upSessions = strapi1.config.get('plugin::users-permissions.sessions');
|
|
112
|
-
const requestHttpOnly = ctx.request.header['x-strapi-refresh-cookie'] === 'httpOnly';
|
|
113
|
-
if (upSessions?.httpOnly || requestHttpOnly) {
|
|
114
|
-
const cookieName = upSessions.cookie?.name || 'strapi_up_refresh';
|
|
115
|
-
const isProduction = process.env.NODE_ENV === 'production';
|
|
116
|
-
const isSecure = typeof upSessions.cookie?.secure === 'boolean' ? upSessions.cookie?.secure : isProduction;
|
|
117
|
-
const cookieOptions = {
|
|
118
|
-
httpOnly: true,
|
|
119
|
-
secure: isSecure,
|
|
120
|
-
sameSite: upSessions.cookie?.sameSite ?? 'lax',
|
|
121
|
-
path: upSessions.cookie?.path ?? '/',
|
|
122
|
-
domain: upSessions.cookie?.domain,
|
|
123
|
-
overwrite: true
|
|
124
|
-
};
|
|
125
|
-
ctx.cookies.set(cookieName, refresh.token, cookieOptions);
|
|
126
|
-
return ctx.send({
|
|
127
|
-
jwt: access.token,
|
|
128
|
-
user: await sanitizeUser(user, ctx)
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
return ctx.send({
|
|
132
|
-
jwt: access.token,
|
|
133
|
-
refreshToken: refresh.token,
|
|
134
|
-
user: await sanitizeUser(user, ctx)
|
|
182
|
+
return sendRefreshAuthResponse(strapi1, ctx, user, {
|
|
183
|
+
metadata: buildSessionMetadataFromContext(ctx)
|
|
135
184
|
});
|
|
136
185
|
}
|
|
137
186
|
return ctx.send({
|
|
@@ -149,38 +198,8 @@ function requireAuth() {
|
|
|
149
198
|
}
|
|
150
199
|
const mode = strapi1.config.get('plugin::users-permissions.jwtManagement', 'legacy-support');
|
|
151
200
|
if (mode === 'refresh') {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
type: 'refresh'
|
|
155
|
-
});
|
|
156
|
-
const access = await strapi1.sessionManager('users-permissions').generateAccessToken(refresh.token);
|
|
157
|
-
if ('error' in access) {
|
|
158
|
-
throw new ApplicationError('Invalid credentials');
|
|
159
|
-
}
|
|
160
|
-
const upSessions = strapi1.config.get('plugin::users-permissions.sessions');
|
|
161
|
-
const requestHttpOnly = ctx.request.header['x-strapi-refresh-cookie'] === 'httpOnly';
|
|
162
|
-
if (upSessions?.httpOnly || requestHttpOnly) {
|
|
163
|
-
const cookieName = upSessions.cookie?.name || 'strapi_up_refresh';
|
|
164
|
-
const isProduction = process.env.NODE_ENV === 'production';
|
|
165
|
-
const isSecure = typeof upSessions.cookie?.secure === 'boolean' ? upSessions.cookie?.secure : isProduction;
|
|
166
|
-
const cookieOptions = {
|
|
167
|
-
httpOnly: true,
|
|
168
|
-
secure: isSecure,
|
|
169
|
-
sameSite: upSessions.cookie?.sameSite ?? 'lax',
|
|
170
|
-
path: upSessions.cookie?.path ?? '/',
|
|
171
|
-
domain: upSessions.cookie?.domain,
|
|
172
|
-
overwrite: true
|
|
173
|
-
};
|
|
174
|
-
ctx.cookies.set(cookieName, refresh.token, cookieOptions);
|
|
175
|
-
return ctx.send({
|
|
176
|
-
jwt: access.token,
|
|
177
|
-
user: await sanitizeUser(user, ctx)
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
return ctx.send({
|
|
181
|
-
jwt: access.token,
|
|
182
|
-
refreshToken: refresh.token,
|
|
183
|
-
user: await sanitizeUser(user, ctx)
|
|
201
|
+
return sendRefreshAuthResponse(strapi1, ctx, user, {
|
|
202
|
+
metadata: buildSessionMetadataFromContext(ctx)
|
|
184
203
|
});
|
|
185
204
|
}
|
|
186
205
|
return ctx.send({
|
|
@@ -216,22 +235,7 @@ function requireAuth() {
|
|
|
216
235
|
});
|
|
217
236
|
const mode = strapi1.config.get('plugin::users-permissions.jwtManagement', 'legacy-support');
|
|
218
237
|
if (mode === 'refresh') {
|
|
219
|
-
|
|
220
|
-
// Invalidate all sessions when password changes for security
|
|
221
|
-
await strapi1.sessionManager('users-permissions').invalidateRefreshToken(String(user.id));
|
|
222
|
-
const newDeviceId = deviceId || crypto.randomUUID();
|
|
223
|
-
const refresh = await strapi1.sessionManager('users-permissions').generateRefreshToken(String(user.id), newDeviceId, {
|
|
224
|
-
type: 'refresh'
|
|
225
|
-
});
|
|
226
|
-
const access = await strapi1.sessionManager('users-permissions').generateAccessToken(refresh.token);
|
|
227
|
-
if ('error' in access) {
|
|
228
|
-
throw new ApplicationError('Invalid credentials');
|
|
229
|
-
}
|
|
230
|
-
return ctx.send({
|
|
231
|
-
jwt: access.token,
|
|
232
|
-
refreshToken: refresh.token,
|
|
233
|
-
user: await sanitizeUser(user, ctx)
|
|
234
|
-
});
|
|
238
|
+
return reissueTokensAfterPasswordChange(strapi1, ctx, user);
|
|
235
239
|
}
|
|
236
240
|
return ctx.send({
|
|
237
241
|
jwt: getService('jwt').issue({
|
|
@@ -260,22 +264,7 @@ function requireAuth() {
|
|
|
260
264
|
});
|
|
261
265
|
const mode = strapi1.config.get('plugin::users-permissions.jwtManagement', 'legacy-support');
|
|
262
266
|
if (mode === 'refresh') {
|
|
263
|
-
|
|
264
|
-
// Invalidate all sessions when password is reset for security
|
|
265
|
-
await strapi1.sessionManager('users-permissions').invalidateRefreshToken(String(user.id));
|
|
266
|
-
const newDeviceId = deviceId || crypto.randomUUID();
|
|
267
|
-
const refresh = await strapi1.sessionManager('users-permissions').generateRefreshToken(String(user.id), newDeviceId, {
|
|
268
|
-
type: 'refresh'
|
|
269
|
-
});
|
|
270
|
-
const access = await strapi1.sessionManager('users-permissions').generateAccessToken(refresh.token);
|
|
271
|
-
if ('error' in access) {
|
|
272
|
-
throw new ApplicationError('Invalid credentials');
|
|
273
|
-
}
|
|
274
|
-
return ctx.send({
|
|
275
|
-
jwt: access.token,
|
|
276
|
-
refreshToken: refresh.token,
|
|
277
|
-
user: await sanitizeUser(user, ctx)
|
|
278
|
-
});
|
|
267
|
+
return reissueTokensAfterPasswordChange(strapi1, ctx, user);
|
|
279
268
|
}
|
|
280
269
|
return ctx.send({
|
|
281
270
|
jwt: getService('jwt').issue({
|
|
@@ -310,16 +299,7 @@ function requireAuth() {
|
|
|
310
299
|
const requestHttpOnly = ctx.request.header['x-strapi-refresh-cookie'] === 'httpOnly';
|
|
311
300
|
if (upSessions?.httpOnly || requestHttpOnly) {
|
|
312
301
|
const isProduction = process.env.NODE_ENV === 'production';
|
|
313
|
-
|
|
314
|
-
const cookieOptions = {
|
|
315
|
-
httpOnly: true,
|
|
316
|
-
secure: isSecure,
|
|
317
|
-
sameSite: upSessions.cookie?.sameSite ?? 'lax',
|
|
318
|
-
path: upSessions.cookie?.path ?? '/',
|
|
319
|
-
domain: upSessions.cookie?.domain,
|
|
320
|
-
overwrite: true
|
|
321
|
-
};
|
|
322
|
-
ctx.cookies.set(cookieName, rotation.token, cookieOptions);
|
|
302
|
+
ctx.cookies.set(cookieName, rotation.token, buildRefreshCookieOptions(upSessions, isProduction));
|
|
323
303
|
return ctx.send({
|
|
324
304
|
jwt: result.token
|
|
325
305
|
});
|
|
@@ -334,17 +314,23 @@ function requireAuth() {
|
|
|
334
314
|
if (mode !== 'refresh') {
|
|
335
315
|
return ctx.notFound();
|
|
336
316
|
}
|
|
337
|
-
// Invalidate all sessions for the authenticated user, or by deviceId if provided
|
|
338
317
|
if (!ctx.state.user) {
|
|
339
318
|
return ctx.unauthorized('Missing authentication');
|
|
340
319
|
}
|
|
341
|
-
const
|
|
320
|
+
const userId = String(ctx.state.user.id);
|
|
321
|
+
const upSessions = strapi1.config.get('plugin::users-permissions.sessions');
|
|
322
|
+
const body = ctx.request.body || {};
|
|
323
|
+
const scope = typeof body.scope === 'string' ? body.scope : undefined;
|
|
324
|
+
const deviceId = extractDeviceId(body);
|
|
342
325
|
try {
|
|
343
|
-
await strapi1
|
|
326
|
+
await revokeLogoutSessions(strapi1, ctx, userId, {
|
|
327
|
+
scope,
|
|
328
|
+
deviceId,
|
|
329
|
+
body
|
|
330
|
+
});
|
|
344
331
|
} catch (err) {
|
|
345
332
|
strapi1.log.error('UP logout failed', err);
|
|
346
333
|
}
|
|
347
|
-
const upSessions = strapi1.config.get('plugin::users-permissions.sessions');
|
|
348
334
|
const requestHttpOnly = ctx.request.header['x-strapi-refresh-cookie'] === 'httpOnly';
|
|
349
335
|
if (upSessions?.httpOnly || requestHttpOnly) {
|
|
350
336
|
const cookieName = upSessions.cookie?.name || 'strapi_up_refresh';
|
|
@@ -356,8 +342,40 @@ function requireAuth() {
|
|
|
356
342
|
ok: true
|
|
357
343
|
});
|
|
358
344
|
},
|
|
345
|
+
async getSessions (ctx) {
|
|
346
|
+
const mode = strapi1.config.get('plugin::users-permissions.jwtManagement', 'legacy-support');
|
|
347
|
+
if (mode !== 'refresh') {
|
|
348
|
+
return ctx.notFound();
|
|
349
|
+
}
|
|
350
|
+
if (!ctx.state.user) {
|
|
351
|
+
return ctx.unauthorized('Missing authentication');
|
|
352
|
+
}
|
|
353
|
+
const currentSessionId = ctx.state.session?.id;
|
|
354
|
+
const sessions = await strapi1.sessionManager('users-permissions').listSessions(String(ctx.state.user.id));
|
|
355
|
+
const data = sortSessionsForDisplay(sessions.map((session)=>sanitizeSessionEntry(session, currentSessionId)));
|
|
356
|
+
return ctx.send({
|
|
357
|
+
data
|
|
358
|
+
});
|
|
359
|
+
},
|
|
360
|
+
async revokeSession (ctx) {
|
|
361
|
+
const mode = strapi1.config.get('plugin::users-permissions.jwtManagement', 'legacy-support');
|
|
362
|
+
if (mode !== 'refresh') {
|
|
363
|
+
return ctx.notFound();
|
|
364
|
+
}
|
|
365
|
+
if (!ctx.state.user) {
|
|
366
|
+
return ctx.unauthorized('Missing authentication');
|
|
367
|
+
}
|
|
368
|
+
const { sessionId } = ctx.params;
|
|
369
|
+
const revoked = await strapi1.sessionManager('users-permissions').revokeSessionById(String(ctx.state.user.id), sessionId);
|
|
370
|
+
if (!revoked) {
|
|
371
|
+
return ctx.notFound('Session not found');
|
|
372
|
+
}
|
|
373
|
+
return ctx.send({
|
|
374
|
+
data: {}
|
|
375
|
+
});
|
|
376
|
+
},
|
|
359
377
|
async connect (ctx, next) {
|
|
360
|
-
const grant = require$$
|
|
378
|
+
const grant = require$$7__default.default.koa();
|
|
361
379
|
const providers = await strapi1.store({
|
|
362
380
|
type: 'plugin',
|
|
363
381
|
name: 'users-permissions',
|
|
@@ -553,7 +571,8 @@ function requireAuth() {
|
|
|
553
571
|
if (mode === 'refresh') {
|
|
554
572
|
const deviceId = extractDeviceId(ctx.request.body) || crypto.randomUUID();
|
|
555
573
|
const refresh = await strapi1.sessionManager('users-permissions').generateRefreshToken(String(user.id), deviceId, {
|
|
556
|
-
type: 'refresh'
|
|
574
|
+
type: 'refresh',
|
|
575
|
+
metadata: buildSessionMetadataFromContext(ctx)
|
|
557
576
|
});
|
|
558
577
|
const access = await strapi1.sessionManager('users-permissions').generateAccessToken(refresh.token);
|
|
559
578
|
if ('error' in access) {
|