@drmhse/authos-react 0.1.2 → 0.1.4
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 +263 -147
- package/dist/index.d.mts +263 -15
- package/dist/index.d.ts +263 -15
- package/dist/index.js +277 -43
- package/dist/index.mjs +274 -45
- package/dist/nextjs.d.mts +30 -1
- package/dist/nextjs.d.ts +30 -1
- package/dist/nextjs.js +11 -0
- package/dist/nextjs.mjs +10 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -50,6 +50,7 @@ function AuthOSProvider({ config, children, client: externalClient, initialSessi
|
|
|
50
50
|
const contextValue = react.useMemo(
|
|
51
51
|
() => ({
|
|
52
52
|
client,
|
|
53
|
+
config,
|
|
53
54
|
user,
|
|
54
55
|
isAuthenticated: !!user,
|
|
55
56
|
isLoading,
|
|
@@ -58,7 +59,7 @@ function AuthOSProvider({ config, children, client: externalClient, initialSessi
|
|
|
58
59
|
setOrganization,
|
|
59
60
|
refreshUser
|
|
60
61
|
}),
|
|
61
|
-
[client, user, isLoading, organization, refreshUser]
|
|
62
|
+
[client, config, user, isLoading, organization, refreshUser]
|
|
62
63
|
);
|
|
63
64
|
return /* @__PURE__ */ jsxRuntime.jsx(AuthOSContext.Provider, { value: contextValue, children });
|
|
64
65
|
}
|
|
@@ -85,8 +86,12 @@ function useOrganization() {
|
|
|
85
86
|
const { client, organization, setOrganization, refreshUser } = useAuthOSContext();
|
|
86
87
|
const switchOrganization = react.useCallback(
|
|
87
88
|
async (slug) => {
|
|
88
|
-
const
|
|
89
|
-
|
|
89
|
+
const result = await client.organizations.select(slug);
|
|
90
|
+
await client.setSession({
|
|
91
|
+
access_token: result.access_token,
|
|
92
|
+
refresh_token: result.refresh_token
|
|
93
|
+
});
|
|
94
|
+
setOrganization(result.organization);
|
|
90
95
|
await refreshUser();
|
|
91
96
|
},
|
|
92
97
|
[client, setOrganization, refreshUser]
|
|
@@ -114,15 +119,71 @@ function useAllPermissions(permissions) {
|
|
|
114
119
|
return permissions.every((perm) => user.permissions.includes(perm));
|
|
115
120
|
}, [user?.permissions, permissions]);
|
|
116
121
|
}
|
|
122
|
+
var PROVIDER_NAMES = {
|
|
123
|
+
github: "GitHub",
|
|
124
|
+
google: "Google",
|
|
125
|
+
microsoft: "Microsoft"
|
|
126
|
+
};
|
|
127
|
+
function OAuthButton({
|
|
128
|
+
provider,
|
|
129
|
+
children,
|
|
130
|
+
className,
|
|
131
|
+
onRedirect,
|
|
132
|
+
disabled = false
|
|
133
|
+
}) {
|
|
134
|
+
const { client, config } = useAuthOSContext();
|
|
135
|
+
const handleClick = react.useCallback(() => {
|
|
136
|
+
if (!config.org || !config.service) {
|
|
137
|
+
console.error(
|
|
138
|
+
`[AuthOS] OAuth login requires "org" and "service" in AuthOSProvider config.
|
|
139
|
+
Current config: { org: ${config.org ? `"${config.org}"` : "undefined"}, service: ${config.service ? `"${config.service}"` : "undefined"} }
|
|
140
|
+
|
|
141
|
+
Example:
|
|
142
|
+
<AuthOSProvider config={{
|
|
143
|
+
baseURL: "${config.baseURL}",
|
|
144
|
+
org: "your-org-slug",
|
|
145
|
+
service: "your-service-slug",
|
|
146
|
+
}}>
|
|
147
|
+
|
|
148
|
+
See: https://docs.authos.dev/react/oauth-setup`
|
|
149
|
+
);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const redirectUri = config.redirectUri ?? (typeof window !== "undefined" ? window.location.origin + "/callback" : void 0);
|
|
153
|
+
const url = client.auth.getLoginUrl(provider, {
|
|
154
|
+
org: config.org,
|
|
155
|
+
service: config.service,
|
|
156
|
+
redirect_uri: redirectUri
|
|
157
|
+
});
|
|
158
|
+
onRedirect?.();
|
|
159
|
+
window.location.href = url;
|
|
160
|
+
}, [client, config, provider, onRedirect]);
|
|
161
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
162
|
+
"button",
|
|
163
|
+
{
|
|
164
|
+
type: "button",
|
|
165
|
+
onClick: handleClick,
|
|
166
|
+
className,
|
|
167
|
+
disabled,
|
|
168
|
+
"data-authos-oauth": "",
|
|
169
|
+
"data-provider": provider,
|
|
170
|
+
children: children ?? `Continue with ${PROVIDER_NAMES[provider]}`
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
}
|
|
117
174
|
var MFA_PREAUTH_EXPIRY = 300;
|
|
118
175
|
function SignIn({
|
|
119
176
|
onSuccess,
|
|
120
177
|
onError,
|
|
121
178
|
showForgotPassword = true,
|
|
122
179
|
showSignUp = true,
|
|
123
|
-
className
|
|
180
|
+
className,
|
|
181
|
+
providers = false,
|
|
182
|
+
showDivider = true
|
|
124
183
|
}) {
|
|
125
|
-
const { client, setUser } = useAuthOSContext();
|
|
184
|
+
const { client, config, setUser } = useAuthOSContext();
|
|
185
|
+
const hasOAuthConfig = !!(config.org && config.service);
|
|
186
|
+
const oauthProviders = providers && Array.isArray(providers) ? providers : [];
|
|
126
187
|
const [state, setState] = react.useState("credentials");
|
|
127
188
|
const [email, setEmail] = react.useState("");
|
|
128
189
|
const [password, setPassword] = react.useState("");
|
|
@@ -205,47 +266,61 @@ function SignIn({
|
|
|
205
266
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: handleBackToCredentials, "data-authos-back": "", children: "Back to login" })
|
|
206
267
|
] }) });
|
|
207
268
|
}
|
|
208
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
209
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-
|
|
210
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
211
|
-
|
|
212
|
-
"input",
|
|
213
|
-
{
|
|
214
|
-
id: "authos-email",
|
|
215
|
-
type: "email",
|
|
216
|
-
autoComplete: "email",
|
|
217
|
-
value: email,
|
|
218
|
-
onChange: (e) => setEmail(e.target.value),
|
|
219
|
-
placeholder: "Enter your email",
|
|
220
|
-
required: true,
|
|
221
|
-
disabled: isLoading
|
|
222
|
-
}
|
|
223
|
-
)
|
|
224
|
-
] }),
|
|
225
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-field": "password", children: [
|
|
226
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "authos-password", children: "Password" }),
|
|
227
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
228
|
-
"input",
|
|
269
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-authos-signin": "", "data-state": "credentials", children: [
|
|
270
|
+
oauthProviders.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-oauth-section": "", children: [
|
|
271
|
+
oauthProviders.map((provider) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
272
|
+
OAuthButton,
|
|
229
273
|
{
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
required: true,
|
|
237
|
-
disabled: isLoading
|
|
238
|
-
}
|
|
239
|
-
)
|
|
274
|
+
provider,
|
|
275
|
+
disabled: isLoading || !hasOAuthConfig
|
|
276
|
+
},
|
|
277
|
+
provider
|
|
278
|
+
)),
|
|
279
|
+
!hasOAuthConfig && /* @__PURE__ */ jsxRuntime.jsx("p", { "data-authos-oauth-warning": "", style: { color: "orange", fontSize: "0.875rem" }, children: "OAuth requires org and service in AuthOSProvider config" })
|
|
240
280
|
] }),
|
|
241
|
-
|
|
242
|
-
/* @__PURE__ */ jsxRuntime.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
281
|
+
oauthProviders.length > 0 && showDivider && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-authos-divider": "", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: "or" }) }),
|
|
282
|
+
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleCredentialsSubmit, children: [
|
|
283
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-field": "email", children: [
|
|
284
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "authos-email", children: "Email" }),
|
|
285
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
286
|
+
"input",
|
|
287
|
+
{
|
|
288
|
+
id: "authos-email",
|
|
289
|
+
type: "email",
|
|
290
|
+
autoComplete: "email",
|
|
291
|
+
value: email,
|
|
292
|
+
onChange: (e) => setEmail(e.target.value),
|
|
293
|
+
placeholder: "Enter your email",
|
|
294
|
+
required: true,
|
|
295
|
+
disabled: isLoading
|
|
296
|
+
}
|
|
297
|
+
)
|
|
298
|
+
] }),
|
|
299
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-field": "password", children: [
|
|
300
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "authos-password", children: "Password" }),
|
|
301
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
302
|
+
"input",
|
|
303
|
+
{
|
|
304
|
+
id: "authos-password",
|
|
305
|
+
type: "password",
|
|
306
|
+
autoComplete: "current-password",
|
|
307
|
+
value: password,
|
|
308
|
+
onChange: (e) => setPassword(e.target.value),
|
|
309
|
+
placeholder: "Enter your password",
|
|
310
|
+
required: true,
|
|
311
|
+
disabled: isLoading
|
|
312
|
+
}
|
|
313
|
+
)
|
|
314
|
+
] }),
|
|
315
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-authos-error": true, children: error }),
|
|
316
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", disabled: isLoading, "data-authos-submit": "", children: isLoading ? "Signing in..." : "Sign In" }),
|
|
317
|
+
showForgotPassword && /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/forgot-password", "data-authos-link": "forgot-password", children: "Forgot password?" }),
|
|
318
|
+
showSignUp && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-signup-prompt": true, children: [
|
|
319
|
+
"Don't have an account? ",
|
|
320
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { href: "/signup", "data-authos-link": "signup", children: "Sign up" })
|
|
321
|
+
] })
|
|
247
322
|
] })
|
|
248
|
-
] })
|
|
323
|
+
] });
|
|
249
324
|
}
|
|
250
325
|
function SignUp({ onSuccess, onError, orgSlug, showSignIn = true, className }) {
|
|
251
326
|
const { client } = useAuthOSContext();
|
|
@@ -534,6 +609,160 @@ function Protect({ permission, role, fallback = null, children }) {
|
|
|
534
609
|
};
|
|
535
610
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-authos-protect": true, children: renderContent() });
|
|
536
611
|
}
|
|
612
|
+
function SignedIn({ children }) {
|
|
613
|
+
const { isAuthenticated, isLoading } = useAuthOSContext();
|
|
614
|
+
if (isLoading) {
|
|
615
|
+
return null;
|
|
616
|
+
}
|
|
617
|
+
if (!isAuthenticated) {
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
621
|
+
}
|
|
622
|
+
function SignedOut({ children }) {
|
|
623
|
+
const { isAuthenticated, isLoading } = useAuthOSContext();
|
|
624
|
+
if (isLoading) {
|
|
625
|
+
return null;
|
|
626
|
+
}
|
|
627
|
+
if (isAuthenticated) {
|
|
628
|
+
return null;
|
|
629
|
+
}
|
|
630
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
631
|
+
}
|
|
632
|
+
function MagicLinkSignIn({
|
|
633
|
+
onSuccess,
|
|
634
|
+
onError,
|
|
635
|
+
className,
|
|
636
|
+
showPasswordSignIn = true
|
|
637
|
+
}) {
|
|
638
|
+
const { client } = useAuthOSContext();
|
|
639
|
+
const [email, setEmail] = react.useState("");
|
|
640
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
641
|
+
const [error, setError] = react.useState(null);
|
|
642
|
+
const [isSent, setIsSent] = react.useState(false);
|
|
643
|
+
const handleSubmit = react.useCallback(
|
|
644
|
+
async (e) => {
|
|
645
|
+
e.preventDefault();
|
|
646
|
+
setError(null);
|
|
647
|
+
setIsLoading(true);
|
|
648
|
+
try {
|
|
649
|
+
await client.magicLinks.request({ email });
|
|
650
|
+
setIsSent(true);
|
|
651
|
+
onSuccess?.();
|
|
652
|
+
} catch (err) {
|
|
653
|
+
const message = err instanceof ssoSdk.SsoApiError ? err.message : "Failed to send magic link";
|
|
654
|
+
setError(message);
|
|
655
|
+
onError?.(err instanceof Error ? err : new Error(message));
|
|
656
|
+
} finally {
|
|
657
|
+
setIsLoading(false);
|
|
658
|
+
}
|
|
659
|
+
},
|
|
660
|
+
[client, email, onSuccess, onError]
|
|
661
|
+
);
|
|
662
|
+
if (isSent) {
|
|
663
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-authos-magic-link": "", "data-state": "sent", children: [
|
|
664
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-success": "", children: [
|
|
665
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Check your email!" }),
|
|
666
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
667
|
+
"We sent a login link to ",
|
|
668
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: email })
|
|
669
|
+
] })
|
|
670
|
+
] }),
|
|
671
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
672
|
+
"button",
|
|
673
|
+
{
|
|
674
|
+
type: "button",
|
|
675
|
+
onClick: () => setIsSent(false),
|
|
676
|
+
"data-authos-back": "",
|
|
677
|
+
children: "Use a different email"
|
|
678
|
+
}
|
|
679
|
+
)
|
|
680
|
+
] });
|
|
681
|
+
}
|
|
682
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-authos-magic-link": "", "data-state": "form", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [
|
|
683
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-field": "email", children: [
|
|
684
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "authos-magic-email", children: "Email" }),
|
|
685
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
686
|
+
"input",
|
|
687
|
+
{
|
|
688
|
+
id: "authos-magic-email",
|
|
689
|
+
type: "email",
|
|
690
|
+
autoComplete: "email",
|
|
691
|
+
value: email,
|
|
692
|
+
onChange: (e) => setEmail(e.target.value),
|
|
693
|
+
placeholder: "Enter your email",
|
|
694
|
+
required: true,
|
|
695
|
+
disabled: isLoading
|
|
696
|
+
}
|
|
697
|
+
)
|
|
698
|
+
] }),
|
|
699
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-authos-error": "", children: error }),
|
|
700
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", disabled: isLoading, "data-authos-submit": "", children: isLoading ? "Sending..." : "Send Magic Link" }),
|
|
701
|
+
showPasswordSignIn && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-authos-signin-prompt": "", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/signin", "data-authos-link": "signin", children: "Sign in with password" }) })
|
|
702
|
+
] }) });
|
|
703
|
+
}
|
|
704
|
+
function PasskeySignIn({
|
|
705
|
+
onSuccess,
|
|
706
|
+
onError,
|
|
707
|
+
className,
|
|
708
|
+
showPasswordSignIn = true
|
|
709
|
+
}) {
|
|
710
|
+
const { client, setUser } = useAuthOSContext();
|
|
711
|
+
const [email, setEmail] = react.useState("");
|
|
712
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
713
|
+
const [error, setError] = react.useState(null);
|
|
714
|
+
const [isSupported, setIsSupported] = react.useState(true);
|
|
715
|
+
react.useEffect(() => {
|
|
716
|
+
setIsSupported(client.passkeys.isSupported());
|
|
717
|
+
}, [client]);
|
|
718
|
+
const handleSubmit = react.useCallback(
|
|
719
|
+
async (e) => {
|
|
720
|
+
e.preventDefault();
|
|
721
|
+
setError(null);
|
|
722
|
+
setIsLoading(true);
|
|
723
|
+
try {
|
|
724
|
+
await client.passkeys.login(email);
|
|
725
|
+
const profile = await client.user.getProfile();
|
|
726
|
+
setUser(profile);
|
|
727
|
+
onSuccess?.();
|
|
728
|
+
} catch (err) {
|
|
729
|
+
const message = err instanceof ssoSdk.SsoApiError ? err.message : err instanceof Error ? err.message : "Passkey authentication failed";
|
|
730
|
+
setError(message);
|
|
731
|
+
onError?.(err instanceof Error ? err : new Error(message));
|
|
732
|
+
} finally {
|
|
733
|
+
setIsLoading(false);
|
|
734
|
+
}
|
|
735
|
+
},
|
|
736
|
+
[client, email, setUser, onSuccess, onError]
|
|
737
|
+
);
|
|
738
|
+
if (!isSupported) {
|
|
739
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-authos-passkey": "", "data-state": "unsupported", children: [
|
|
740
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { "data-authos-error": "", children: "Passkeys are not supported in this browser." }),
|
|
741
|
+
showPasswordSignIn && /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/signin", "data-authos-link": "signin", children: "Sign in with password" })
|
|
742
|
+
] });
|
|
743
|
+
}
|
|
744
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-authos-passkey": "", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [
|
|
745
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-field": "email", children: [
|
|
746
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "authos-passkey-email", children: "Email" }),
|
|
747
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
748
|
+
"input",
|
|
749
|
+
{
|
|
750
|
+
id: "authos-passkey-email",
|
|
751
|
+
type: "email",
|
|
752
|
+
autoComplete: "email webauthn",
|
|
753
|
+
value: email,
|
|
754
|
+
onChange: (e) => setEmail(e.target.value),
|
|
755
|
+
placeholder: "Enter your email",
|
|
756
|
+
required: true,
|
|
757
|
+
disabled: isLoading
|
|
758
|
+
}
|
|
759
|
+
)
|
|
760
|
+
] }),
|
|
761
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-authos-error": "", children: error }),
|
|
762
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", disabled: isLoading, "data-authos-submit": "", children: isLoading ? "Authenticating..." : "Sign in with Passkey" }),
|
|
763
|
+
showPasswordSignIn && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-authos-signin-prompt": "", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/signin", "data-authos-link": "signin", children: "Sign in with password" }) })
|
|
764
|
+
] }) });
|
|
765
|
+
}
|
|
537
766
|
|
|
538
767
|
Object.defineProperty(exports, "AuthErrorCodes", {
|
|
539
768
|
enumerable: true,
|
|
@@ -548,10 +777,15 @@ Object.defineProperty(exports, "SsoClient", {
|
|
|
548
777
|
get: function () { return ssoSdk.SsoClient; }
|
|
549
778
|
});
|
|
550
779
|
exports.AuthOSProvider = AuthOSProvider;
|
|
780
|
+
exports.MagicLinkSignIn = MagicLinkSignIn;
|
|
781
|
+
exports.OAuthButton = OAuthButton;
|
|
551
782
|
exports.OrganizationSwitcher = OrganizationSwitcher;
|
|
783
|
+
exports.PasskeySignIn = PasskeySignIn;
|
|
552
784
|
exports.Protect = Protect;
|
|
553
785
|
exports.SignIn = SignIn;
|
|
554
786
|
exports.SignUp = SignUp;
|
|
787
|
+
exports.SignedIn = SignedIn;
|
|
788
|
+
exports.SignedOut = SignedOut;
|
|
555
789
|
exports.UserButton = UserButton;
|
|
556
790
|
exports.useAllPermissions = useAllPermissions;
|
|
557
791
|
exports.useAnyPermission = useAnyPermission;
|