@checkstack/auth-frontend 0.4.1 → 0.5.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/CHANGELOG.md +46 -0
- package/package.json +1 -1
- package/src/components/AuthStrategyCard.tsx +28 -1
- package/src/components/LoginPage.tsx +10 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# @checkstack/auth-frontend
|
|
2
2
|
|
|
3
|
+
## 0.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [83557c7]
|
|
8
|
+
- Updated dependencies [83557c7]
|
|
9
|
+
- Updated dependencies [d316128]
|
|
10
|
+
- Updated dependencies [6dbfab8]
|
|
11
|
+
- @checkstack/ui@0.3.0
|
|
12
|
+
- @checkstack/common@0.4.0
|
|
13
|
+
- @checkstack/auth-common@0.5.1
|
|
14
|
+
- @checkstack/frontend-api@0.3.1
|
|
15
|
+
|
|
16
|
+
## 0.5.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- d94121b: Add group-to-role mapping for SAML and LDAP authentication
|
|
21
|
+
|
|
22
|
+
**Features:**
|
|
23
|
+
|
|
24
|
+
- SAML and LDAP users can now be automatically assigned Checkstack roles based on their directory group memberships
|
|
25
|
+
- Configure group mappings in the authentication strategy settings with dynamic role dropdowns
|
|
26
|
+
- Managed role sync: roles configured in mappings are fully synchronized (added when user gains group, removed when user leaves group)
|
|
27
|
+
- Unmanaged roles (manually assigned, not in any mapping) are preserved during sync
|
|
28
|
+
- Optional default role for all users from a directory
|
|
29
|
+
|
|
30
|
+
**Bug Fix:**
|
|
31
|
+
|
|
32
|
+
- Fixed `x-options-resolver` not working for fields inside arrays with `.default([])` in DynamicForm schemas
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- 10aa9fb: Add SAML 2.0 SSO support
|
|
37
|
+
|
|
38
|
+
- Added new `auth-saml-backend` plugin for SAML 2.0 Single Sign-On authentication
|
|
39
|
+
- Supports SP-initiated SSO with configurable IdP metadata (URL or manual configuration)
|
|
40
|
+
- Uses samlify library for SAML protocol handling
|
|
41
|
+
- Configurable attribute mapping for user email/name extraction
|
|
42
|
+
- Automatic user creation and updates via S2S Identity API
|
|
43
|
+
- Added SAML redirect handling in LoginPage for seamless SSO flow
|
|
44
|
+
|
|
45
|
+
- Updated dependencies [d94121b]
|
|
46
|
+
- @checkstack/auth-common@0.5.0
|
|
47
|
+
- @checkstack/ui@0.2.4
|
|
48
|
+
|
|
3
49
|
## 0.4.1
|
|
4
50
|
|
|
5
51
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { useCallback, useMemo } from "react";
|
|
1
2
|
import {
|
|
2
3
|
StrategyConfigCard,
|
|
3
4
|
type ConfigSection,
|
|
4
5
|
type LucideIconName,
|
|
6
|
+
type OptionsResolver,
|
|
5
7
|
} from "@checkstack/ui";
|
|
8
|
+
import { usePluginClient } from "@checkstack/frontend-api";
|
|
9
|
+
import { AuthApi } from "@checkstack/auth-common";
|
|
6
10
|
import type { AuthStrategy } from "../api";
|
|
7
11
|
|
|
8
12
|
export interface AuthStrategyCardProps {
|
|
@@ -30,6 +34,28 @@ export function AuthStrategyCard({
|
|
|
30
34
|
onExpandedChange,
|
|
31
35
|
config,
|
|
32
36
|
}: AuthStrategyCardProps) {
|
|
37
|
+
const authClient = usePluginClient(AuthApi);
|
|
38
|
+
|
|
39
|
+
// Fetch all roles once for the dropdown options
|
|
40
|
+
const { data: roles = [] } = authClient.getRoles.useQuery({});
|
|
41
|
+
|
|
42
|
+
// Create resolver for dynamic role selection in group mapping
|
|
43
|
+
// Uses the already-fetched roles data
|
|
44
|
+
const roleOptionsResolver: OptionsResolver = useCallback(async () => {
|
|
45
|
+
return roles.map((role) => ({
|
|
46
|
+
value: role.id,
|
|
47
|
+
label: role.name,
|
|
48
|
+
}));
|
|
49
|
+
}, [roles]);
|
|
50
|
+
|
|
51
|
+
// Memoize the resolvers object to prevent unnecessary re-renders
|
|
52
|
+
const optionsResolvers = useMemo(
|
|
53
|
+
() => ({
|
|
54
|
+
roleOptions: roleOptionsResolver,
|
|
55
|
+
}),
|
|
56
|
+
[roleOptionsResolver],
|
|
57
|
+
);
|
|
58
|
+
|
|
33
59
|
// Check if config schema has properties
|
|
34
60
|
const hasConfigSchema =
|
|
35
61
|
strategy.configSchema &&
|
|
@@ -40,7 +66,7 @@ export function AuthStrategyCard({
|
|
|
40
66
|
// Config is missing if schema has properties but no saved config
|
|
41
67
|
const configMissing = hasConfigSchema && strategy.config === undefined;
|
|
42
68
|
|
|
43
|
-
// Build config sections
|
|
69
|
+
// Build config sections with role options resolver
|
|
44
70
|
const configSections: ConfigSection[] = [];
|
|
45
71
|
if (hasConfigSchema) {
|
|
46
72
|
configSections.push({
|
|
@@ -48,6 +74,7 @@ export function AuthStrategyCard({
|
|
|
48
74
|
title: "Configuration",
|
|
49
75
|
schema: strategy.configSchema,
|
|
50
76
|
value: config ?? strategy.config,
|
|
77
|
+
optionsResolvers,
|
|
51
78
|
onSave: async (newConfig) => {
|
|
52
79
|
await onSaveConfig(strategy.id, newConfig);
|
|
53
80
|
},
|
|
@@ -54,7 +54,7 @@ export const LoginPage = () => {
|
|
|
54
54
|
|
|
55
55
|
// Query: Registration status
|
|
56
56
|
const { data: registrationData } = authClient.getRegistrationStatus.useQuery(
|
|
57
|
-
{}
|
|
57
|
+
{},
|
|
58
58
|
);
|
|
59
59
|
const registrationAllowed = registrationData?.allowRegistration ?? true;
|
|
60
60
|
|
|
@@ -76,6 +76,11 @@ export const LoginPage = () => {
|
|
|
76
76
|
|
|
77
77
|
const handleSocialLogin = async (provider: string) => {
|
|
78
78
|
try {
|
|
79
|
+
// SAML uses a custom endpoint, not the better-auth OAuth flow
|
|
80
|
+
if (provider === "saml") {
|
|
81
|
+
globalThis.location.href = "/api/auth-saml/saml/login";
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
79
84
|
await authApi.signInWithSocial(provider);
|
|
80
85
|
// Navigation will happen automatically after OAuth redirect
|
|
81
86
|
} catch (error) {
|
|
@@ -142,8 +147,8 @@ export const LoginPage = () => {
|
|
|
142
147
|
{hasCredential && hasSocial
|
|
143
148
|
? "Choose your preferred sign-in method"
|
|
144
149
|
: hasCredential
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
? "Enter your credentials to access the dashboard"
|
|
151
|
+
: "Continue with your account"}
|
|
147
152
|
</CardDescription>
|
|
148
153
|
</CardHeader>
|
|
149
154
|
<CardContent>
|
|
@@ -280,7 +285,7 @@ export const LoginNavbarAction = () => {
|
|
|
280
285
|
authClient.listAccounts().then((result) => {
|
|
281
286
|
if (result.data) {
|
|
282
287
|
const hasCredential = result.data.some(
|
|
283
|
-
(account) => account.providerId === "credential"
|
|
288
|
+
(account) => account.providerId === "credential",
|
|
284
289
|
);
|
|
285
290
|
setHasCredentialAccount(hasCredential);
|
|
286
291
|
}
|
|
@@ -295,7 +300,7 @@ export const LoginNavbarAction = () => {
|
|
|
295
300
|
if (session?.user) {
|
|
296
301
|
// Check if we have any bottom items to decide if we need a separator
|
|
297
302
|
const bottomExtensions = pluginRegistry.getExtensions(
|
|
298
|
-
UserMenuItemsBottomSlot.id
|
|
303
|
+
UserMenuItemsBottomSlot.id,
|
|
299
304
|
);
|
|
300
305
|
const hasBottomItems = bottomExtensions.length > 0;
|
|
301
306
|
const menuContext: UserMenuItemsContext = {
|