@confighub/react-auth 0.1.2 → 0.2.0
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/README.md +38 -8
- package/dist/index.cjs +203 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +104 -19
- package/dist/index.d.ts +104 -19
- package/dist/index.js +202 -59
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -2,19 +2,97 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { ConfigHubClient } from '@confighub/api';
|
|
4
4
|
|
|
5
|
+
interface Discovery {
|
|
6
|
+
AuthIssuer?: string;
|
|
7
|
+
TokenExchangeEndpoint?: string;
|
|
8
|
+
TokenExchangeAudience?: string;
|
|
9
|
+
}
|
|
10
|
+
interface MintedSession {
|
|
11
|
+
accessToken: string;
|
|
12
|
+
organizationId: string;
|
|
13
|
+
/** Claims of the validated IdP token (owning-org, audience, organization shape). */
|
|
14
|
+
idpClaims: Record<string, unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* The IdP's ID token, kept only so logout can pass it as `id_token_hint` to the
|
|
17
|
+
* end-session endpoint. Absent for sessions that did not come from an OIDC login.
|
|
18
|
+
*/
|
|
19
|
+
idToken?: string;
|
|
20
|
+
}
|
|
21
|
+
interface LoginOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Where to land after login, as a same-origin path (`/space/x?tab=units`). Carried
|
|
24
|
+
* through the authorize round trip in the PKCE state, never in the redirect URI:
|
|
25
|
+
* OAuth clients register exact redirect URIs, so the URI itself must not vary with
|
|
26
|
+
* the page the user started from. Defaults to the current path and query.
|
|
27
|
+
*/
|
|
28
|
+
returnTo?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Keycloak organization alias to sign in to, sent as the `organization:<alias>`
|
|
31
|
+
* scope. Without it Keycloak prompts a multi-org user to pick one (or uses the
|
|
32
|
+
* organization already selected in the SSO session).
|
|
33
|
+
*/
|
|
34
|
+
organization?: string;
|
|
35
|
+
/**
|
|
36
|
+
* `'none'` asks the IdP to re-authenticate without any UI, failing with
|
|
37
|
+
* `login_required` if the SSO session is gone -- the way to refresh an expired
|
|
38
|
+
* ConfigHub token when the user is still signed in at the IdP. `'login'` forces the
|
|
39
|
+
* login form even with a live SSO session.
|
|
40
|
+
*/
|
|
41
|
+
prompt?: 'none' | 'login';
|
|
42
|
+
}
|
|
43
|
+
interface FlowOptions {
|
|
44
|
+
/**
|
|
45
|
+
* Same-origin path the IdP redirects back to, and therefore the redirect URI to
|
|
46
|
+
* register for the client: `{origin}{callbackPath}`. Defaults to `/`.
|
|
47
|
+
*/
|
|
48
|
+
callbackPath?: string;
|
|
49
|
+
}
|
|
50
|
+
/** The fixed callback URI: the page origin plus the configured callback path. */
|
|
51
|
+
declare const callbackUri: (opts?: FlowOptions) => string;
|
|
52
|
+
/** Decode a JWT's claims without verifying it. Returns {} for anything malformed. */
|
|
53
|
+
declare function decodeJwtClaims(token: string): Record<string, unknown>;
|
|
54
|
+
/** Whether a JWT's `exp` is in the past (with a small skew allowance). */
|
|
55
|
+
declare function isExpired(token: string, skewSeconds?: number): boolean;
|
|
56
|
+
|
|
5
57
|
type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated' | 'error';
|
|
6
58
|
interface ConfigHubUser {
|
|
7
59
|
organizationId: string;
|
|
8
60
|
idpClaims: Record<string, unknown>;
|
|
9
61
|
}
|
|
62
|
+
interface LogoutOptions {
|
|
63
|
+
/**
|
|
64
|
+
* Also end the IdP session (RP-initiated logout), so the next login asks for
|
|
65
|
+
* credentials instead of riding the SSO cookie. Redirects the page; the landing
|
|
66
|
+
* URI must be registered for the client. Default: false, which only forgets the
|
|
67
|
+
* token in this tab.
|
|
68
|
+
*/
|
|
69
|
+
endSession?: boolean;
|
|
70
|
+
/** Where to land after IdP logout. Defaults to the callback URI. */
|
|
71
|
+
postLogoutRedirectUri?: string;
|
|
72
|
+
}
|
|
10
73
|
interface ConfigHubAuthContextValue {
|
|
11
74
|
status: AuthStatus;
|
|
12
75
|
user: ConfigHubUser | null;
|
|
13
76
|
error: Error | null;
|
|
14
77
|
/** Begin login: redirects the page to the IdP. */
|
|
15
|
-
login: () => Promise<void>;
|
|
16
|
-
/**
|
|
17
|
-
logout: () => void
|
|
78
|
+
login: (options?: LoginOptions) => Promise<void>;
|
|
79
|
+
/** Forget the session in this tab and, optionally, end the IdP session too. */
|
|
80
|
+
logout: (options?: LogoutOptions) => Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Re-mint the ConfigHub token for another organization the user belongs to. The
|
|
83
|
+
* IdP session is untouched. Rejects with the server's error if the user is not a
|
|
84
|
+
* member; the current session stays as it was.
|
|
85
|
+
*/
|
|
86
|
+
switchOrganization: (organizationId: string) => Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* The ConfigHub token stopped working (a 401). Try to get a new one without any
|
|
89
|
+
* UI: a `prompt=none` round trip through the IdP, for the organization the session
|
|
90
|
+
* already had. Status goes to `loading` meanwhile, not `unauthenticated`, so an
|
|
91
|
+
* app that auto-logs-in on `unauthenticated` does not race this with an
|
|
92
|
+
* interactive login. If the IdP session is gone too, the page comes back
|
|
93
|
+
* `unauthenticated`. Redirects the page.
|
|
94
|
+
*/
|
|
95
|
+
reauthenticate: () => Promise<void>;
|
|
18
96
|
/** Current bearer token, or undefined when unauthenticated. */
|
|
19
97
|
getToken: () => string | undefined;
|
|
20
98
|
/** A typed API client pre-wired with the current token. Stable across renders. */
|
|
@@ -26,14 +104,33 @@ interface ConfigHubAuthProviderProps {
|
|
|
26
104
|
baseUrl: string;
|
|
27
105
|
/** This app's registered OAuth `client_id` (from `cub oauthclient create`). */
|
|
28
106
|
clientId: string;
|
|
107
|
+
/**
|
|
108
|
+
* Same-origin path the IdP redirects back to; `{origin}{callbackPath}` is the
|
|
109
|
+
* redirect URI to register. Defaults to `/`. Fixed on purpose: the page a user
|
|
110
|
+
* starts login from travels in the PKCE state, not in the redirect URI.
|
|
111
|
+
*/
|
|
112
|
+
callbackPath?: string;
|
|
113
|
+
/**
|
|
114
|
+
* `'session'` keeps the minted token in `sessionStorage` so a reload or an in-tab
|
|
115
|
+
* navigation does not round-trip through the IdP. Tab-scoped and gone when the tab
|
|
116
|
+
* closes. Default `'none'`: memory only, a reload starts unauthenticated.
|
|
117
|
+
*/
|
|
118
|
+
persist?: 'none' | 'session';
|
|
119
|
+
/**
|
|
120
|
+
* What a 401 from the API means. `'login'` (default): the token is stale, try a
|
|
121
|
+
* silent re-authentication (`prompt=none`) and fall back to unauthenticated if the
|
|
122
|
+
* IdP session is gone too. `'logout'`: just drop the session.
|
|
123
|
+
*/
|
|
124
|
+
onUnauthorized?: 'login' | 'logout';
|
|
29
125
|
children: ReactNode;
|
|
30
126
|
}
|
|
31
127
|
/**
|
|
32
128
|
* Runs the browser-direct auth flow and manages the token lifecycle. On mount it
|
|
33
|
-
* completes a redirect if the page is the IdP callback
|
|
34
|
-
* unauthenticated until `login()`
|
|
129
|
+
* completes a redirect if the page is the IdP callback, restores a persisted
|
|
130
|
+
* session if there is one, and otherwise starts unauthenticated until `login()`
|
|
131
|
+
* is called.
|
|
35
132
|
*/
|
|
36
|
-
declare function ConfigHubAuthProvider({ baseUrl, clientId, children, }: ConfigHubAuthProviderProps): JSX.Element;
|
|
133
|
+
declare function ConfigHubAuthProvider({ baseUrl, clientId, callbackPath, persist, onUnauthorized, children, }: ConfigHubAuthProviderProps): JSX.Element;
|
|
37
134
|
|
|
38
135
|
/**
|
|
39
136
|
* Access the ConfigHub auth state and actions. Must be called under a
|
|
@@ -63,16 +160,4 @@ declare function useConfigHub(): ConfigHubClient;
|
|
|
63
160
|
*/
|
|
64
161
|
declare function getAccessToken(): string | undefined;
|
|
65
162
|
|
|
66
|
-
|
|
67
|
-
AuthIssuer?: string;
|
|
68
|
-
TokenExchangeEndpoint?: string;
|
|
69
|
-
TokenExchangeAudience?: string;
|
|
70
|
-
}
|
|
71
|
-
interface MintedSession {
|
|
72
|
-
accessToken: string;
|
|
73
|
-
organizationId: string;
|
|
74
|
-
/** Claims of the validated IdP token (owning-org, audience, organization shape). */
|
|
75
|
-
idpClaims: Record<string, unknown>;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export { type AuthStatus, ConfigHubAuthContext, type ConfigHubAuthContextValue, ConfigHubAuthProvider, type ConfigHubAuthProviderProps, type ConfigHubUser, type Discovery, type MintedSession, getAccessToken, useAuth, useConfigHub };
|
|
163
|
+
export { type AuthStatus, ConfigHubAuthContext, type ConfigHubAuthContextValue, ConfigHubAuthProvider, type ConfigHubAuthProviderProps, type ConfigHubUser, type Discovery, type FlowOptions, type LoginOptions, type LogoutOptions, type MintedSession, callbackUri, decodeJwtClaims, getAccessToken, isExpired, useAuth, useConfigHub };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,19 +2,97 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { ConfigHubClient } from '@confighub/api';
|
|
4
4
|
|
|
5
|
+
interface Discovery {
|
|
6
|
+
AuthIssuer?: string;
|
|
7
|
+
TokenExchangeEndpoint?: string;
|
|
8
|
+
TokenExchangeAudience?: string;
|
|
9
|
+
}
|
|
10
|
+
interface MintedSession {
|
|
11
|
+
accessToken: string;
|
|
12
|
+
organizationId: string;
|
|
13
|
+
/** Claims of the validated IdP token (owning-org, audience, organization shape). */
|
|
14
|
+
idpClaims: Record<string, unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* The IdP's ID token, kept only so logout can pass it as `id_token_hint` to the
|
|
17
|
+
* end-session endpoint. Absent for sessions that did not come from an OIDC login.
|
|
18
|
+
*/
|
|
19
|
+
idToken?: string;
|
|
20
|
+
}
|
|
21
|
+
interface LoginOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Where to land after login, as a same-origin path (`/space/x?tab=units`). Carried
|
|
24
|
+
* through the authorize round trip in the PKCE state, never in the redirect URI:
|
|
25
|
+
* OAuth clients register exact redirect URIs, so the URI itself must not vary with
|
|
26
|
+
* the page the user started from. Defaults to the current path and query.
|
|
27
|
+
*/
|
|
28
|
+
returnTo?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Keycloak organization alias to sign in to, sent as the `organization:<alias>`
|
|
31
|
+
* scope. Without it Keycloak prompts a multi-org user to pick one (or uses the
|
|
32
|
+
* organization already selected in the SSO session).
|
|
33
|
+
*/
|
|
34
|
+
organization?: string;
|
|
35
|
+
/**
|
|
36
|
+
* `'none'` asks the IdP to re-authenticate without any UI, failing with
|
|
37
|
+
* `login_required` if the SSO session is gone -- the way to refresh an expired
|
|
38
|
+
* ConfigHub token when the user is still signed in at the IdP. `'login'` forces the
|
|
39
|
+
* login form even with a live SSO session.
|
|
40
|
+
*/
|
|
41
|
+
prompt?: 'none' | 'login';
|
|
42
|
+
}
|
|
43
|
+
interface FlowOptions {
|
|
44
|
+
/**
|
|
45
|
+
* Same-origin path the IdP redirects back to, and therefore the redirect URI to
|
|
46
|
+
* register for the client: `{origin}{callbackPath}`. Defaults to `/`.
|
|
47
|
+
*/
|
|
48
|
+
callbackPath?: string;
|
|
49
|
+
}
|
|
50
|
+
/** The fixed callback URI: the page origin plus the configured callback path. */
|
|
51
|
+
declare const callbackUri: (opts?: FlowOptions) => string;
|
|
52
|
+
/** Decode a JWT's claims without verifying it. Returns {} for anything malformed. */
|
|
53
|
+
declare function decodeJwtClaims(token: string): Record<string, unknown>;
|
|
54
|
+
/** Whether a JWT's `exp` is in the past (with a small skew allowance). */
|
|
55
|
+
declare function isExpired(token: string, skewSeconds?: number): boolean;
|
|
56
|
+
|
|
5
57
|
type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated' | 'error';
|
|
6
58
|
interface ConfigHubUser {
|
|
7
59
|
organizationId: string;
|
|
8
60
|
idpClaims: Record<string, unknown>;
|
|
9
61
|
}
|
|
62
|
+
interface LogoutOptions {
|
|
63
|
+
/**
|
|
64
|
+
* Also end the IdP session (RP-initiated logout), so the next login asks for
|
|
65
|
+
* credentials instead of riding the SSO cookie. Redirects the page; the landing
|
|
66
|
+
* URI must be registered for the client. Default: false, which only forgets the
|
|
67
|
+
* token in this tab.
|
|
68
|
+
*/
|
|
69
|
+
endSession?: boolean;
|
|
70
|
+
/** Where to land after IdP logout. Defaults to the callback URI. */
|
|
71
|
+
postLogoutRedirectUri?: string;
|
|
72
|
+
}
|
|
10
73
|
interface ConfigHubAuthContextValue {
|
|
11
74
|
status: AuthStatus;
|
|
12
75
|
user: ConfigHubUser | null;
|
|
13
76
|
error: Error | null;
|
|
14
77
|
/** Begin login: redirects the page to the IdP. */
|
|
15
|
-
login: () => Promise<void>;
|
|
16
|
-
/**
|
|
17
|
-
logout: () => void
|
|
78
|
+
login: (options?: LoginOptions) => Promise<void>;
|
|
79
|
+
/** Forget the session in this tab and, optionally, end the IdP session too. */
|
|
80
|
+
logout: (options?: LogoutOptions) => Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Re-mint the ConfigHub token for another organization the user belongs to. The
|
|
83
|
+
* IdP session is untouched. Rejects with the server's error if the user is not a
|
|
84
|
+
* member; the current session stays as it was.
|
|
85
|
+
*/
|
|
86
|
+
switchOrganization: (organizationId: string) => Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* The ConfigHub token stopped working (a 401). Try to get a new one without any
|
|
89
|
+
* UI: a `prompt=none` round trip through the IdP, for the organization the session
|
|
90
|
+
* already had. Status goes to `loading` meanwhile, not `unauthenticated`, so an
|
|
91
|
+
* app that auto-logs-in on `unauthenticated` does not race this with an
|
|
92
|
+
* interactive login. If the IdP session is gone too, the page comes back
|
|
93
|
+
* `unauthenticated`. Redirects the page.
|
|
94
|
+
*/
|
|
95
|
+
reauthenticate: () => Promise<void>;
|
|
18
96
|
/** Current bearer token, or undefined when unauthenticated. */
|
|
19
97
|
getToken: () => string | undefined;
|
|
20
98
|
/** A typed API client pre-wired with the current token. Stable across renders. */
|
|
@@ -26,14 +104,33 @@ interface ConfigHubAuthProviderProps {
|
|
|
26
104
|
baseUrl: string;
|
|
27
105
|
/** This app's registered OAuth `client_id` (from `cub oauthclient create`). */
|
|
28
106
|
clientId: string;
|
|
107
|
+
/**
|
|
108
|
+
* Same-origin path the IdP redirects back to; `{origin}{callbackPath}` is the
|
|
109
|
+
* redirect URI to register. Defaults to `/`. Fixed on purpose: the page a user
|
|
110
|
+
* starts login from travels in the PKCE state, not in the redirect URI.
|
|
111
|
+
*/
|
|
112
|
+
callbackPath?: string;
|
|
113
|
+
/**
|
|
114
|
+
* `'session'` keeps the minted token in `sessionStorage` so a reload or an in-tab
|
|
115
|
+
* navigation does not round-trip through the IdP. Tab-scoped and gone when the tab
|
|
116
|
+
* closes. Default `'none'`: memory only, a reload starts unauthenticated.
|
|
117
|
+
*/
|
|
118
|
+
persist?: 'none' | 'session';
|
|
119
|
+
/**
|
|
120
|
+
* What a 401 from the API means. `'login'` (default): the token is stale, try a
|
|
121
|
+
* silent re-authentication (`prompt=none`) and fall back to unauthenticated if the
|
|
122
|
+
* IdP session is gone too. `'logout'`: just drop the session.
|
|
123
|
+
*/
|
|
124
|
+
onUnauthorized?: 'login' | 'logout';
|
|
29
125
|
children: ReactNode;
|
|
30
126
|
}
|
|
31
127
|
/**
|
|
32
128
|
* Runs the browser-direct auth flow and manages the token lifecycle. On mount it
|
|
33
|
-
* completes a redirect if the page is the IdP callback
|
|
34
|
-
* unauthenticated until `login()`
|
|
129
|
+
* completes a redirect if the page is the IdP callback, restores a persisted
|
|
130
|
+
* session if there is one, and otherwise starts unauthenticated until `login()`
|
|
131
|
+
* is called.
|
|
35
132
|
*/
|
|
36
|
-
declare function ConfigHubAuthProvider({ baseUrl, clientId, children, }: ConfigHubAuthProviderProps): JSX.Element;
|
|
133
|
+
declare function ConfigHubAuthProvider({ baseUrl, clientId, callbackPath, persist, onUnauthorized, children, }: ConfigHubAuthProviderProps): JSX.Element;
|
|
37
134
|
|
|
38
135
|
/**
|
|
39
136
|
* Access the ConfigHub auth state and actions. Must be called under a
|
|
@@ -63,16 +160,4 @@ declare function useConfigHub(): ConfigHubClient;
|
|
|
63
160
|
*/
|
|
64
161
|
declare function getAccessToken(): string | undefined;
|
|
65
162
|
|
|
66
|
-
|
|
67
|
-
AuthIssuer?: string;
|
|
68
|
-
TokenExchangeEndpoint?: string;
|
|
69
|
-
TokenExchangeAudience?: string;
|
|
70
|
-
}
|
|
71
|
-
interface MintedSession {
|
|
72
|
-
accessToken: string;
|
|
73
|
-
organizationId: string;
|
|
74
|
-
/** Claims of the validated IdP token (owning-org, audience, organization shape). */
|
|
75
|
-
idpClaims: Record<string, unknown>;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export { type AuthStatus, ConfigHubAuthContext, type ConfigHubAuthContextValue, ConfigHubAuthProvider, type ConfigHubAuthProviderProps, type ConfigHubUser, type Discovery, type MintedSession, getAccessToken, useAuth, useConfigHub };
|
|
163
|
+
export { type AuthStatus, ConfigHubAuthContext, type ConfigHubAuthContextValue, ConfigHubAuthProvider, type ConfigHubAuthProviderProps, type ConfigHubUser, type Discovery, type FlowOptions, type LoginOptions, type LogoutOptions, type MintedSession, callbackUri, decodeJwtClaims, getAccessToken, isExpired, useAuth, useConfigHub };
|