@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/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 orgResponse = await client.organizations.get(slug);
89
- setOrganization(orgResponse.organization);
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.jsx("div", { className, "data-authos-signin": "", "data-state": "credentials", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleCredentialsSubmit, children: [
209
- /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-field": "email", children: [
210
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "authos-email", children: "Email" }),
211
- /* @__PURE__ */ jsxRuntime.jsx(
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
- id: "authos-password",
231
- type: "password",
232
- autoComplete: "current-password",
233
- value: password,
234
- onChange: (e) => setPassword(e.target.value),
235
- placeholder: "Enter your password",
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
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-authos-error": true, children: error }),
242
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", disabled: isLoading, "data-authos-submit": "", children: isLoading ? "Signing in..." : "Sign In" }),
243
- showForgotPassword && /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/forgot-password", "data-authos-link": "forgot-password", children: "Forgot password?" }),
244
- showSignUp && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-authos-signup-prompt": true, children: [
245
- "Don't have an account? ",
246
- /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/signup", "data-authos-link": "signup", children: "Sign up" })
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;